To test a local web application, write a native Python Playwright script.
Available Helper Scripts:
scripts/with_server.py- Manage server lifecycle (supports multiple servers)
Be sure to first use --help to run the script to view usage. Do not read the source code until you have first tried running the script directly and confirmed that customization is necessary. These scripts can be very large and will pollute your context window. They are designed to be called directly as black-box scripts, not to be brought into your context window.
Decision Tree: Choosing Your Approach
用户任务 → 是静态 HTML 吗?
├─ 是 → 直接读取 HTML 文件以识别选择器
│ ├─ 成功 → 使用这些选择器编写 Playwright 脚本
│ └─ 失败/不完整 → 按动态应用处理(见下)
│
└─ 否(动态 Web 应用) → 服务器是否已在运行?
├─ 否 → 运行:python scripts/with_server.py --help
│ 然后使用该助手 + 编写精简的 Playwright 脚本
│
└─ 是 → 先侦察,后操作:
1. 导航并等待 networkidle
2. 截图或检查 DOM
3. 从渲染状态中识别选择器
4. 使用发现的选择器执行操作
Example: Using with_server.py
To start a server, first run --help, then use the helper:
Single server:
python scripts/with_server.py --server "npm run dev" --port 5173 -- python your_automation.py
Multiple servers (e.g., backend + frontend):
python scripts/with_server.py \
--server "cd backend && python server.py" --port 3000 \
--server "cd frontend && npm run dev" --port 5173 \
-- python your_automation.py
When writing automation scripts, include only the Playwright logic (servers are managed automatically by the helper):
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True) # 始终以无头模式启动 chromium
page = browser.new_page()
page.goto('http://localhost:5173') # 服务器已运行且就绪
page.wait_for_load_state('networkidle') # 关键:等待 JS 执行
# ... 你的自动化逻辑
browser.close()
"Recon first, then act" pattern
-
Inspect the rendered DOM:
page.screenshot(path='/tmp/inspect.png', full_page=True) content = page.content() page.locator('button').all() -
Based on the inspection resultsIdentify selectors
-
Use the discovered selectorsPerform actions
Common Pitfalls
❌ In dynamic applications, do not inspect the DOM before waiting for networkidle ✅ Before inspecting, wait for page.wait_for_load_state('networkidle')
Best Practices
- Use bundled scripts as black boxes - When handling tasks, consider whether
scripts/already has a script available. These scripts can reliably handle common and complex workflows without polluting your context window. Use--helpto view usage, then call directly. - Use for synchronous scripts
sync_playwright() - Always close the browser when done
- Use descriptive selectors:
text=、role=, CSS selectors, or IDs - Add appropriate waits:
page.wait_for_selector()orpage.wait_for_timeout()
Reference Files
- examples/ - Examples showing common patterns:
element_discovery.py- Discover buttons, links, and input fields on a pagestatic_html_automation.py- Manipulate local HTML using file:// URLsconsole_logging.py- Capture console logs during automation