# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview This is a Python automation project using Playwright to interact with a Chinese ERP system (YonBIP/用友). The scripts automate login, navigation, form filling, and data submission workflows in a nested iframe environment. ## Environment Setup ```bash # Activate the virtual environment (Windows) .venv\Scripts\activate # Install dependencies pip install playwright # Install Playwright browsers playwright install chromium ``` ## Running Scripts ```bash # Run the main test script python test_playwright.py # Run the record script python record.py ``` ## Key Dependencies - **playwright==1.57.0**: Browser automation framework - Uses synchronous API (`playwright.sync_api`) ## Architecture ### Nested Iframe Structure The target application uses deeply nested iframes that require careful handling: ``` page (browser context) └── #forwardFrame (main iframe) └── #mainiframe (inner iframe, contains actual application UI) ``` **Critical Pattern**: When accessing nested iframes, always wait for the inner iframe to be visible before extracting its content frame: ```python outer_frame = page.locator("#forwardFrame").content_frame inner_frame_locator = outer_frame.locator("#mainiframe") inner_frame_locator.wait_for(state="visible", timeout=15000) inner_frame = inner_frame_locator.content_frame ``` ### Loading State Management The application uses loading overlays ("加载中") that must be detected and waited for: ```python # Detect and wait for loading to complete loading_locator = frame.locator("div").filter(has_text="加载中").nth(1) try: loading_locator.wait_for(state="visible", timeout=3000) loading_locator.wait_for(state="hidden", timeout=0) # Infinite wait except TimeoutError: # Loading completed quickly or never appeared pass ``` ### Page Navigation Pattern New windows/popups are handled using `expect_popup()`: ```python with page.expect_popup() as popup_info: some_button.click() new_page = popup_info.value ``` ## Common Utilities ### `get_input_by_label(frame, label_text)` Locates input fields by their associated label text. Searches upward through parent containers to find the input: ```python input_box = get_input_by_label(frame, "生产部门") if input_box: current_value = input_box.input_value() input_box.fill("new value") ``` ### `click_button_until_disappear(frame, button_name, max_attempts, max_duration)` Continuously clicks a button until it disappears from the DOM. Includes logic to auto-fill missing data before each click. ## Development Notes - **Browser launch**: `chromium.launch(headless=False)` for debugging - **HTTPS errors**: Ignored with `ignore_https_errors=True` due to self-signed certificates on target system - **Locators**: Uses role-based locators (`get_by_role()`) where possible, falling back to CSS selectors and text filtering - **Text matching**: Uses regular expressions for matching text with patterns like `re.compile(r"^生产部门$")` - **Date format**: "YYYY-MM-DD" (e.g., "2025-12-28") - **Language**: Application is in Chinese; comments and print statements use Chinese for clarity - **Debugging**: Uses `pdb.set_trace()` for interactive debugging sessions ## Target Application Details - **URL**: `https://68.11.34.30:8082/` (internal network) - **System**: YonBIP (用友) ERP system - **Login**: Requires username and password; may show "force login" confirmation dialog - **Key workflows**: - "补货安排" (Replenishment Arrangement) - "生产订单" (Production Orders) - Batch data submission with "保存提交" (Save & Submit) button