"""
Sprint 21 Tests: Send button polish — hidden until content, pop-in animation,
icon-only circle design.
"""
import re
import urllib.request
from tests._pytest_port import BASE
def get_text(path):
with urllib.request.urlopen(BASE + path, timeout=10) as r:
return r.read().decode(), r.status
def _find_global_selector(css, selector):
"""Find the GLOBAL (unscoped) occurrence of a selector in style.css.
Skin-scoped rules of the form ``:root[data-skin="..."] .selector{...}``
can appear earlier in the file than the global ``.selector{...}`` rule,
so a naive ``css.find(".selector{")`` would match the wrong block.
This walks every occurrence and returns the first one whose preceding
context on the same line does NOT include ``:root[data-skin=``.
See references/skin-scoped-css-test-trap.md.
"""
pos = 0
while True:
idx = css.find(selector, pos)
if idx == -1:
return -1
line_start = css.rfind('\n', 0, idx) + 1
line_prefix = css[line_start:idx]
# Skip skin-scoped rules. Skins use both `:root[data-skin="x"]` and the
# dark-variant `:root.dark[data-skin="x"]` (#3164 Neon), so match the
# `[data-skin=` marker generically rather than the bare `:root[` form.
if '[data-skin=' not in line_prefix:
return idx
pos = idx + 1
# ── index.html ────────────────────────────────────────────────────────────
def test_send_button_present():
"""btnSend must still exist in the DOM."""
html, status = get_text("/")
assert status == 200
assert 'id="btnSend"' in html
def test_send_button_disabled_by_default():
"""btnSend must start disabled — enabled only when there is content."""
html, _ = get_text("/")
btn_match = re.search(r'id="btnSend"[^>]*>', html)
assert btn_match, "btnSend element not found"
assert 'disabled' in btn_match.group(0)
def test_send_button_no_text_label():
"""Send button must be icon-only — no visible 'Send' text label."""
html, _ = get_text("/")
# Find the full button element (from opening tag to closing tag)
btn_open_end = html.find('>', html.find('id="btnSend"')) + 1
btn_end = html.find('', btn_open_end) + len('')
btn_inner = html[btn_open_end:btn_end]
# Strip SVG content and any remaining tags; check visible text
no_svg = re.sub(r'', '', btn_inner, flags=re.DOTALL)
visible_text = re.sub(r'<[^>]+>', '', no_svg).strip()
assert visible_text == '', f"Send button has visible text: {visible_text!r}"
def test_send_button_has_svg_icon():
"""Send button must have an SVG icon."""
html, _ = get_text("/")
btn_start = html.find('id="btnSend"')
btn_end = html.find('', btn_start) + len('')
btn_html = html[btn_start:btn_end]
assert '