Files
shopdb-flask/tools/shot.py
cproudlock 7d7862f4b5
Some checks failed
CI / backend (push) Successful in 1m41s
CI / naming (push) Successful in 1s
CI / frontend (push) Successful in 8s
CI / migrations-mysql (push) Failing after 8s
Neutral wording in import docs; portable tool output paths
Import-surface docs and docstrings describe the automation as a
migration script; status-doc references in CHANGELOG/ADR-009/ROADMAP
point at repo files. Screenshot/verify tools write to /tmp/shopdb-shots
(created on import) instead of a machine-specific directory.
2026-07-13 16:23:24 -04:00

59 lines
2.1 KiB
Python

"""Headless-Chromium screenshot helper for the dev UI.
Logs in once via the API, injects the token into localStorage the same way
the auth store does, then screenshots each path passed on the command line.
venv/bin/python tools/shot.py /printers/1 /reports/toner /printers/1/edit
Images land in the scratchpad dir as shot_<sanitised-path>.png.
"""
import os
import sys
import json
import urllib.request
from playwright.sync_api import sync_playwright
UI = "http://localhost:5173"
API = "http://localhost:5001/api"
# creds from env so no real login lands in source; fall back to dev defaults
USERNAME = os.environ.get("SHOT_USERNAME", "270015376")
PASSWORD = os.environ.get("SHOT_PASSWORD", "changeme")
OUTDIR = "/tmp/shopdb-shots"
os.makedirs(OUTDIR, exist_ok=True)
def login():
body = json.dumps({"username": USERNAME, "password": PASSWORD}).encode()
loginrequest = urllib.request.Request(f"{API}/auth/login", data=body,
headers={"Content-Type": "application/json"})
data = json.load(urllib.request.urlopen(loginrequest))["data"]
return data["access_token"], data["refresh_token"], data["user"]
def main(paths):
token, refresh, user = login()
seed = f"""
localStorage.setItem('token', {json.dumps(token)});
localStorage.setItem('refreshToken', {json.dumps(refresh)});
localStorage.setItem('user', {json.dumps(json.dumps(user))});
"""
with sync_playwright() as p:
browser = p.chromium.launch()
context = browser.new_context(viewport={"width": 1400, "height": 1000})
context.add_init_script(seed)
page = context.new_page()
for path in paths:
page.goto(f"{UI}{path}", wait_until="networkidle", timeout=30000)
page.wait_for_timeout(1200) # let supply fetch + render settle
name = "shot_" + (path.strip("/").replace("/", "_") or "home") + ".png"
out = f"{OUTDIR}/{name}"
page.screenshot(path=out, full_page=True)
print(out)
browser.close()
if __name__ == "__main__":
main(sys.argv[1:] or ["/printers/1"])