"""Смоук панели в реальном Chromium: скриншоты + ошибки консоли. python tools/ui_smoke.py [--url http://127.0.0.1:8078/] [--shots data/shots] """ import argparse import asyncio import json import pathlib import sys from playwright.async_api import async_playwright async def run(url, out): out.mkdir(parents=True, exist_ok=True) errors, report = [], {} async with async_playwright() as p: b = await p.chromium.launch() pg = await b.new_page(viewport={"width": 1500, "height": 950}) pg.on("console", lambda m: errors.append([m.type, m.text]) if m.type in ("error",) else None) pg.on("pageerror", lambda e: errors.append(["pageerror", str(e)])) await pg.goto(url, wait_until="domcontentloaded", timeout=30000) await pg.wait_for_selector(".kpi", timeout=20000) await pg.wait_for_timeout(1200) report["title"] = await pg.title() report["nav"] = await pg.locator(".nav-i").count() report["kpi"] = (await pg.locator(".kpi").all_inner_texts())[:4] await pg.screenshot(path=str(out / "v2_overview.png"), full_page=False) await pg.click("[data-nav=feed]") await pg.wait_for_selector("#list .item", timeout=20000) report["feed_rows"] = await pg.locator(".item").count() await pg.screenshot(path=str(out / "v2_feed.png")) await pg.locator(".item").first.click() await pg.wait_for_timeout(1200) report["drawer"] = (await pg.locator("#d-title").inner_text())[:100] await pg.screenshot(path=str(out / "v2_drawer.png")) await pg.keyboard.press("Escape") await pg.click("[data-nav=sources]") await pg.wait_for_timeout(1500) report["src_rows"] = await pg.locator("#src-tbl tbody tr").count() await pg.screenshot(path=str(out / "v2_sources.png")) await pg.click("[data-nav=abuse]") await pg.wait_for_timeout(1500) report["abuse_rows"] = await pg.locator(".item").count() await pg.screenshot(path=str(out / "v2_abuse.png")) await pg.click("[data-nav=runs]") await pg.wait_for_timeout(900) report["run_rows"] = await pg.locator("#r-tbl tbody tr").count() await pg.screenshot(path=str(out / "v2_runs.png")) await pg.click("[data-nav=tg]") await pg.wait_for_timeout(2000) report["tg"] = (await pg.locator(".card").first.inner_text())[:160].replace("\n", " | ") await pg.screenshot(path=str(out / "v2_tg.png")) await pg.click("[data-nav=keys]") await pg.wait_for_timeout(800) report["key_rows"] = await pg.locator("#k-tbl tbody tr").count() await pg.screenshot(path=str(out / "v2_keys.png")) await pg.click("[data-nav=digest]") await pg.wait_for_timeout(500) await pg.click("[data-act=digest]") await pg.wait_for_timeout(6000) report["digest_chars"] = len(await pg.locator("#d-out").inner_text()) await pg.screenshot(path=str(out / "v2_digest.png")) await pg.click("[data-nav=watch]") await pg.wait_for_timeout(600) await pg.screenshot(path=str(out / "v2_watch.png")) # мобильный вид await pg.set_viewport_size({"width": 420, "height": 900}) await pg.click("[data-nav=feed]") await pg.wait_for_timeout(1200) await pg.screenshot(path=str(out / "v2_mobile.png")) await b.close() report["console"] = errors[:12] print(json.dumps(report, ensure_ascii=False, indent=1)) return 0 if not errors else 1 def main(): ap = argparse.ArgumentParser() ap.add_argument("--url", default="http://127.0.0.1:8078/") ap.add_argument("--shots", default="data/shots") a = ap.parse_args() sys.exit(asyncio.run(run(a.url, pathlib.Path(a.shots)))) if __name__ == "__main__": main()