Files
playwrite/CLAUDE.md

119 lines
3.7 KiB
Markdown

# 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