Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
186 lines
5.6 KiB
Python
186 lines
5.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Batch mobile/tablet screenshots with a reused codehelper browser session."""
|
|
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"
|
|
|
|
PAGES = [
|
|
("02-login", "/login", True),
|
|
("03-dashboard", "/dashboard", False),
|
|
("04-settings", "/settings", False),
|
|
("05-billing", "/billing", False),
|
|
("06-support", "/support", False),
|
|
("07-support-new", "/support/new", False),
|
|
("08-admin", "/admin", False),
|
|
("09-admin-billing", "/admin/billing", False),
|
|
("10-admin-support", "/admin/support", False),
|
|
("11-admin-users", "/admin/users", False),
|
|
("12-admin-settings", "/admin/settings", False),
|
|
]
|
|
|
|
|
|
def run(cmd: list[str]) -> subprocess.CompletedProcess[str]:
|
|
print(">", " ".join(cmd[:8]), "...")
|
|
r = subprocess.run(cmd, capture_output=True, text=True)
|
|
if r.stdout:
|
|
print(r.stdout[-2000:] if len(r.stdout) > 2000 else r.stdout)
|
|
if r.stderr:
|
|
print(r.stderr[-2000:] if len(r.stderr) > 2000 else r.stderr, file=sys.stderr)
|
|
return r
|
|
|
|
|
|
def main() -> int:
|
|
OUT.mkdir(parents=True, exist_ok=True)
|
|
login_actions = json.dumps(
|
|
[
|
|
{"action": "wait_hydrate"},
|
|
{
|
|
"action": "fill",
|
|
"selector": "input[type=email],input[name=email],#email",
|
|
"text": "demo@descrybe.local",
|
|
},
|
|
{
|
|
"action": "fill",
|
|
"selector": "input[type=password],input[name=password],#password",
|
|
"text": "DemoPass123!",
|
|
},
|
|
{"action": "click", "selector": "button[type=submit]"},
|
|
{"action": "wait_nav"},
|
|
{"action": "wait_hydrate"},
|
|
{"action": "wait", "ms": 1500},
|
|
# dismiss cookies if present
|
|
{"action": "click", "selector": "button:has-text('Accept all'), [data-testid=cookie-consent-banner] button:nth-of-type(3)"},
|
|
{"action": "wait", "ms": 500},
|
|
]
|
|
)
|
|
|
|
for device in ("mobile", "tablet"):
|
|
session = f"audit-{device}"
|
|
# login once per device
|
|
r = run(
|
|
[
|
|
"codehelper",
|
|
"browser",
|
|
"test",
|
|
f"{BASE}/login",
|
|
"--device",
|
|
device,
|
|
"--format",
|
|
"png",
|
|
"--wait-hydrate",
|
|
"--session",
|
|
session,
|
|
"--session-clear",
|
|
"--actions",
|
|
login_actions,
|
|
"-o",
|
|
str(OUT / f"00-post-login-{device}.png"),
|
|
"--path",
|
|
str(ROOT),
|
|
]
|
|
)
|
|
if r.returncode != 0:
|
|
print(f"login failed for {device}", file=sys.stderr)
|
|
return r.returncode
|
|
|
|
for slug, path, public in PAGES:
|
|
if path == "/login":
|
|
# public unauth shot (separate short session not needed — skip for auth device)
|
|
continue
|
|
actions = json.dumps(
|
|
[
|
|
{"action": "navigate", "url": f"{BASE}{path}"},
|
|
{"action": "wait_hydrate"},
|
|
{"action": "wait", "ms": 1200},
|
|
]
|
|
)
|
|
out = OUT / f"{slug}-{device}.png"
|
|
r = 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={r.returncode} -> {out.exists()}")
|
|
|
|
# nav open on dashboard
|
|
nav_actions = json.dumps(
|
|
[
|
|
{"action": "navigate", "url": f"{BASE}/dashboard"},
|
|
{"action": "wait_hydrate"},
|
|
{"action": "click", "selector": 'button[aria-label="Open navigation"], [data-tour=nav-mobile-toggle]'},
|
|
{"action": "wait", "ms": 800},
|
|
]
|
|
)
|
|
r = run(
|
|
[
|
|
"codehelper",
|
|
"browser",
|
|
"test",
|
|
f"{BASE}/dashboard",
|
|
"--device",
|
|
device,
|
|
"--format",
|
|
"png",
|
|
"--wait-hydrate",
|
|
"--session",
|
|
session,
|
|
"--actions",
|
|
nav_actions,
|
|
"-o",
|
|
str(OUT / f"13-nav-open-{device}.png"),
|
|
"--path",
|
|
str(ROOT),
|
|
]
|
|
)
|
|
print(f"nav-open {device} exit={r.returncode}")
|
|
|
|
# public login (no session)
|
|
for device in ("mobile", "tablet"):
|
|
run(
|
|
[
|
|
"codehelper",
|
|
"browser",
|
|
"test",
|
|
f"{BASE}/login",
|
|
"--device",
|
|
device,
|
|
"--format",
|
|
"png",
|
|
"--wait-hydrate",
|
|
"-o",
|
|
str(OUT / f"02-login-{device}.png"),
|
|
"--path",
|
|
str(ROOT),
|
|
]
|
|
)
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|