tools/overlays_check.py
Rama main · réplica de lectura del repositorio original.
#!/usr/bin/env python3
"""Every modal sheet is a real centered overlay — not an unstyled block in flow.
inbox, diff, board and broadcast are dialogs that open over the app. They each
need the overlay rule (`position: fixed`, a scrim, centred) that #settings and
#keys have. They once shipped without it and rendered as full-width unstyled
strips at the foot of the page — the board fell entirely below the fold — yet
the per-feature Playwright checks passed, because Playwright drives an element
by DOM ref no matter where it renders. This asserts the CSS itself, so that
class of "the button does nothing / breaks the UI" bug cannot come back unseen.
Needs the Playwright venv:
~/.cache/clique-visual/bin/python tools/overlays_check.py
Exit status is 0 on pass, 1 on fail.
"""
from __future__ import annotations
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
import tools.visual_check as vc
from clique.auth import COOKIE_NAME, Auth
SHEETS = ("inbox", "diff", "board", "broadcast")
def main() -> int:
from playwright.sync_api import sync_playwright
panel = vc._own_panel()
res: dict[str, object] = {}
try:
auth = Auth(vc.PASSWORD, vc.SANDBOX / "secret")
vc._scratch_session()
with sync_playwright() as play:
browser = play.chromium.launch()
ctx = browser.new_context(viewport={"width": 1400, "height": 900})
ctx.add_init_script("try { localStorage.setItem('clique.gpu','0'); } catch (e) {}")
ctx.add_cookies(
[{"name": COOKIE_NAME, "value": auth.issue(), "domain": "127.0.0.1", "path": "/"}]
)
page = ctx.new_page()
page.goto(vc.BASE, wait_until="networkidle")
page.wait_for_timeout(800)
probe = page.evaluate(
"""() => {
const out = {};
for (const id of %s) {
const el = document.getElementById(id);
if (!el) { out[id] = { missing: true }; continue; }
el.hidden = false;
const cs = getComputedStyle(el);
const sheet = el.querySelector('.sheet');
const sr = sheet ? sheet.getBoundingClientRect() : null;
out[id] = {
position: cs.position,
scrim: cs.backgroundColor,
centered: sr ? (sr.top > 0 && sr.bottom < window.innerHeight + 1) : false,
};
el.hidden = true;
}
return out;
}"""
% ("['" + "','".join(SHEETS) + "']")
)
finally:
panel.terminate()
for sid in SHEETS:
info = probe.get(sid, {"missing": True})
ok = (
not info.get("missing")
and info.get("position") == "fixed"
and info.get("scrim") not in ("rgba(0, 0, 0, 0)", "transparent")
and info.get("centered")
)
res[sid] = ok
print(
f" {'ok ' if ok else 'FAIL'} #{sid} is a fixed, scrimmed, on-screen overlay: {info}"
)
passed = all(res.values())
print("overlays_check:", "PASS" if passed else "FAIL")
return 0 if passed else 1
if __name__ == "__main__":
sys.exit(main())