I couldn't save the script to disk because the Write tool is disabled in this session. The full script is below, so you can save it as smoke_test.py yourself. I haven't run it.
import sys
from playwright.sync_api import sync_playwright, TimeoutError as PlaywrightTimeout
URL = "http://localhost:5173"
BUTTON_NAME = "Save profile"
SCREENSHOT_PATH = "smoke_test.png"
console_messages = []
def main() -> int:
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
# Register listeners before navigation so early messages are captured
page.on("console", lambda msg: console_messages.append((msg.type, msg.text)))
page.on("pageerror", lambda err: console_messages.append(("pageerror", str(err))))
exit_code = 0
try:
page.goto(URL)
# Critical for dynamic apps: wait for JS to render and network to settle
page.wait_for_load_state("networkidle")
# Discover visible buttons
buttons = [b for b in page.get_by_role("button").all() if b.is_visible()]
print(f"Found {len(buttons)} visible button(s):")
for i, b in enumerate(buttons):
label = (b.inner_text() or b.get_attribute("aria-label") or "").strip()
print(f" [{i}] {label!r}")
# Click by accessible name
target = page.get_by_role("button", name=BUTTON_NAME, exact=True)
target.wait_for(state="visible", timeout=5000)
target.click()
page.wait_for_load_state("networkidle")
print(f"Clicked button {BUTTON_NAME!r}")
except PlaywrightTimeout as e:
print(f"FAIL: button {BUTTON_NAME!r} not found/visible: {e}")
exit_code = 1
finally:
page.screenshot(path=SCREENSHOT_PATH, full_page=True)
print(f"Screenshot saved to {SCREENSHOT_PATH}")
print(f"\nConsole messages ({len(console_messages)}):")
for kind, text in console_messages:
print(f" [{kind}] {text}")
if any(k in ("error", "pageerror") for k, _ in console_messages):
print("WARNING: console errors detected")
exit_code = exit_code or 1
browser.close()
return exit_code
if __name__ == "__main__":
sys.exit(main())
Run it with python smoke_test.py. Your server is already up, so you don't need with_server.py. If you haven't installed Playwright yet, run pip install playwright && playwright install chromium first.
What it does, in order
- It registers the
consoleandpageerrorlisteners beforegoto, so messages logged during the initial render are captured. - It waits for
networkidleso the dynamic page has finished rendering before it inspects anything. - It lists every visible button, using
get_by_role("button")plus anis_visible()filter. - It clicks the button named "Save profile", waits for the network to settle again, and prints the captured console messages.
- It saves a full-page screenshot to
smoke_test.png. This happens infinally, so you get a screenshot even if the click fails.
Assumptions about selectors
- Role and name: I used
get_by_role("button", name="Save profile", exact=True). This assumes the control is a real<button>,<input type="submit">, or an element withrole="button". Its accessible name must be exactly "Save profile", whether from its text,aria-label, or an associated label. It also keeps working if CSS classes change. - A
<div onClick>won't match: If "Save profile" is a styled<div>withoutrole="button", the lookup will time out. In that case, switch topage.get_by_text("Save profile")or add adata-testidand useget_by_test_id. - Exact match:
exact=Trueis a case-sensitive, full-string match. Remove it if the label might change, for example to "Save profile…" or "Saving…". - One match only: Playwright's strict mode raises an error if more than one button matches. If the page has duplicates, such as one per tab, scope the lookup, for example
page.locator("form").get_by_role(...). - Idle waiting:
networkidlecan hang if the app polls, uses websockets, or runs HMR traffic. If that happens, wait for a specific element instead of network idle. - Failure condition: The script exits non-zero if the button isn't found or if any console error or uncaught page error appears.
Real run recorded with claude-code / claude-sonnet-5-5. Output is shown verbatim, unmodified.
하는 일
네이티브 Python Playwright 스크립트로 로컬 웹 애플리케이션을 테스트하도록 안내합니다.
작동 방식
- 애플리케이션이 정적인지 동적인지 판단합니다.
- 렌더링된 DOM을 검사하기 전에 동적 페이지가 유휴 상태가 될 때까지 기다립니다.
- 보이는 선택자, 스크린샷, 브라우저 로그를 이용해 UI 동작을 자동화하고 진단합니다.
적합한 경우
스모크 테스트, UI 회귀 조사, 선택자 탐색, 스크린샷, 콘솔 로그 수집.
Python 예제와 서버 수명 주기 도우미를 포함합니다. 로컬 URL 접근, 브라우저 자동화 실행, 스크린샷 또는 로그 쓰기, 로컬 개발 서버로 제공된 shell 명령 실행을 할 수 있습니다. 자격 증명은 포함하지 않으며, 실행 전에 명령과 경로를 검토해야 합니다.