#!/usr/bin/env python3 """Is every help-tip reachable by keyboard and by touch? — C1 + S8, T9.5. The badges were elements whose :focus CSS was dead code (no tabindex) and whose touch path did not exist - on tablets, Field View's surface. Now the component upgrades every badge to a button at load, and one viewport-clamped role=tooltip bubble serves them all. This probe drives a badge with REAL key events and a tap at 390px, then greps the app-wide metrics the audit document cites. Exit 0 all passed, 1 a failure, 2 could not run. """ import io import json import os import re import sys import tempfile import time sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import cdp # noqa: E402 from browser_check import seed, start_server, chk, _PASS, _FAIL # noqa: E402 from sections_check import set_sop # noqa: E402 from stepper_check import dismiss_dialogs # noqa: E402 ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) HTML = os.path.join(ROOT, "html") def ascii_(v, n=280): return re.sub(r"\s+", " ", str(v)).encode("ascii", "replace").decode()[:n] def settle(seconds=0.5): time.sleep(seconds) def strip_js(src): src = re.sub(r"/\*.*?\*/", "", src, flags=re.S) return "\n".join(re.sub(r"(?]*\bonclick=", code)) for m in re.finditer(r"outline:\s*none", code): # The replacement can sit in the rule ABOVE (wp-chrome's search shell # rings on :focus-within, and ringing input + shell would draw two), # so the window looks both ways. ctx = code[max(0, m.start() - 400):m.start() + 260] tail = ctx[ctx.find("outline:") + 12:] if ("outline" not in tail and "box-shadow" not in ctx and "focus-within" not in ctx and "border" not in tail): outline_bad.append(name) chk("div/span click handlers app-wide: 0 (baseline 12/2)", divspan == 0, divspan) chk("outline:none without a replacement: 0", not outline_bad, outline_bad[:4]) chk("the audit document exists with the per-page table", "## Per-page results" in io.open(os.path.join(ROOT, "docs", "reference", "accessibility-audit.md"), encoding="utf-8").read()) tmpdir = tempfile.mkdtemp(prefix="wpsuite-tip-") db_path = os.path.join(tmpdir, "check.db") server = None browser = None try: tok = seed(db_path) set_sop(db_path, {}) port = cdp.free_port() base = "http://127.0.0.1:%d" % port server = start_server(port, db_path) browser = cdp.Browser(exe) page = browser.page() page.clear_cookies() page.set_cookie("wp_session", tok["root"]) page.viewport(390, 844, mobile=True) page.goto(base + "/wp-creation-index.html?project=projA") dismiss_dialogs(page) chk("the creator boots at 390px", wait_creator(page)) settle(1.8) # ── 2. every badge is a real button ────────────────────────────────── print("\n2. the component, upgraded") counts = json.loads(page.eval("""JSON.stringify({ total: document.querySelectorAll('.help-tip').length, buttons: document.querySelectorAll('button.help-tip').length, spans: document.querySelectorAll('span.help-tip').length, })""")) chk("every help-tip on the page is a