"""The mobile-layout bundle (goal 41 T12): the server-side invariants of the mobile containment contract (docs/spry-conversion.md), plus — when chromium is present — the full browser audit (test/mobile_audit) that renders every route at 360/768/1280 and fails on any horizontal overflow or dialog-fit failure. CI without chromium: the browser part skips gracefully (print + pass a SKIP marker, never a FAIL) unless T12MOBILE_BROWSER=1 demands it.""" import os import re import sys sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from harness import * # noqa: F401,F403 WIDE_TABLE_RE = re.compile(r"]*>", re.IGNORECASE) # Every page that ships a in its compiled markup; the audit's # route set mirrors this list. PAGES_WITH_TABLES = ("/tasks", "/goals", "/projects", "/chats", "/saddles", "/users") def run(ctx): admin = ctx.auth print("== every wide table sits in .table-wrap ==") for uri in PAGES_WITH_TABLES: page = http_get_page(admin, uri) tables = WIDE_TABLE_RE.findall(page) check(bool(tables), "%s renders at least one table" % uri) for match in WIDE_TABLE_RE.finditer(page): before = page[:match.start()] # the NEAREST enclosing div before the table must be the # wrap (allow attributes between class names) opening = before.rfind("= 1000px in markup" % uri) print("== dialogs use the fitting width grammar ==") # spry's dialog rule is width: min(92vw, rem); the app never # overrides it with a fixed width. Assert the dialog markup keeps # the shared classes and app.css carries no fixed dialog width. status, css = http("GET", "/_statum/resource/app.css") check(status == 200, "app.css served") fixed = [line for line in css.splitlines() if "dialog" in line and re.search(r"width:\s*\d", line)] check(not fixed, "app.css sets no fixed dialog width: %s" % fixed[:2]) for uri in ("/tasks", "/goals", "/rules", "/projects"): page = http_get_page(admin, uri) for dialog_id in re.findall(r']*id="([^"]+)"', page): check(bool(dialog_id), "dialog %s has an id" % dialog_id) check('class="dialog-sm"' in page or "