ismail c5f76b3855
Some checks are pending
Build and Push Docker Image / build (push) Waiting to run
updates
2026-05-11 14:45:30 +03:00

155 lines
5.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
verify.py — Playwright封装用于验证claude-design产出的HTML
Usage:
python verify.py path/to/design.html # 基础:打开+截图+抓控制台错误
python verify.py design.html --viewports 1920x1080,375x667 # 多viewport
python verify.py deck.html --slides 10 # 幻灯片逐页截前10张
python verify.py design.html --output ./screenshots/ # 输出目录
python verify.py design.html --show # 非headless打开真实浏览器
依赖:
pip install playwright
playwright install chromium
"""
import argparse
import sys
import os
import time
from pathlib import Path
def parse_viewport(s):
w, h = s.split('x')
return {'width': int(w), 'height': int(h)}
def verify_html(html_path, viewports=None, slides=0, output_dir=None, show=False, wait=2000):
try:
from playwright.sync_api import sync_playwright
except ImportError:
print("ERROR: playwright未安装。")
print("运行: pip install playwright && playwright install chromium")
sys.exit(1)
html_path = Path(html_path).resolve()
if not html_path.exists():
print(f"ERROR: 文件不存在: {html_path}")
sys.exit(1)
if output_dir is None:
output_dir = html_path.parent / 'screenshots'
output_dir = Path(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
file_url = html_path.as_uri()
stem = html_path.stem
if viewports is None:
viewports = [{'width': 1440, 'height': 900}]
console_errors = []
page_errors = []
with sync_playwright() as p:
browser = p.chromium.launch(headless=not show)
for viewport in viewports:
context = browser.new_context(viewport=viewport, device_scale_factor=2)
page = context.new_page()
page.on("console", lambda msg: console_errors.append(f"[{msg.type}] {msg.text}") if msg.type in ("error", "warning") else None)
page.on("pageerror", lambda err: page_errors.append(str(err)))
print(f"\n→ 打开 {file_url} @ {viewport['width']}x{viewport['height']}")
page.goto(file_url, wait_until='networkidle')
page.wait_for_timeout(wait)
if slides > 0:
for i in range(slides):
screenshot_path = output_dir / f"{stem}-slide-{str(i + 1).zfill(2)}.png"
page.screenshot(path=str(screenshot_path), full_page=False)
print(f" ✓ slide {i+1}{screenshot_path.name}")
if i < slides - 1:
page.keyboard.press('ArrowRight')
page.wait_for_timeout(500)
else:
suffix = f"-{viewport['width']}x{viewport['height']}" if len(viewports) > 1 else ""
screenshot_path = output_dir / f"{stem}{suffix}.png"
page.screenshot(path=str(screenshot_path), full_page=False)
print(f" ✓ 截图 → {screenshot_path.name}")
full_path = output_dir / f"{stem}{suffix}-full.png"
page.screenshot(path=str(full_path), full_page=True)
print(f" ✓ 完整页 → {full_path.name}")
if show:
print(" (浏览器窗口保持打开按Enter关闭...)")
input()
context.close()
browser.close()
print("\n" + "=" * 50)
print("验证报告")
print("=" * 50)
if page_errors:
print(f"\n❌ Page Errors ({len(page_errors)}):")
for e in page_errors:
print(f" - {e}")
else:
print("\n✅ 无JavaScript错误")
if console_errors:
print(f"\n⚠️ Console Errors/Warnings ({len(console_errors)}):")
for e in console_errors[:20]:
print(f" - {e}")
if len(console_errors) > 20:
print(f" ... 还有{len(console_errors) - 20}")
else:
print("✅ Console干净")
print(f"\n📸 截图保存至: {output_dir}")
return 0 if not page_errors else 1
def main():
parser = argparse.ArgumentParser(
description="Verify HTML design outputs with Playwright",
formatter_class=argparse.RawDescriptionHelpFormatter,
)
parser.add_argument("html_path", help="HTML file path")
parser.add_argument("--viewports", default="1440x900",
help="逗号分隔的viewport列表格式 WxH默认 1440x900")
parser.add_argument("--slides", type=int, default=0,
help="幻灯片模式截取前N张需要HTML支持ArrowRight翻页")
parser.add_argument("--output", default=None,
help="输出目录默认HTML所在目录的screenshots/")
parser.add_argument("--show", action="store_true",
help="非headless打开真实浏览器窗口")
parser.add_argument("--wait", type=int, default=2000,
help="打开页面后等待的毫秒数默认2000")
args = parser.parse_args()
viewports = [parse_viewport(v) for v in args.viewports.split(",")]
return verify_html(
html_path=args.html_path,
viewports=viewports,
slides=args.slides,
output_dir=args.output,
show=args.show,
wait=args.wait,
)
if __name__ == "__main__":
sys.exit(main())