fix(desk): the heid code-review and bug-hunt panels on r2b merge 2, folded
The bug hunt (4/4) and code review (4/4) were both clean on mechanism.
Their shared catch was the one-sided minute check.
Dates:
- The date filters never raise. One clock outside the calendar's range
500'd the Desk for every booth, because every row renders in one
response. An unrenderable date now renders nothing.
- "Updated" shows whenever it differs from "created" by a minute or more,
either way. Copied content is often older than its folder.
- A clock ahead of now shows its date, never "just now".
- A day is 24h ("1d ago" never appeared).
The row:
- The controls are last in the markup, so the booth's name comes first in
tab order and wipe last. The cluster is placed over the strip from the
row's box.
The theme:
- A choice made in one tab moves the Booth's other open tabs.
- The theme mark goes only on ask fragments the embed mounted.
Tests, strengthened after the code review:
- the pill is visible at rest;
- keyboard focus reveals the controls;
- the controls act with scripts off;
- Reveal all reaches the doc page;
- the high-contrast check reads tokens that actually differ;
- the art-light extras are written from SVOS, not derived from the
copies;
- two overstated mutation rows are replaced (one was a runtime no-op, one
went red through a syntax error).
Contract amended.
r2b.toml 55/55 proved. 799 passed.
This commit is contained in:
+123
-1
@@ -898,11 +898,19 @@ def test_a_forced_theme_follows_high_contrast(browser, live):
|
||||
cdp.send("Emulation.setEmulatedMedia", {"features": [
|
||||
{"name": "prefers-contrast", "value": "more"},
|
||||
{"name": "prefers-color-scheme", "value": os_scheme}]})
|
||||
got[(os_scheme, forced)] = page.evaluate(_VAR, "--surface-card")
|
||||
# tokens that DIFFER between a theme and its high-contrast variant
|
||||
# (--surface-card does not, so reading it saw nothing — heid, 2/4)
|
||||
got[(os_scheme, forced)] = (page.evaluate(_VAR, "--text-faint"), page.evaluate(_VAR, "--border-default"))
|
||||
if forced is None and os_scheme == "dark":
|
||||
cdp.send("Emulation.setEmulatedMedia", {"features": [
|
||||
{"name": "prefers-contrast", "value": "no-preference"},
|
||||
{"name": "prefers-color-scheme", "value": os_scheme}]})
|
||||
got["dark, no contrast"] = (page.evaluate(_VAR, "--text-faint"), page.evaluate(_VAR, "--border-default"))
|
||||
ctx.close()
|
||||
assert got[("light", "dark")] == got[("dark", None)] == got[("dark", "dark")]
|
||||
assert got[("dark", "light")] == got[("light", None)] == got[("light", "light")]
|
||||
assert got[("dark", None)] != got[("light", None)]
|
||||
assert got[("dark", None)] != got["dark, no contrast"] # high contrast really applied
|
||||
|
||||
|
||||
def test_the_theme_toggle_never_shows_without_js_and_a_storage_failure_still_applies(browser, live):
|
||||
@@ -961,3 +969,117 @@ def test_a_forced_theme_reaches_the_ask_chrome_inside_a_verbatim_page(browser, l
|
||||
ctx.close()
|
||||
assert os_dark == "#b2cd12" and forced_light == "#586519" and after_reload == "#586519", (os_dark, forced_light, after_reload)
|
||||
assert host_html is None
|
||||
|
||||
|
||||
def test_a_rows_booth_name_comes_before_its_controls_in_tab_order(browser, live):
|
||||
"""heid bug-hunt (groa): the cluster sat before the text in the markup, so
|
||||
the first tab stop on a row was zip, then keep, then WIPE — before the booth
|
||||
it acts on — and with scripts off, wipe submits with no confirm. The name
|
||||
is first; the controls follow, wipe last."""
|
||||
base, root = live
|
||||
_two_rows(root)
|
||||
ctx = browser.new_context(viewport={"width": 390, "height": 844}, has_touch=True, is_mobile=True)
|
||||
page = ctx.new_page()
|
||||
page.goto(f"{base}/", wait_until="networkidle")
|
||||
order = page.evaluate("""() => { const row = document.querySelector('.desk-row[data-booth="loose"]');
|
||||
return [...row.querySelectorAll('a[href], button')].filter(e => e.tabIndex >= 0)
|
||||
.map(e => e.classList.contains('desk-title') ? 'title' : e.closest('form') ? e.closest('form').className.split(' ')[0] : e.className.split(' ')[0]); }""")
|
||||
ctx.close()
|
||||
assert order == ["title", "dl-link", "keepit", "wipe"], order
|
||||
|
||||
|
||||
def test_a_theme_chosen_in_one_tab_moves_the_others(browser, live):
|
||||
"""heid bug-hunt (groa): the ask chrome followed a choice made in another
|
||||
tab, but the Booth's own open pages did not until reloaded."""
|
||||
base, root = live
|
||||
_set(root, 1)
|
||||
ctx = browser.new_context(color_scheme="dark")
|
||||
a, b = ctx.new_page(), ctx.new_page()
|
||||
a.goto(f"{base}/", wait_until="networkidle")
|
||||
b.goto(f"{base}/b/g/", wait_until="networkidle")
|
||||
a.locator('.theme [data-theme-choice="light"]').click()
|
||||
b.wait_for_function("document.documentElement.getAttribute('data-theme') === 'light'", timeout=5000)
|
||||
pressed = b.locator('.theme [aria-pressed="true"]').get_attribute("data-theme-choice")
|
||||
a.locator('.theme [data-theme-choice="system"]').click()
|
||||
b.wait_for_function("!document.documentElement.hasAttribute('data-theme')", timeout=5000)
|
||||
ctx.close()
|
||||
assert pressed == "light"
|
||||
|
||||
|
||||
def test_the_theme_marks_only_the_ask_fragments_we_mounted(browser, live):
|
||||
"""heid bug-hunt (regin): the theme mark went on every `.bk-ask` in the
|
||||
page, the author's own included. Only fragments the embed mounted."""
|
||||
from booth.marks import declare_pick
|
||||
base, root = live
|
||||
b = root / "rep"
|
||||
b.mkdir()
|
||||
declare_pick(b, "winner", {"prompt": "Which?", "options": ["A", "B"]})
|
||||
(b / "index.html").write_text('<!doctype html><title>r</title><body><div class="bk-ask" id="authors">mine</div>'
|
||||
'<script src="/_booth/embed.js" defer></script></body>')
|
||||
ctx = browser.new_context()
|
||||
page = ctx.new_page()
|
||||
page.add_init_script("try { localStorage.setItem('booth.theme', 'light'); } catch (e) {}")
|
||||
page.goto(f"{base}/b/rep/", wait_until="networkidle")
|
||||
page.wait_for_selector(".bk-ask:not(#authors)")
|
||||
got = page.evaluate("""() => [document.getElementById('authors').getAttribute('data-bk-theme'),
|
||||
[...document.querySelectorAll('.bk-ask:not(#authors)')].map(e => e.getAttribute('data-bk-theme'))]""")
|
||||
ctx.close()
|
||||
assert got[0] is None and got[1] and all(t == "light" for t in got[1]), got
|
||||
|
||||
|
||||
def test_the_pill_shows_at_rest_and_focus_reveals_the_controls(browser, live):
|
||||
"""heid code-review: the pill's "visible with no hover" was never asserted
|
||||
(an opacity-0 box keeps its geometry), and nothing pinned KEYBOARD focus
|
||||
revealing the controls — `:focus-within` could go alone."""
|
||||
base, root = live
|
||||
_two_rows(root)
|
||||
page = browser.new_page(viewport={"width": 1400, "height": 900})
|
||||
page.goto(f"{base}/", wait_until="networkidle")
|
||||
page.mouse.move(0, 0)
|
||||
row = page.locator('.desk-row[data-booth="loose"]')
|
||||
pill = row.locator(".life").evaluate("e => [getComputedStyle(e).opacity, getComputedStyle(e).visibility, e.offsetWidth > 0]")
|
||||
row.locator(".desk-acts .dl-link").focus()
|
||||
page.wait_for_timeout(350)
|
||||
focused = row.locator(".desk-acts").evaluate("a => [getComputedStyle(a).opacity, getComputedStyle(a).pointerEvents]")
|
||||
page.close()
|
||||
assert pill == ["1", "visible", True], pill
|
||||
assert focused == ["1", "auto"], focused
|
||||
|
||||
|
||||
def test_with_scripts_off_a_rows_controls_still_act(browser, live):
|
||||
"""r2b INV-2, never exercised with JS actually off (heid code-review): the
|
||||
hover reveal is CSS, and keep is a plain form."""
|
||||
base, root = live
|
||||
_two_rows(root)
|
||||
ctx = browser.new_context(java_script_enabled=False, viewport={"width": 1400, "height": 900})
|
||||
page = ctx.new_page()
|
||||
page.goto(f"{base}/", wait_until="networkidle")
|
||||
row = page.locator('.desk-row[data-booth="loose"]')
|
||||
row.hover()
|
||||
page.wait_for_timeout(350)
|
||||
with page.expect_navigation():
|
||||
row.locator(".desk-acts form.keepit button").click()
|
||||
ctx.close()
|
||||
assert (root / "loose" / ".forever").exists()
|
||||
|
||||
|
||||
def test_reveal_all_lifts_the_doc_page_it_reaches(browser, live):
|
||||
"""heid code-review (regin, seat-settled): the doc page carries the rules,
|
||||
but no test turned Reveal all on and looked there."""
|
||||
from booth.app import set_blurred
|
||||
base, root = live
|
||||
b = root / "g"
|
||||
b.mkdir()
|
||||
(b / "a.png").write_bytes(PNG)
|
||||
(b / "n.md").write_text("# secret\n\nbody")
|
||||
set_blurred(b, "a.png", True)
|
||||
set_blurred(b, "n.md", True)
|
||||
page = browser.new_page(viewport={"width": 1200, "height": 800})
|
||||
page.goto(f"{base}/b/g/", wait_until="networkidle")
|
||||
page.locator("[data-reveal-all]").click()
|
||||
page.goto(f"{base}/b/g/view?f=n.md", wait_until="networkidle")
|
||||
_settle(page)
|
||||
got = [page.evaluate(_FILTER, "#docbody .markdown-body, #docbody .textview"),
|
||||
page.evaluate("getComputedStyle(document.getElementById('docreveal')).display")]
|
||||
page.close()
|
||||
assert got == ["none", "none"], got
|
||||
|
||||
Reference in New Issue
Block a user