playwright-smart-locators 0.1.0__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.
- playwright_smart_locators-0.1.0/.github/workflows/publish.yml +37 -0
- playwright_smart_locators-0.1.0/.github/workflows/review.yml +26 -0
- playwright_smart_locators-0.1.0/.gitignore +29 -0
- playwright_smart_locators-0.1.0/.idea/.gitignore +8 -0
- playwright_smart_locators-0.1.0/.idea/vcs.xml +4 -0
- playwright_smart_locators-0.1.0/.idea/workspace.xml +4 -0
- playwright_smart_locators-0.1.0/.npmignore +7 -0
- playwright_smart_locators-0.1.0/.smart-locators-cache.master.json.lock +0 -0
- playwright_smart_locators-0.1.0/PKG-INFO +126 -0
- playwright_smart_locators-0.1.0/README.md +105 -0
- playwright_smart_locators-0.1.0/docs/superpowers/plans/2026-06-04-python-playwright-smart-locators.md +2782 -0
- playwright_smart_locators-0.1.0/docs/superpowers/specs/2026-06-04-python-playwright-smart-locators-design.md +660 -0
- playwright_smart_locators-0.1.0/example/package.json +16 -0
- playwright_smart_locators-0.1.0/example/pages/login.page.ts +31 -0
- playwright_smart_locators-0.1.0/example/playwright.config.ts +22 -0
- playwright_smart_locators-0.1.0/example/tests/example.spec.ts +39 -0
- playwright_smart_locators-0.1.0/example/tests/pom.spec.ts +34 -0
- playwright_smart_locators-0.1.0/example_python/conftest.py +9 -0
- playwright_smart_locators-0.1.0/example_python/pages/login_page.py +19 -0
- playwright_smart_locators-0.1.0/example_python/pyproject.toml +22 -0
- playwright_smart_locators-0.1.0/example_python/server.py +30 -0
- playwright_smart_locators-0.1.0/example_python/tests/test_pom.py +24 -0
- playwright_smart_locators-0.1.0/example_python/tests/test_procedural.py +20 -0
- playwright_smart_locators-0.1.0/package-lock.json +118 -0
- playwright_smart_locators-0.1.0/package.json +66 -0
- playwright_smart_locators-0.1.0/playwright_smart_locators/__init__.py +61 -0
- playwright_smart_locators-0.1.0/playwright_smart_locators/ai_client.py +288 -0
- playwright_smart_locators-0.1.0/playwright_smart_locators/cache.py +93 -0
- playwright_smart_locators-0.1.0/playwright_smart_locators/exceptions.py +46 -0
- playwright_smart_locators-0.1.0/playwright_smart_locators/plugin.py +168 -0
- playwright_smart_locators-0.1.0/playwright_smart_locators/prompts.py +60 -0
- playwright_smart_locators-0.1.0/playwright_smart_locators/py.typed +0 -0
- playwright_smart_locators-0.1.0/playwright_smart_locators/reporter.py +92 -0
- playwright_smart_locators-0.1.0/playwright_smart_locators/sanitizer.py +39 -0
- playwright_smart_locators-0.1.0/playwright_smart_locators/smart_config.py +29 -0
- playwright_smart_locators-0.1.0/playwright_smart_locators/smart_locator.py +239 -0
- playwright_smart_locators-0.1.0/playwright_smart_locators/smart_page.py +116 -0
- playwright_smart_locators-0.1.0/playwright_smart_locators/stack_parser.py +30 -0
- playwright_smart_locators-0.1.0/playwright_smart_locators/types.py +25 -0
- playwright_smart_locators-0.1.0/pyproject.toml +43 -0
- playwright_smart_locators-0.1.0/src/ai-client.ts +77 -0
- playwright_smart_locators-0.1.0/src/cache.ts +19 -0
- playwright_smart_locators-0.1.0/src/index.ts +221 -0
- playwright_smart_locators-0.1.0/src/prompts.ts +17 -0
- playwright_smart_locators-0.1.0/src/reporter.ts +73 -0
- playwright_smart_locators-0.1.0/src/types.ts +7 -0
- playwright_smart_locators-0.1.0/tests/__init__.py +0 -0
- playwright_smart_locators-0.1.0/tests/conftest.py +2 -0
- playwright_smart_locators-0.1.0/tests/integration/conftest.py +95 -0
- playwright_smart_locators-0.1.0/tests/integration/test_smart_page_e2e.py +19 -0
- playwright_smart_locators-0.1.0/tests/integration/test_xdist_concurrency.py +32 -0
- playwright_smart_locators-0.1.0/tests/unit/test_ai_client.py +246 -0
- playwright_smart_locators-0.1.0/tests/unit/test_cache.py +79 -0
- playwright_smart_locators-0.1.0/tests/unit/test_exceptions.py +44 -0
- playwright_smart_locators-0.1.0/tests/unit/test_plugin.py +205 -0
- playwright_smart_locators-0.1.0/tests/unit/test_prompts.py +45 -0
- playwright_smart_locators-0.1.0/tests/unit/test_reporter.py +103 -0
- playwright_smart_locators-0.1.0/tests/unit/test_sanitizer.py +51 -0
- playwright_smart_locators-0.1.0/tests/unit/test_smart_config.py +32 -0
- playwright_smart_locators-0.1.0/tests/unit/test_smart_locator.py +308 -0
- playwright_smart_locators-0.1.0/tests/unit/test_smart_page.py +133 -0
- playwright_smart_locators-0.1.0/tests/unit/test_stack_parser.py +21 -0
- playwright_smart_locators-0.1.0/tests/unit/test_types.py +35 -0
- playwright_smart_locators-0.1.0/tsconfig.json +16 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: Publish Package to npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
# Alternatively, you can use push on main or tags:
|
|
8
|
+
# push:
|
|
9
|
+
# tags:
|
|
10
|
+
# - 'v*'
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build-and-publish:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout code
|
|
17
|
+
uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Setup Node.js
|
|
20
|
+
uses: actions/setup-node@v4
|
|
21
|
+
with:
|
|
22
|
+
node-version: '20.x'
|
|
23
|
+
registry-url: 'https://registry.npmjs.org'
|
|
24
|
+
|
|
25
|
+
- name: Install dependencies
|
|
26
|
+
run: npm ci
|
|
27
|
+
|
|
28
|
+
- name: Build package
|
|
29
|
+
run: npm run build
|
|
30
|
+
|
|
31
|
+
- name: Publish to npm
|
|
32
|
+
run: npm publish --access public
|
|
33
|
+
env:
|
|
34
|
+
# actions/setup-node creates an .npmrc that uses NODE_AUTH_TOKEN
|
|
35
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
36
|
+
# Providing NPM_TOKEN as well in case the local .npmrc relies on it
|
|
37
|
+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Self-Review
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
types: [opened, synchronize, reopened]
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
pull-requests: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
review:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: AxeForging/reviewforge@main
|
|
18
|
+
with:
|
|
19
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
20
|
+
AI_PROVIDER: gemini
|
|
21
|
+
AI_MODEL: gemini-2.5-flash
|
|
22
|
+
AI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
|
|
23
|
+
SHOW_TOKEN_USAGE: true
|
|
24
|
+
INCREMENTAL: false
|
|
25
|
+
PERSONA: ""
|
|
26
|
+
REVIEW_RULES: concise
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
node_modules/
|
|
2
|
+
dist/
|
|
3
|
+
.DS_Store
|
|
4
|
+
*.tgz
|
|
5
|
+
.env
|
|
6
|
+
*-healed.ts
|
|
7
|
+
test-results/
|
|
8
|
+
.smart-locators-cache.json
|
|
9
|
+
example/node_modules/
|
|
10
|
+
example/package-lock.json
|
|
11
|
+
|
|
12
|
+
# Worktree
|
|
13
|
+
.worktrees/
|
|
14
|
+
|
|
15
|
+
# Python implementation (added by Python port worktree)
|
|
16
|
+
.venv/
|
|
17
|
+
.venv*/
|
|
18
|
+
__pycache__/
|
|
19
|
+
*.py[cod]
|
|
20
|
+
.pytest_cache/
|
|
21
|
+
.mypy_cache/
|
|
22
|
+
.ruff_cache/
|
|
23
|
+
htmlcov/
|
|
24
|
+
*-healed.py
|
|
25
|
+
.smart-locators-cache*.json
|
|
26
|
+
example_python/__pycache__/
|
|
27
|
+
example_python/.venv/
|
|
28
|
+
example_python/.venv*/
|
|
29
|
+
uv.lock
|
|
File without changes
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: playwright-smart-locators
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: AI-powered self-healing smart locators for Playwright (Python).
|
|
5
|
+
Author: R&D Team
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: ai,anthropic,e2e,llm,locators,ollama,openai,playwright,pytest,self-healing
|
|
8
|
+
Requires-Python: >=3.9
|
|
9
|
+
Requires-Dist: httpx>=0.24
|
|
10
|
+
Requires-Dist: playwright>=1.40
|
|
11
|
+
Requires-Dist: pytest-playwright>=0.4
|
|
12
|
+
Requires-Dist: pytest>=7
|
|
13
|
+
Provides-Extra: dev
|
|
14
|
+
Requires-Dist: fastapi; extra == 'dev'
|
|
15
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
16
|
+
Requires-Dist: pytest-xdist>=3; extra == 'dev'
|
|
17
|
+
Requires-Dist: respx>=0.20; extra == 'dev'
|
|
18
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
19
|
+
Requires-Dist: uvicorn; extra == 'dev'
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# playwright_smart_locators (Python)
|
|
23
|
+
|
|
24
|
+
[](https://pypi.org/project/playwright-smart-locators/)
|
|
25
|
+
|
|
26
|
+
AI-powered self-healing smart locators for Playwright tests (Python port of
|
|
27
|
+
[@axeforging/playwright-smart-locators](https://github.com/AxeForging/playwright-smart-locators)).
|
|
28
|
+
|
|
29
|
+
When a Playwright locator fails, `playwright_smart_locators` intercepts the
|
|
30
|
+
timeout, queries an LLM with the broken selector and live/cached DOM, and
|
|
31
|
+
retries with the top 7 AI-suggested locators. After the run, it writes
|
|
32
|
+
`*-healed.py` suggestion files for review.
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install playwright_smart_locators
|
|
38
|
+
playwright install chromium
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Configure
|
|
42
|
+
|
|
43
|
+
In your `conftest.py` (opt-in):
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
import pytest
|
|
47
|
+
from playwright_smart_locators import smart_page
|
|
48
|
+
|
|
49
|
+
@pytest.fixture
|
|
50
|
+
def page(smart_page):
|
|
51
|
+
return smart_page
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
In `pyproject.toml` or `pytest.ini`:
|
|
55
|
+
|
|
56
|
+
```toml
|
|
57
|
+
[tool.pytest.ini_options]
|
|
58
|
+
addopts = [
|
|
59
|
+
"--enable-auto-heal",
|
|
60
|
+
"--ai-model=qwen2.5:7b",
|
|
61
|
+
"--ai-pipe-url=http://localhost:11434",
|
|
62
|
+
"--ai-admin-key=sk-",
|
|
63
|
+
]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Or via environment variables (recommended for Docker / CI):
|
|
67
|
+
|
|
68
|
+
| Env var | Default | Notes |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| `ENABLE_AUTO_HEAL` | `false` | `true` / `1` / `yes` / `on` to activate |
|
|
71
|
+
| `AI_MODEL` | `qwen2.5:7b` | Any model name your provider accepts |
|
|
72
|
+
| `AI_PIPE_URL` | `http://localhost:11434` | Base URL — OpenAI provider appends `/v1/chat/completions` |
|
|
73
|
+
| `AI_ADMIN_KEY` | (empty) | Bearer token; leave empty for local Ollama |
|
|
74
|
+
| `AI_PROVIDER` | `openai` | `openai` or `anthropic` |
|
|
75
|
+
| `AI_RATE_PER_MIN` | `30` | In-process token bucket rate |
|
|
76
|
+
|
|
77
|
+
Precedence: **env var > CLI flag > built-in default**. Env wins so Docker / CI configs don't have to be repeated on the command line. Empty env values fall back to the CLI value (so you can set `AI_ADMIN_KEY=` in a `.env` to mean "leave unset" without overriding the CLI flag).
|
|
78
|
+
|
|
79
|
+
**Provider auto-detect**: if `AI_PIPE_URL` ends with `/anthropic` (e.g. `https://api.example.com/anthropic`), the plugin automatically sets `ai_provider=anthropic` and emits a `UserWarning`. This lets Anthropic-compatible services (like MiniMax) work without setting `AI_PROVIDER=anthropic` explicitly. To opt out, set `AI_PIPE_URL` to a path that doesn't end with `/anthropic` (e.g. add a suffix like `/v1`).
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Examples
|
|
83
|
+
export ENABLE_AUTO_HEAL=true
|
|
84
|
+
export AI_MODEL=gpt-4o
|
|
85
|
+
export AI_PIPE_URL=https://api.openai.com
|
|
86
|
+
export AI_ADMIN_KEY=sk-xxx
|
|
87
|
+
pytest
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## AI Providers
|
|
91
|
+
|
|
92
|
+
Built-in:
|
|
93
|
+
- `openai` (also works with Ollama, Open WebUI, vLLM, LocalAI)
|
|
94
|
+
- `anthropic`
|
|
95
|
+
|
|
96
|
+
Register your own:
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from playwright_smart_locators import register_provider
|
|
100
|
+
|
|
101
|
+
class MyProvider:
|
|
102
|
+
def complete(self, *, system, user, model, timeout=30.0) -> str:
|
|
103
|
+
return '{"locators": [".my-locator"]}'
|
|
104
|
+
|
|
105
|
+
register_provider("custom", MyProvider)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## POM Support
|
|
109
|
+
|
|
110
|
+
When a locator fails inside a Page Object Model method, the auto-healer
|
|
111
|
+
uses `inspect.stack()` to find the real caller file/line. The
|
|
112
|
+
`*-healed.py` is written next to the POM file (e.g. `pages/login_page-healed.py`),
|
|
113
|
+
not the test spec.
|
|
114
|
+
|
|
115
|
+
## CI
|
|
116
|
+
|
|
117
|
+
Disable in CI (no LLM available):
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# CI: don't pass --enable-auto-heal
|
|
121
|
+
pytest --browser=chromium
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## License
|
|
125
|
+
|
|
126
|
+
MIT
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# playwright_smart_locators (Python)
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/playwright-smart-locators/)
|
|
4
|
+
|
|
5
|
+
AI-powered self-healing smart locators for Playwright tests (Python port of
|
|
6
|
+
[@axeforging/playwright-smart-locators](https://github.com/AxeForging/playwright-smart-locators)).
|
|
7
|
+
|
|
8
|
+
When a Playwright locator fails, `playwright_smart_locators` intercepts the
|
|
9
|
+
timeout, queries an LLM with the broken selector and live/cached DOM, and
|
|
10
|
+
retries with the top 7 AI-suggested locators. After the run, it writes
|
|
11
|
+
`*-healed.py` suggestion files for review.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install playwright_smart_locators
|
|
17
|
+
playwright install chromium
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Configure
|
|
21
|
+
|
|
22
|
+
In your `conftest.py` (opt-in):
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
import pytest
|
|
26
|
+
from playwright_smart_locators import smart_page
|
|
27
|
+
|
|
28
|
+
@pytest.fixture
|
|
29
|
+
def page(smart_page):
|
|
30
|
+
return smart_page
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
In `pyproject.toml` or `pytest.ini`:
|
|
34
|
+
|
|
35
|
+
```toml
|
|
36
|
+
[tool.pytest.ini_options]
|
|
37
|
+
addopts = [
|
|
38
|
+
"--enable-auto-heal",
|
|
39
|
+
"--ai-model=qwen2.5:7b",
|
|
40
|
+
"--ai-pipe-url=http://localhost:11434",
|
|
41
|
+
"--ai-admin-key=sk-",
|
|
42
|
+
]
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Or via environment variables (recommended for Docker / CI):
|
|
46
|
+
|
|
47
|
+
| Env var | Default | Notes |
|
|
48
|
+
|---|---|---|
|
|
49
|
+
| `ENABLE_AUTO_HEAL` | `false` | `true` / `1` / `yes` / `on` to activate |
|
|
50
|
+
| `AI_MODEL` | `qwen2.5:7b` | Any model name your provider accepts |
|
|
51
|
+
| `AI_PIPE_URL` | `http://localhost:11434` | Base URL — OpenAI provider appends `/v1/chat/completions` |
|
|
52
|
+
| `AI_ADMIN_KEY` | (empty) | Bearer token; leave empty for local Ollama |
|
|
53
|
+
| `AI_PROVIDER` | `openai` | `openai` or `anthropic` |
|
|
54
|
+
| `AI_RATE_PER_MIN` | `30` | In-process token bucket rate |
|
|
55
|
+
|
|
56
|
+
Precedence: **env var > CLI flag > built-in default**. Env wins so Docker / CI configs don't have to be repeated on the command line. Empty env values fall back to the CLI value (so you can set `AI_ADMIN_KEY=` in a `.env` to mean "leave unset" without overriding the CLI flag).
|
|
57
|
+
|
|
58
|
+
**Provider auto-detect**: if `AI_PIPE_URL` ends with `/anthropic` (e.g. `https://api.example.com/anthropic`), the plugin automatically sets `ai_provider=anthropic` and emits a `UserWarning`. This lets Anthropic-compatible services (like MiniMax) work without setting `AI_PROVIDER=anthropic` explicitly. To opt out, set `AI_PIPE_URL` to a path that doesn't end with `/anthropic` (e.g. add a suffix like `/v1`).
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Examples
|
|
62
|
+
export ENABLE_AUTO_HEAL=true
|
|
63
|
+
export AI_MODEL=gpt-4o
|
|
64
|
+
export AI_PIPE_URL=https://api.openai.com
|
|
65
|
+
export AI_ADMIN_KEY=sk-xxx
|
|
66
|
+
pytest
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## AI Providers
|
|
70
|
+
|
|
71
|
+
Built-in:
|
|
72
|
+
- `openai` (also works with Ollama, Open WebUI, vLLM, LocalAI)
|
|
73
|
+
- `anthropic`
|
|
74
|
+
|
|
75
|
+
Register your own:
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
from playwright_smart_locators import register_provider
|
|
79
|
+
|
|
80
|
+
class MyProvider:
|
|
81
|
+
def complete(self, *, system, user, model, timeout=30.0) -> str:
|
|
82
|
+
return '{"locators": [".my-locator"]}'
|
|
83
|
+
|
|
84
|
+
register_provider("custom", MyProvider)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## POM Support
|
|
88
|
+
|
|
89
|
+
When a locator fails inside a Page Object Model method, the auto-healer
|
|
90
|
+
uses `inspect.stack()` to find the real caller file/line. The
|
|
91
|
+
`*-healed.py` is written next to the POM file (e.g. `pages/login_page-healed.py`),
|
|
92
|
+
not the test spec.
|
|
93
|
+
|
|
94
|
+
## CI
|
|
95
|
+
|
|
96
|
+
Disable in CI (no LLM available):
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# CI: don't pass --enable-auto-heal
|
|
100
|
+
pytest --browser=chromium
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## License
|
|
104
|
+
|
|
105
|
+
MIT
|