pomelo-pw 0.15.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pomelo_pw-0.15.4/.gitignore +33 -0
- pomelo_pw-0.15.4/PKG-INFO +231 -0
- pomelo_pw-0.15.4/README.md +219 -0
- pomelo_pw-0.15.4/pyproject.toml +69 -0
- pomelo_pw-0.15.4/src/pomelo_pw/__init__.py +5 -0
- pomelo_pw-0.15.4/src/pomelo_pw/__main__.py +12 -0
- pomelo_pw-0.15.4/src/pomelo_pw/browser.py +36 -0
- pomelo_pw-0.15.4/src/pomelo_pw/cli.py +214 -0
- pomelo_pw-0.15.4/src/pomelo_pw/config/__init__.py +15 -0
- pomelo_pw-0.15.4/src/pomelo_pw/config/settings.py +128 -0
- pomelo_pw-0.15.4/src/pomelo_pw/error_context.py +130 -0
- pomelo_pw-0.15.4/src/pomelo_pw/executor.py +527 -0
- pomelo_pw-0.15.4/src/pomelo_pw/explorer.py +305 -0
- pomelo_pw-0.15.4/src/pomelo_pw/recorder.py +340 -0
- pomelo_pw-0.15.4/src/pomelo_pw/steps/__init__.py +64 -0
- pomelo_pw-0.15.4/src/pomelo_pw/steps/base.py +100 -0
- pomelo_pw-0.15.4/src/pomelo_pw/steps/check.py +27 -0
- pomelo_pw-0.15.4/src/pomelo_pw/steps/click.py +78 -0
- pomelo_pw-0.15.4/src/pomelo_pw/steps/conditional.py +116 -0
- pomelo_pw-0.15.4/src/pomelo_pw/steps/evaluate.py +117 -0
- pomelo_pw-0.15.4/src/pomelo_pw/steps/fill.py +28 -0
- pomelo_pw-0.15.4/src/pomelo_pw/steps/hover.py +27 -0
- pomelo_pw-0.15.4/src/pomelo_pw/steps/load_state.py +81 -0
- pomelo_pw-0.15.4/src/pomelo_pw/steps/loop.py +70 -0
- pomelo_pw-0.15.4/src/pomelo_pw/steps/navigate.py +46 -0
- pomelo_pw-0.15.4/src/pomelo_pw/steps/press.py +25 -0
- pomelo_pw-0.15.4/src/pomelo_pw/steps/save_state.py +43 -0
- pomelo_pw-0.15.4/src/pomelo_pw/steps/screenshot.py +203 -0
- pomelo_pw-0.15.4/src/pomelo_pw/steps/scroll.py +40 -0
- pomelo_pw-0.15.4/src/pomelo_pw/steps/select.py +44 -0
- pomelo_pw-0.15.4/src/pomelo_pw/steps/set_viewport.py +30 -0
- pomelo_pw-0.15.4/src/pomelo_pw/steps/type.py +29 -0
- pomelo_pw-0.15.4/src/pomelo_pw/steps/uncheck.py +27 -0
- pomelo_pw-0.15.4/src/pomelo_pw/steps/wait.py +183 -0
- pomelo_pw-0.15.4/src/pomelo_pw/substitution.py +85 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
.venv
|
|
8
|
+
venv/
|
|
9
|
+
.pytest_cache/
|
|
10
|
+
.mypy_cache/
|
|
11
|
+
.ruff_cache/
|
|
12
|
+
coverage/
|
|
13
|
+
*.cover
|
|
14
|
+
.coverage
|
|
15
|
+
|
|
16
|
+
# IDE
|
|
17
|
+
.idea/
|
|
18
|
+
.vscode/
|
|
19
|
+
*.swp
|
|
20
|
+
*.swo
|
|
21
|
+
*~
|
|
22
|
+
|
|
23
|
+
# OS
|
|
24
|
+
.DS_Store
|
|
25
|
+
Thumbs.db
|
|
26
|
+
|
|
27
|
+
# Env
|
|
28
|
+
.env
|
|
29
|
+
.env.local
|
|
30
|
+
.env.*.local
|
|
31
|
+
|
|
32
|
+
output
|
|
33
|
+
build/
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: pomelo-pw
|
|
3
|
+
Version: 0.15.4
|
|
4
|
+
Summary: Flow-based UI automation tool powered by Playwright
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
|
+
Requires-Dist: click>=8.0.0
|
|
7
|
+
Requires-Dist: playwright>=1.40.0
|
|
8
|
+
Requires-Dist: pyyaml>=6.0
|
|
9
|
+
Provides-Extra: visual
|
|
10
|
+
Requires-Dist: pillow>=10.0.0; extra == 'visual'
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# Pomelo PW
|
|
14
|
+
|
|
15
|
+
[](https://github.com/leoninew/pomelo-pw/actions/workflows/ci.yml)
|
|
16
|
+
|
|
17
|
+
[English](README.md) | [简体中文](README_CN.md)
|
|
18
|
+
|
|
19
|
+
Pomelo PW is a Playwright-powered CLI for browser automation. It runs declarative YAML flows, so browser checks can live alongside application code without requiring a custom test harness.
|
|
20
|
+
|
|
21
|
+
It is intended for repeatable UI checks, scripted workflows, visual comparisons, and agent-assisted browser tasks. Flows validate their parameters before execution and collect screenshots, page snapshots, console errors, and network failures when a step fails.
|
|
22
|
+
|
|
23
|
+
## What It Provides
|
|
24
|
+
|
|
25
|
+
- YAML flows with `{{variable}}` substitution and CLI overrides
|
|
26
|
+
- Browser steps for navigation, forms, waits, screenshots, state reuse, conditions, and loops
|
|
27
|
+
- Interactive explorer and recorder for finding selectors and creating starting flows
|
|
28
|
+
- Step-level retries, data-driven runs, and screenshot baseline comparison
|
|
29
|
+
- Native plugin packaging for Claude Code, Codex, and Grok Build
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
Pomelo PW requires Python 3.12+ and [uv](https://docs.astral.sh/uv/).
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Install the published CLI, then install its browser
|
|
37
|
+
uv tool install pomelo-pw
|
|
38
|
+
pomelo-pw install
|
|
39
|
+
|
|
40
|
+
# Or invoke the published package once without installing the CLI
|
|
41
|
+
uvx pomelo-pw install
|
|
42
|
+
|
|
43
|
+
# Work from a source checkout
|
|
44
|
+
uv sync --all-groups --locked
|
|
45
|
+
uv run pomelo-pw install
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The `install` command downloads Playwright Chromium for package installations. When run from a source checkout or the standalone binary, Pomelo PW uses an installed system Chrome or Chromium when it can find one.
|
|
49
|
+
|
|
50
|
+
Install visual comparison support only when flows use screenshot baselines:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
uv pip install pillow
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Quick Start
|
|
57
|
+
|
|
58
|
+
Create `smoke.yaml`:
|
|
59
|
+
|
|
60
|
+
```yaml
|
|
61
|
+
name: example-smoke
|
|
62
|
+
variables:
|
|
63
|
+
base_url: "https://example.com"
|
|
64
|
+
|
|
65
|
+
steps:
|
|
66
|
+
- type: navigate
|
|
67
|
+
url: "{{base_url}}"
|
|
68
|
+
- type: screenshot
|
|
69
|
+
file: "homepage.png"
|
|
70
|
+
- type: scroll
|
|
71
|
+
direction: down
|
|
72
|
+
distance: 500
|
|
73
|
+
- type: screenshot
|
|
74
|
+
file: "scrolled.png"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Run and validate it:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
uvx pomelo-pw validate smoke.yaml
|
|
81
|
+
uvx pomelo-pw run smoke.yaml --headless
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Screenshots and failure artifacts are written to `./smoke/` by default. Use `-o <directory>` to choose another output directory.
|
|
85
|
+
|
|
86
|
+
## Use Pomelo PW
|
|
87
|
+
|
|
88
|
+
### Find Selectors and Create Flows
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# Inspect a page and copy a selector from the interactive overlay
|
|
92
|
+
pomelo-pw explore https://example.com
|
|
93
|
+
|
|
94
|
+
# Record clicks, fills, and Enter presses into a YAML flow
|
|
95
|
+
pomelo-pw record https://example.com recorded-flow.yaml
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Prefer selectors based on stable semantics, such as `role=button[name="Continue"]`, over presentation-oriented CSS classes.
|
|
99
|
+
|
|
100
|
+
### Run Flows
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
# Run visibly with step progress
|
|
104
|
+
pomelo-pw run flow.yaml -v
|
|
105
|
+
|
|
106
|
+
# Run headlessly and emit the result as JSON
|
|
107
|
+
pomelo-pw run flow.yaml --headless --json
|
|
108
|
+
|
|
109
|
+
# Override a flow variable for this run
|
|
110
|
+
pomelo-pw run flow.yaml --var base_url=https://staging.example.com
|
|
111
|
+
|
|
112
|
+
# Validate YAML and step parameters without launching a browser
|
|
113
|
+
pomelo-pw validate flow.yaml
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Variables use `{{name}}`; CLI values take precedence over step-level values, which take precedence over flow-level values. The `${name}` form is preserved for JavaScript and shell template literals.
|
|
117
|
+
|
|
118
|
+
### Author Flows
|
|
119
|
+
|
|
120
|
+
The following flow shows the common pattern: navigate, interact, wait for a meaningful result, then capture evidence.
|
|
121
|
+
|
|
122
|
+
```yaml
|
|
123
|
+
name: login-smoke
|
|
124
|
+
variables:
|
|
125
|
+
base_url: "https://app.example.com"
|
|
126
|
+
username: "user@example.com"
|
|
127
|
+
password: "secret"
|
|
128
|
+
|
|
129
|
+
steps:
|
|
130
|
+
- type: navigate
|
|
131
|
+
url: "{{base_url}}/login"
|
|
132
|
+
- type: fill
|
|
133
|
+
selector: "input[name='email']"
|
|
134
|
+
value: "{{username}}"
|
|
135
|
+
- type: fill
|
|
136
|
+
selector: "input[name='password']"
|
|
137
|
+
value: "{{password}}"
|
|
138
|
+
- type: click
|
|
139
|
+
selector: "button[type='submit']"
|
|
140
|
+
- type: wait
|
|
141
|
+
url_contains: "/dashboard"
|
|
142
|
+
- type: screenshot
|
|
143
|
+
file: "dashboard.png"
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
| Step | Main parameters | Purpose |
|
|
147
|
+
| --- | --- | --- |
|
|
148
|
+
| `navigate` | `url` | Open a page |
|
|
149
|
+
| `click`, `hover`, `press` | `selector` or `key` | Interact with an element or keyboard |
|
|
150
|
+
| `fill`, `type` | `selector`, `value` | Enter text |
|
|
151
|
+
| `select` | `selector`, one of `value` / `label` | Choose an option by HTML value or visible text |
|
|
152
|
+
| `wait` | selector, URL, network, or timing condition | Synchronize with dynamic UI |
|
|
153
|
+
| `screenshot` | `file` | Capture a page or element, optionally against a baseline |
|
|
154
|
+
| `check`, `uncheck` | `selector` | Control checkboxes |
|
|
155
|
+
| `save-state`, `load-state` | `file` | Reuse authenticated browser state |
|
|
156
|
+
| `if`, `loop` | condition or iteration settings | Model branches and repeated actions |
|
|
157
|
+
| `evaluate`, `scroll`, `set-viewport` | step-specific parameters | Run browser-side scripts or adjust the viewport |
|
|
158
|
+
|
|
159
|
+
List the available steps or inspect any step's exact parameters before writing a flow:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
pomelo-pw steps
|
|
163
|
+
pomelo-pw spec wait
|
|
164
|
+
pomelo-pw spec select
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
The [flows/](flows/) directory contains runnable examples for waits, retries, saved state, data-driven runs, conditions, loops, JavaScript evaluation, and visual baselines. The bundled [agent skill](plugins/pomelo-pw/skills/pomelo-pw/SKILL.md) contains agent-oriented guidance and reusable flow templates.
|
|
168
|
+
|
|
169
|
+
## Develop
|
|
170
|
+
|
|
171
|
+
Install the locked development environment:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
uv sync --all-groups --locked
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Run the normal quality gates directly with `uv`:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
uv run --locked --no-sync ruff format --check src tests scripts
|
|
181
|
+
uv run --locked --no-sync ruff check src tests scripts
|
|
182
|
+
uv run --locked --no-sync mypy src tests scripts
|
|
183
|
+
uv run --locked --no-sync pytest
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
On systems with GNU Make and Bash, `make check` and `make test` wrap those commands. `make test cov=1` also writes an HTML coverage report.
|
|
187
|
+
|
|
188
|
+
### Refresh the Native Plugin
|
|
189
|
+
|
|
190
|
+
The repository packages the `pomelo-pw` skill as a native plugin. Validate the package first, then refresh the editable CLI and installed plugin for available agent clients:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
uv run --locked python scripts/install.py plugin check
|
|
194
|
+
uv tool install --editable . --force
|
|
195
|
+
uv run --locked python scripts/install.py plugin apply
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Restart the agent client after applying a plugin update so it loads the new skill.
|
|
199
|
+
|
|
200
|
+
### Build and Release
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
# Inspect the Git-derived release version
|
|
204
|
+
uv run --locked --no-sync python scripts/version_calc.py
|
|
205
|
+
|
|
206
|
+
# Apply the calculated version to pyproject.toml and uv.lock
|
|
207
|
+
uv run --locked --no-sync python scripts/version_calc.py --no-dry-run
|
|
208
|
+
|
|
209
|
+
# Build source and wheel distributions
|
|
210
|
+
uv build
|
|
211
|
+
|
|
212
|
+
# Build a standalone executable when GNU Make and Bash are available
|
|
213
|
+
make binary
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Release versions are derived from Git history. After reviewing the version-file changes, commit them and create the matching `vX.Y.Z` tag; GitHub Actions builds the wheel and platform binaries from that tag.
|
|
217
|
+
|
|
218
|
+
## Repository Layout
|
|
219
|
+
|
|
220
|
+
```text
|
|
221
|
+
src/pomelo_pw/ CLI, executor, configuration, and step implementations
|
|
222
|
+
tests/ Unit and integration-style tests
|
|
223
|
+
flows/ Runnable YAML examples
|
|
224
|
+
plugins/pomelo-pw/ Native plugin and agent skill
|
|
225
|
+
docs/ Architecture and process documentation
|
|
226
|
+
scripts/ Plugin synchronization and release helpers
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## License
|
|
230
|
+
|
|
231
|
+
MIT
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Pomelo PW
|
|
2
|
+
|
|
3
|
+
[](https://github.com/leoninew/pomelo-pw/actions/workflows/ci.yml)
|
|
4
|
+
|
|
5
|
+
[English](README.md) | [简体中文](README_CN.md)
|
|
6
|
+
|
|
7
|
+
Pomelo PW is a Playwright-powered CLI for browser automation. It runs declarative YAML flows, so browser checks can live alongside application code without requiring a custom test harness.
|
|
8
|
+
|
|
9
|
+
It is intended for repeatable UI checks, scripted workflows, visual comparisons, and agent-assisted browser tasks. Flows validate their parameters before execution and collect screenshots, page snapshots, console errors, and network failures when a step fails.
|
|
10
|
+
|
|
11
|
+
## What It Provides
|
|
12
|
+
|
|
13
|
+
- YAML flows with `{{variable}}` substitution and CLI overrides
|
|
14
|
+
- Browser steps for navigation, forms, waits, screenshots, state reuse, conditions, and loops
|
|
15
|
+
- Interactive explorer and recorder for finding selectors and creating starting flows
|
|
16
|
+
- Step-level retries, data-driven runs, and screenshot baseline comparison
|
|
17
|
+
- Native plugin packaging for Claude Code, Codex, and Grok Build
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
Pomelo PW requires Python 3.12+ and [uv](https://docs.astral.sh/uv/).
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Install the published CLI, then install its browser
|
|
25
|
+
uv tool install pomelo-pw
|
|
26
|
+
pomelo-pw install
|
|
27
|
+
|
|
28
|
+
# Or invoke the published package once without installing the CLI
|
|
29
|
+
uvx pomelo-pw install
|
|
30
|
+
|
|
31
|
+
# Work from a source checkout
|
|
32
|
+
uv sync --all-groups --locked
|
|
33
|
+
uv run pomelo-pw install
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The `install` command downloads Playwright Chromium for package installations. When run from a source checkout or the standalone binary, Pomelo PW uses an installed system Chrome or Chromium when it can find one.
|
|
37
|
+
|
|
38
|
+
Install visual comparison support only when flows use screenshot baselines:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
uv pip install pillow
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Quick Start
|
|
45
|
+
|
|
46
|
+
Create `smoke.yaml`:
|
|
47
|
+
|
|
48
|
+
```yaml
|
|
49
|
+
name: example-smoke
|
|
50
|
+
variables:
|
|
51
|
+
base_url: "https://example.com"
|
|
52
|
+
|
|
53
|
+
steps:
|
|
54
|
+
- type: navigate
|
|
55
|
+
url: "{{base_url}}"
|
|
56
|
+
- type: screenshot
|
|
57
|
+
file: "homepage.png"
|
|
58
|
+
- type: scroll
|
|
59
|
+
direction: down
|
|
60
|
+
distance: 500
|
|
61
|
+
- type: screenshot
|
|
62
|
+
file: "scrolled.png"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Run and validate it:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
uvx pomelo-pw validate smoke.yaml
|
|
69
|
+
uvx pomelo-pw run smoke.yaml --headless
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Screenshots and failure artifacts are written to `./smoke/` by default. Use `-o <directory>` to choose another output directory.
|
|
73
|
+
|
|
74
|
+
## Use Pomelo PW
|
|
75
|
+
|
|
76
|
+
### Find Selectors and Create Flows
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Inspect a page and copy a selector from the interactive overlay
|
|
80
|
+
pomelo-pw explore https://example.com
|
|
81
|
+
|
|
82
|
+
# Record clicks, fills, and Enter presses into a YAML flow
|
|
83
|
+
pomelo-pw record https://example.com recorded-flow.yaml
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Prefer selectors based on stable semantics, such as `role=button[name="Continue"]`, over presentation-oriented CSS classes.
|
|
87
|
+
|
|
88
|
+
### Run Flows
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# Run visibly with step progress
|
|
92
|
+
pomelo-pw run flow.yaml -v
|
|
93
|
+
|
|
94
|
+
# Run headlessly and emit the result as JSON
|
|
95
|
+
pomelo-pw run flow.yaml --headless --json
|
|
96
|
+
|
|
97
|
+
# Override a flow variable for this run
|
|
98
|
+
pomelo-pw run flow.yaml --var base_url=https://staging.example.com
|
|
99
|
+
|
|
100
|
+
# Validate YAML and step parameters without launching a browser
|
|
101
|
+
pomelo-pw validate flow.yaml
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Variables use `{{name}}`; CLI values take precedence over step-level values, which take precedence over flow-level values. The `${name}` form is preserved for JavaScript and shell template literals.
|
|
105
|
+
|
|
106
|
+
### Author Flows
|
|
107
|
+
|
|
108
|
+
The following flow shows the common pattern: navigate, interact, wait for a meaningful result, then capture evidence.
|
|
109
|
+
|
|
110
|
+
```yaml
|
|
111
|
+
name: login-smoke
|
|
112
|
+
variables:
|
|
113
|
+
base_url: "https://app.example.com"
|
|
114
|
+
username: "user@example.com"
|
|
115
|
+
password: "secret"
|
|
116
|
+
|
|
117
|
+
steps:
|
|
118
|
+
- type: navigate
|
|
119
|
+
url: "{{base_url}}/login"
|
|
120
|
+
- type: fill
|
|
121
|
+
selector: "input[name='email']"
|
|
122
|
+
value: "{{username}}"
|
|
123
|
+
- type: fill
|
|
124
|
+
selector: "input[name='password']"
|
|
125
|
+
value: "{{password}}"
|
|
126
|
+
- type: click
|
|
127
|
+
selector: "button[type='submit']"
|
|
128
|
+
- type: wait
|
|
129
|
+
url_contains: "/dashboard"
|
|
130
|
+
- type: screenshot
|
|
131
|
+
file: "dashboard.png"
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
| Step | Main parameters | Purpose |
|
|
135
|
+
| --- | --- | --- |
|
|
136
|
+
| `navigate` | `url` | Open a page |
|
|
137
|
+
| `click`, `hover`, `press` | `selector` or `key` | Interact with an element or keyboard |
|
|
138
|
+
| `fill`, `type` | `selector`, `value` | Enter text |
|
|
139
|
+
| `select` | `selector`, one of `value` / `label` | Choose an option by HTML value or visible text |
|
|
140
|
+
| `wait` | selector, URL, network, or timing condition | Synchronize with dynamic UI |
|
|
141
|
+
| `screenshot` | `file` | Capture a page or element, optionally against a baseline |
|
|
142
|
+
| `check`, `uncheck` | `selector` | Control checkboxes |
|
|
143
|
+
| `save-state`, `load-state` | `file` | Reuse authenticated browser state |
|
|
144
|
+
| `if`, `loop` | condition or iteration settings | Model branches and repeated actions |
|
|
145
|
+
| `evaluate`, `scroll`, `set-viewport` | step-specific parameters | Run browser-side scripts or adjust the viewport |
|
|
146
|
+
|
|
147
|
+
List the available steps or inspect any step's exact parameters before writing a flow:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
pomelo-pw steps
|
|
151
|
+
pomelo-pw spec wait
|
|
152
|
+
pomelo-pw spec select
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
The [flows/](flows/) directory contains runnable examples for waits, retries, saved state, data-driven runs, conditions, loops, JavaScript evaluation, and visual baselines. The bundled [agent skill](plugins/pomelo-pw/skills/pomelo-pw/SKILL.md) contains agent-oriented guidance and reusable flow templates.
|
|
156
|
+
|
|
157
|
+
## Develop
|
|
158
|
+
|
|
159
|
+
Install the locked development environment:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
uv sync --all-groups --locked
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Run the normal quality gates directly with `uv`:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
uv run --locked --no-sync ruff format --check src tests scripts
|
|
169
|
+
uv run --locked --no-sync ruff check src tests scripts
|
|
170
|
+
uv run --locked --no-sync mypy src tests scripts
|
|
171
|
+
uv run --locked --no-sync pytest
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
On systems with GNU Make and Bash, `make check` and `make test` wrap those commands. `make test cov=1` also writes an HTML coverage report.
|
|
175
|
+
|
|
176
|
+
### Refresh the Native Plugin
|
|
177
|
+
|
|
178
|
+
The repository packages the `pomelo-pw` skill as a native plugin. Validate the package first, then refresh the editable CLI and installed plugin for available agent clients:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
uv run --locked python scripts/install.py plugin check
|
|
182
|
+
uv tool install --editable . --force
|
|
183
|
+
uv run --locked python scripts/install.py plugin apply
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Restart the agent client after applying a plugin update so it loads the new skill.
|
|
187
|
+
|
|
188
|
+
### Build and Release
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
# Inspect the Git-derived release version
|
|
192
|
+
uv run --locked --no-sync python scripts/version_calc.py
|
|
193
|
+
|
|
194
|
+
# Apply the calculated version to pyproject.toml and uv.lock
|
|
195
|
+
uv run --locked --no-sync python scripts/version_calc.py --no-dry-run
|
|
196
|
+
|
|
197
|
+
# Build source and wheel distributions
|
|
198
|
+
uv build
|
|
199
|
+
|
|
200
|
+
# Build a standalone executable when GNU Make and Bash are available
|
|
201
|
+
make binary
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Release versions are derived from Git history. After reviewing the version-file changes, commit them and create the matching `vX.Y.Z` tag; GitHub Actions builds the wheel and platform binaries from that tag.
|
|
205
|
+
|
|
206
|
+
## Repository Layout
|
|
207
|
+
|
|
208
|
+
```text
|
|
209
|
+
src/pomelo_pw/ CLI, executor, configuration, and step implementations
|
|
210
|
+
tests/ Unit and integration-style tests
|
|
211
|
+
flows/ Runnable YAML examples
|
|
212
|
+
plugins/pomelo-pw/ Native plugin and agent skill
|
|
213
|
+
docs/ Architecture and process documentation
|
|
214
|
+
scripts/ Plugin synchronization and release helpers
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## License
|
|
218
|
+
|
|
219
|
+
MIT
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "pomelo-pw"
|
|
3
|
+
version = "0.15.4"
|
|
4
|
+
description = "Flow-based UI automation tool powered by Playwright"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.12"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"playwright>=1.40.0",
|
|
9
|
+
"click>=8.0.0",
|
|
10
|
+
"pyyaml>=6.0",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
[project.optional-dependencies]
|
|
14
|
+
visual = [
|
|
15
|
+
"pillow>=10.0.0",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
[project.scripts]
|
|
19
|
+
pomelo-pw = "pomelo_pw.__main__:main"
|
|
20
|
+
|
|
21
|
+
[build-system]
|
|
22
|
+
requires = ["hatchling"]
|
|
23
|
+
build-backend = "hatchling.build"
|
|
24
|
+
|
|
25
|
+
[tool.hatch.build.targets.wheel]
|
|
26
|
+
packages = ["src/pomelo_pw"]
|
|
27
|
+
|
|
28
|
+
[tool.hatch.build.targets.sdist]
|
|
29
|
+
include = ["src/pomelo_pw"]
|
|
30
|
+
|
|
31
|
+
[dependency-groups]
|
|
32
|
+
dev = [
|
|
33
|
+
"pyinstaller>=6.18.0",
|
|
34
|
+
"ruff>=0.15.17",
|
|
35
|
+
"mypy>=2.1.0",
|
|
36
|
+
"pytest>=9.0.2",
|
|
37
|
+
"types-pyyaml>=6.0.12.20260518",
|
|
38
|
+
"pytest-asyncio>=1.4.0",
|
|
39
|
+
"pytest-cov>=7.0.0,<8.0.0",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[tool.mypy]
|
|
43
|
+
python_version = "3.12"
|
|
44
|
+
files = ["src", "tests", "scripts"]
|
|
45
|
+
mypy_path = "src"
|
|
46
|
+
strict = true
|
|
47
|
+
warn_return_any = true
|
|
48
|
+
warn_unused_configs = true
|
|
49
|
+
warn_unreachable = true
|
|
50
|
+
pretty = true
|
|
51
|
+
|
|
52
|
+
[tool.ruff]
|
|
53
|
+
line-length = 120
|
|
54
|
+
target-version = "py312"
|
|
55
|
+
exclude = ["scripts/install.py"]
|
|
56
|
+
force-exclude = true
|
|
57
|
+
|
|
58
|
+
[tool.ruff.format]
|
|
59
|
+
quote-style = "double"
|
|
60
|
+
indent-style = "space"
|
|
61
|
+
line-ending = "auto"
|
|
62
|
+
|
|
63
|
+
[tool.ruff.lint]
|
|
64
|
+
select = ["E", "F", "I", "UP", "B", "SIM"]
|
|
65
|
+
ignore = ["E501"]
|
|
66
|
+
|
|
67
|
+
[tool.pytest.ini_options]
|
|
68
|
+
asyncio_mode = "auto"
|
|
69
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Shared Playwright browser setup."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from playwright.async_api import Browser, BrowserContext, Playwright
|
|
8
|
+
|
|
9
|
+
from pomelo_pw.config import PlaywrightConfig
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BrowserLifecycle:
|
|
13
|
+
"""Create browser resources from the resolved Playwright configuration."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, config: PlaywrightConfig) -> None:
|
|
16
|
+
self.config = config
|
|
17
|
+
|
|
18
|
+
async def launch(self, playwright: Playwright, *, headless: bool) -> Browser:
|
|
19
|
+
"""Launch Chromium with the configured runtime options."""
|
|
20
|
+
launch_options: dict[str, Any] = {
|
|
21
|
+
"headless": headless,
|
|
22
|
+
"timeout": self.config.timeout,
|
|
23
|
+
"slow_mo": self.config.slow_mo,
|
|
24
|
+
}
|
|
25
|
+
if self.config.executable_path:
|
|
26
|
+
launch_options["executable_path"] = self.config.executable_path
|
|
27
|
+
return await playwright.chromium.launch(**launch_options)
|
|
28
|
+
|
|
29
|
+
async def new_context(self, browser: Browser) -> BrowserContext:
|
|
30
|
+
"""Create a browser context with the configured viewport."""
|
|
31
|
+
return await browser.new_context(
|
|
32
|
+
viewport={
|
|
33
|
+
"width": self.config.viewport.width,
|
|
34
|
+
"height": self.config.viewport.height,
|
|
35
|
+
},
|
|
36
|
+
)
|