215 lines
6.5 KiB
Python
215 lines
6.5 KiB
Python
#!/usr/bin/env python3
|
|||
|
|
"""Re-audit key surfaces after header/consent/support fixes."""
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import json
|
||
|
|
import subprocess
|
||
|
|
import sys
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
ROOT = Path(r"F:\laragon\www\_MY\descrybe-v2")
|
||
|
|
OUT = ROOT / "apps" / "web" / "static" / ".audit"
|
||
|
|
BASE = "http://localhost:28472"
|
||
|
|
CONSENT = json.dumps(
|
||
|
|
{"v": 1, "analytics": False, "marketing": False, "updatedAt": "2026-08-09T00:00:00.000Z"}
|
||
|
|
)
|
||
|
|
|
||
|
|
PAGES = [
|
||
|
|
("r02-login", "/login", False),
|
||
|
|
("r03-dashboard", "/dashboard", True),
|
||
|
|
("r04-settings", "/settings", True),
|
||
|
|
("r05-billing", "/billing", True),
|
||
|
|
("r06-support", "/support", True),
|
||
|
|
("r07-support-new", "/support/new", True),
|
||
|
|
("r08-admin", "/admin", True),
|
||
|
|
("r09-admin-billing", "/admin/billing", True),
|
||
|
|
("r10-admin-support", "/admin/support", True),
|
||
|
|
("r11-admin-users", "/admin/users", True),
|
||
|
|
("r13-nav-open", "/dashboard", True),
|
||
|
|
]
|
||
|
|
|
||
|
|
|
||
|
|
def nav(url: str) -> dict:
|
||
|
|
return {"action": "navigate", "text": url}
|
||
|
|
|
||
|
|
|
||
|
|
def run(cmd: list[str]) -> int:
|
||
|
|
r = subprocess.run(cmd, capture_output=True, text=True)
|
||
|
|
tail = (r.stderr or r.stdout or "")[-500:]
|
||
|
|
if r.returncode != 0:
|
||
|
|
print("FAIL", cmd[3] if len(cmd) > 3 else cmd, r.returncode, tail)
|
||
|
|
return r.returncode
|
||
|
|
|
||
|
|
|
||
|
|
def main() -> int:
|
||
|
|
OUT.mkdir(parents=True, exist_ok=True)
|
||
|
|
consent_action = {
|
||
|
|
"action": "storage_set",
|
||
|
|
"key": "descrybe-cookie-consent",
|
||
|
|
"text": CONSENT,
|
||
|
|
}
|
||
|
|
|
||
|
|
for device in ("mobile", "tablet"):
|
||
|
|
session = f"reaudit-{device}"
|
||
|
|
login = json.dumps(
|
||
|
|
[
|
||
|
|
{"action": "wait_hydrate"},
|
||
|
|
consent_action,
|
||
|
|
nav(f"{BASE}/login"),
|
||
|
|
{"action": "wait_hydrate"},
|
||
|
|
{
|
||
|
|
"action": "fill",
|
||
|
|
"selector": "#email,input[type=email]",
|
||
|
|
"text": "demo@descrybe.local",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"action": "fill",
|
||
|
|
"selector": "#password,input[type=password]",
|
||
|
|
"text": "DemoPass123!",
|
||
|
|
},
|
||
|
|
{"action": "click", "selector": "button[type=submit]"},
|
||
|
|
{"action": "wait_nav"},
|
||
|
|
{"action": "wait_hydrate"},
|
||
|
|
{"action": "wait", "ms": 1500},
|
||
|
|
]
|
||
|
|
)
|
||
|
|
run(
|
||
|
|
[
|
||
|
|
"codehelper",
|
||
|
|
"browser",
|
||
|
|
"test",
|
||
|
|
f"{BASE}/login",
|
||
|
|
"--device",
|
||
|
|
device,
|
||
|
|
"--format",
|
||
|
|
"png",
|
||
|
|
"--wait-hydrate",
|
||
|
|
"--session",
|
||
|
|
session,
|
||
|
|
"--session-clear",
|
||
|
|
"--actions",
|
||
|
|
login,
|
||
|
|
"-o",
|
||
|
|
str(OUT / f"r00-logged-in-{device}.png"),
|
||
|
|
"--path",
|
||
|
|
str(ROOT),
|
||
|
|
]
|
||
|
|
)
|
||
|
|
|
||
|
|
for slug, path, auth in PAGES:
|
||
|
|
if slug == "r02-login":
|
||
|
|
actions = json.dumps(
|
||
|
|
[
|
||
|
|
consent_action,
|
||
|
|
nav(f"{BASE}/login"),
|
||
|
|
{"action": "wait_hydrate"},
|
||
|
|
{"action": "wait", "ms": 600},
|
||
|
|
]
|
||
|
|
)
|
||
|
|
# public: no auth session needed but storage helps
|
||
|
|
run(
|
||
|
|
[
|
||
|
|
"codehelper",
|
||
|
|
"browser",
|
||
|
|
"test",
|
||
|
|
f"{BASE}/login",
|
||
|
|
"--device",
|
||
|
|
device,
|
||
|
|
"--format",
|
||
|
|
"png",
|
||
|
|
"--wait-hydrate",
|
||
|
|
"--actions",
|
||
|
|
actions,
|
||
|
|
"-o",
|
||
|
|
str(OUT / f"{slug}-{device}.png"),
|
||
|
|
"--path",
|
||
|
|
str(ROOT),
|
||
|
|
]
|
||
|
|
)
|
||
|
|
continue
|
||
|
|
|
||
|
|
if slug == "r13-nav-open":
|
||
|
|
actions = json.dumps(
|
||
|
|
[
|
||
|
|
nav(f"{BASE}/dashboard"),
|
||
|
|
{"action": "wait_hydrate"},
|
||
|
|
{
|
||
|
|
"action": "click",
|
||
|
|
"selector": '[data-tour=nav-mobile-toggle],button[aria-label="Open navigation"]',
|
||
|
|
},
|
||
|
|
{"action": "wait", "ms": 800},
|
||
|
|
{"action": "assert", "selector": "#app-sidebar"},
|
||
|
|
]
|
||
|
|
)
|
||
|
|
else:
|
||
|
|
actions = json.dumps(
|
||
|
|
[
|
||
|
|
nav(f"{BASE}{path}"),
|
||
|
|
{"action": "wait_hydrate"},
|
||
|
|
{"action": "wait", "ms": 1800},
|
||
|
|
]
|
||
|
|
)
|
||
|
|
|
||
|
|
out = OUT / f"{slug}-{device}.png"
|
||
|
|
code = run(
|
||
|
|
[
|
||
|
|
"codehelper",
|
||
|
|
"browser",
|
||
|
|
"test",
|
||
|
|
f"{BASE}{path}",
|
||
|
|
"--device",
|
||
|
|
device,
|
||
|
|
"--format",
|
||
|
|
"png",
|
||
|
|
"--wait-hydrate",
|
||
|
|
"--session",
|
||
|
|
session,
|
||
|
|
"--actions",
|
||
|
|
actions,
|
||
|
|
"-o",
|
||
|
|
str(out),
|
||
|
|
"--path",
|
||
|
|
str(ROOT),
|
||
|
|
"--snapshot",
|
||
|
|
]
|
||
|
|
)
|
||
|
|
print(f"{slug}-{device}: exit={code} size={out.stat().st_size if out.exists() else 0}")
|
||
|
|
|
||
|
|
# FAB still present + z-layer not covered by assert; snapshot check
|
||
|
|
fab = json.dumps(
|
||
|
|
[
|
||
|
|
nav(f"{BASE}/dashboard"),
|
||
|
|
{"action": "wait_hydrate"},
|
||
|
|
{"action": "wait", "ms": 800},
|
||
|
|
{"action": "assert", "selector": '[data-testid=assistant-fab],[data-tour=assistant-fab]'},
|
||
|
|
]
|
||
|
|
)
|
||
|
|
code = run(
|
||
|
|
[
|
||
|
|
"codehelper",
|
||
|
|
"browser",
|
||
|
|
"test",
|
||
|
|
f"{BASE}/dashboard",
|
||
|
|
"--device",
|
||
|
|
device,
|
||
|
|
"--format",
|
||
|
|
"png",
|
||
|
|
"--wait-hydrate",
|
||
|
|
"--session",
|
||
|
|
session,
|
||
|
|
"--actions",
|
||
|
|
fab,
|
||
|
|
"-o",
|
||
|
|
str(OUT / f"r14-fab-{device}.png"),
|
||
|
|
"--path",
|
||
|
|
str(ROOT),
|
||
|
|
]
|
||
|
|
)
|
||
|
|
print(f"fab-{device}: exit={code}")
|
||
|
|
|
||
|
|
return 0
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
raise SystemExit(main())
|