"""UX-13 P5: the DOCS screenshots of the new screens, taken from the real page. Run by tools/ux13_screenshots.sh, which serves tools/ux13_demo.py fixtures and runs this inside the Playwright image. Each shot fails the run on a page error, so a broken screen is never pictured. python3 ux13_screenshots.py OUT_DIR # DEMO_ = the fixture's URL The battery-mode screens (P3) are not built, so there is no shot of them: DOCS.md says so instead of showing a mock-up. """ import os import sys from playwright.sync_api import sync_playwright OUT = sys.argv[1] DESKTOP = {"width": 1000, "height": 900} PHONE = {"width": 390, "height": 844} def url(state): return os.environ[f"DEMO_{state.upper()}"] def shot(browser, name, state, route, *, lang="en-GB", size=DESKTOP, full=True, act=None, only=None): ctx = browser.new_context(locale=lang, viewport=size, color_scheme="light", reduced_motion="reduce") page = ctx.new_page() errors = [] page.on("pageerror", lambda e: errors.append(str(e))) page.goto(url(state) + route) page.wait_for_load_state("networkidle") page.wait_for_timeout(1500) # the first /status and checks if act: act(page) page.wait_for_timeout(1500) # the debounced start checks path = os.path.join(OUT, name + ".png") if only: page.locator(only).screenshot(path=path) else: page.screenshot(path=path, full_page=full) ctx.close() if errors: raise SystemExit(f"{name}: page errors {errors}") print(f" {name}.png") def open_tariff(page): page.locator("details.grp[data-g=tariff] > summary").click() page.locator("details.grp[data-g=meter] > summary").click() # close it # The fixture site is on a dynamic contract: its fallback gets windows. page.get_by_role("radiogroup", name="Price when the feed is down") \ .get_by_role("radio", name="Other time windows").click() def windows(page, overlap=False): open_tariff(page) add = page.get_by_role("button", name="+ Add a time window") rows = (("07:00", "23:00" if overlap else "22:00", "mon-fri", "0.34"), ("22:00", "07:00", "mon-fri", "0.26"), ("00:00", "24:00", "sat,sun", "0.24")) for i, (a, b, days, price) in enumerate(rows, start=1): add.click() page.get_by_label(f"Window {i}, From").fill(a) page.get_by_label(f"Window {i}, To").fill(b) page.get_by_label(f"Window {i}, Days").select_option(days) page.get_by_label(f"Window {i}, Price").fill(price) page.locator("[data-key='ui.periods']").scroll_into_view_if_needed() def main(): os.makedirs(OUT, exist_ok=True) with sync_playwright() as p: b = p.chromium.launch() shot(b, "home-running", "running", "#home") shot(b, "home-running-nl", "running", "#home", lang="nl-BE") shot(b, "home-shadow", "shadow", "#home") shot(b, "home-phone", "running", "#home", size=PHONE) shot(b, "home-setup-only", "setup", "#home", full=False) shot(b, "settings-installer", "running", "#settings") shot(b, "settings-installer-nl", "running", "#settings", lang="nl-BE") tariff = "details.grp[data-g=tariff]" shot(b, "settings-time-windows", "running", "#settings", act=windows, only=tariff) shot(b, "settings-time-windows-overlap", "running", "#settings", act=lambda page: windows(page, overlap=True), only=tariff) shot(b, "setup-step-1", "new", "#setup") shot(b, "setup-step-1-nl", "new", "#setup", lang="nl-BE") b.close() if __name__ == "__main__": main()