#!/usr/bin/env python3 # Covers frontend smoke flows: login, chart browser rendering, launch modal, # registry/cluster configuration pages, instances page, and mobile layout sanity. import os from pathlib import Path from playwright.sync_api import expect, sync_playwright BASE_URL = os.environ.get("FRONTEND_URL", "http://localhost:18080") ADMIN_USER = os.environ.get("ADMIN_USER", "admin") ADMIN_PASS = os.environ["ADMIN_PASS"] def login(page): page.goto(BASE_URL, wait_until="networkidle") if page.locator("input[type='password']").count() == 0: return text_inputs = page.locator("input:not([type='password'])") text_inputs.first.fill(ADMIN_USER) page.locator("input[type='password']").first.fill(ADMIN_PASS) page.get_by_role("button").filter(has_text="Login").last.click() page.wait_for_url("**/home", timeout=15000) page.wait_for_load_state("networkidle") expect(page.locator("body")).not_to_contain_text("Login failed") def screenshot(page, name): page.screenshot(path=f"/tmp/{name}.png", full_page=True) def click_nav(page, name, index=0): item = page.get_by_role("button", name=name).nth(index) try: item.click(timeout=5000) except Exception: item.evaluate("element => element.click()") page.wait_for_load_state("networkidle") page.wait_for_timeout(500) def record_console_error(errors, msg): text = msg.text ignored = [ "Failed to load resource: the server responded with a status of 404", "[LaunchModal] Failed to load values schema", ] if any(item in text for item in ignored): return errors.append(text) with sync_playwright() as p: browser = p.chromium.launch(headless=True) page = browser.new_page(viewport={"width": 1440, "height": 950}) errors = [] page.on("pageerror", lambda exc: errors.append(str(exc))) page.on("console", lambda msg: record_console_error(errors, msg) if msg.type == "error" else None) login(page) click_nav(page, "Launch Instance") expect(page.get_by_text("Chart Browser")).to_be_visible(timeout=15000) screenshot(page, "ocdp-chart-browser-desktop") if page.get_by_role("button", name="Launch").count() > 0: page.get_by_role("button", name="Launch").first.click() if page.get_by_role("button", name="Cancel").count() > 0: expect(page.get_by_role("heading", name="Launch Instance")).to_be_visible(timeout=10000) screenshot(page, "ocdp-launch-modal") page.get_by_role("button", name="Cancel").click() click_nav(page, "Registries") expect(page.locator("body")).to_contain_text("Registry") screenshot(page, "ocdp-registry-config") click_nav(page, "Clusters") expect(page.locator("body")).to_contain_text("Cluster") screenshot(page, "ocdp-cluster-config") click_nav(page, "Instances") expect(page.locator("body")).to_contain_text("Instance") screenshot(page, "ocdp-instances") mobile = browser.new_page(viewport={"width": 390, "height": 844}, is_mobile=True) login(mobile) click_nav(mobile, "Launch Instance") expect(mobile.get_by_text("Chart Browser")).to_be_visible(timeout=15000) screenshot(mobile, "ocdp-chart-browser-mobile") overflow = mobile.evaluate("document.documentElement.scrollWidth > document.documentElement.clientWidth + 2") assert not overflow, "mobile page has horizontal overflow" browser.close() if errors: raise AssertionError("\\n".join(errors[:10]))