tamash-playwright 0.8.0-beta.1 → 0.8.0
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.
- package/.env.example +10 -12
- package/README.md +28 -17
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +0 -9
- package/dist/cli/doctor.js.map +1 -1
- package/package.json +1 -1
- package/usage.md +4 -16
package/.env.example
CHANGED
|
@@ -9,11 +9,6 @@ HEALER_ENABLED=true
|
|
|
9
9
|
# for setup.
|
|
10
10
|
HEALER_PROVIDER=ollama
|
|
11
11
|
|
|
12
|
-
# Optional, off by default. If a locator gets healed but the action on it still fails (e.g. the
|
|
13
|
-
# element is covered or needs scrolling into view), the AI can pick a recovery tactic (scroll,
|
|
14
|
-
# force, wait, or dispatch the DOM event directly) instead of giving up immediately.
|
|
15
|
-
# HEALER_ACTION_RECOVERY_ENABLED=true
|
|
16
|
-
|
|
17
12
|
# --- Ollama Cloud (https://ollama.com) ---
|
|
18
13
|
OLLAMA_MODEL=gpt-oss:120b
|
|
19
14
|
OLLAMA_API_KEY=
|
|
@@ -34,16 +29,19 @@ OLLAMA_API_KEY=
|
|
|
34
29
|
# GEMINI_BASE_URL=https://generativelanguage.googleapis.com/v1beta/openai
|
|
35
30
|
|
|
36
31
|
# --- Claude subscription (no API key — uses your existing Claude Pro/Max/Team/Enterprise subscription) ---
|
|
37
|
-
# Requires: npm install @anthropic-ai/claude-
|
|
38
|
-
#
|
|
32
|
+
# Requires: npm install -g @anthropic-ai/claude-code (the CLI, so `claude login` exists to run),
|
|
33
|
+
# and npm install @anthropic-ai/claude-agent-sdk (the SDK tamash-playwright actually calls).
|
|
34
|
+
# Locally: run `claude login` once.
|
|
39
35
|
# In CI: run `claude setup-token` once to mint a 12-month token, then set it as a CI secret below.
|
|
40
36
|
# CLAUDE_SUBSCRIPTION_MODEL=haiku
|
|
41
37
|
# CLAUDE_CODE_OAUTH_TOKEN=
|
|
42
38
|
|
|
43
39
|
# --- GitHub Copilot subscription (no API key — uses your existing Copilot subscription or free tier) ---
|
|
44
|
-
# Requires: npm install @github/copilot
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
#
|
|
40
|
+
# Requires: npm install -g @github/copilot (the CLI, so `copilot` exists to sign in with),
|
|
41
|
+
# and npm install @github/copilot-sdk (the SDK tamash-playwright actually calls).
|
|
42
|
+
# Locally: sign in with the `copilot` CLI once.
|
|
43
|
+
# In GitHub Actions CI: add `permissions: { copilot-requests: write }` to the workflow job — but
|
|
44
|
+
# only works if the repo's owning account/org has Copilot enabled; see README for the personal-
|
|
45
|
+
# account PAT fallback (COPILOT_GITHUB_TOKEN) if it doesn't.
|
|
46
|
+
# In other CI systems: set GITHUB_TOKEN (or COPILOT_GITHUB_TOKEN) to a PAT with "Copilot Requests".
|
|
49
47
|
# COPILOT_SUBSCRIPTION_MODEL=mai-code-1-flash-picker
|
package/README.md
CHANGED
|
@@ -41,9 +41,6 @@ HEALER_ENABLED=true
|
|
|
41
41
|
# Pick one: ollama | openai | anthropic | gemini | claude-subscription | copilot-subscription
|
|
42
42
|
HEALER_PROVIDER=ollama
|
|
43
43
|
|
|
44
|
-
# Optional, off by default — see "Action recovery" below.
|
|
45
|
-
# HEALER_ACTION_RECOVERY_ENABLED=true
|
|
46
|
-
|
|
47
44
|
# --- Ollama Cloud (https://ollama.com) ---
|
|
48
45
|
OLLAMA_MODEL=gpt-oss:120b
|
|
49
46
|
OLLAMA_API_KEY=
|
|
@@ -95,8 +92,14 @@ If you don't have an API key issued to you but do have a personal Claude (Pro/Ma
|
|
|
95
92
|
**Claude subscription** — works both locally and unattended in CI:
|
|
96
93
|
|
|
97
94
|
```sh
|
|
98
|
-
npm install @anthropic-ai/claude-
|
|
99
|
-
|
|
95
|
+
npm install -g @anthropic-ai/claude-code # the CLI itself — needed so `claude login` exists to run.
|
|
96
|
+
# @anthropic-ai/claude-agent-sdk (below) bundles its own
|
|
97
|
+
# copy of the Claude Code binary too, but only for its own
|
|
98
|
+
# internal use — it exposes no `claude` command of its own,
|
|
99
|
+
# so this separate install is still required for the login
|
|
100
|
+
# step below.
|
|
101
|
+
npm install @anthropic-ai/claude-agent-sdk # the SDK — what tamash-playwright actually calls
|
|
102
|
+
claude login # one-time, locally
|
|
100
103
|
```
|
|
101
104
|
|
|
102
105
|
```sh
|
|
@@ -113,8 +116,10 @@ CLAUDE_CODE_OAUTH_TOKEN=the-token-you-copied
|
|
|
113
116
|
**GitHub Copilot subscription** — works locally, and unattended in GitHub Actions specifically:
|
|
114
117
|
|
|
115
118
|
```sh
|
|
116
|
-
npm install @github/copilot
|
|
117
|
-
copilot
|
|
119
|
+
npm install -g @github/copilot # the CLI itself — needed so `copilot` exists to sign in with
|
|
120
|
+
npm install @github/copilot-sdk # the SDK — what tamash-playwright actually calls (wraps the CLI,
|
|
121
|
+
# doesn't replace it, so both installs above are required)
|
|
122
|
+
copilot # sign in once, locally
|
|
118
123
|
```
|
|
119
124
|
|
|
120
125
|
```sh
|
|
@@ -122,14 +127,25 @@ HEALER_PROVIDER=copilot-subscription
|
|
|
122
127
|
COPILOT_SUBSCRIPTION_MODEL=mai-code-1-flash-picker
|
|
123
128
|
```
|
|
124
129
|
|
|
125
|
-
In a GitHub Actions workflow, no secret is needed at all — just grant the job permission to use it:
|
|
130
|
+
In a GitHub Actions workflow, no secret is needed at all *if the repo's owning account/org has Copilot enabled* — just grant the job permission to use it:
|
|
126
131
|
|
|
127
132
|
```yaml
|
|
128
133
|
permissions:
|
|
129
134
|
copilot-requests: write
|
|
130
135
|
```
|
|
131
136
|
|
|
132
|
-
|
|
137
|
+
**Gotcha, confirmed by real testing, not just docs**: this only works if Copilot is enabled for whoever *owns the repo* — an organization, if that's who the repo belongs to. A personal Copilot subscription on your own account does **not** carry over to a separate organization's repos, even one you administer yourself; organizations need their own Copilot enablement (Business/Enterprise plan, or an explicit org policy), which is a different thing from an individual plan. If the job fails with `Authorization error, you may need to run /login` despite the permission being set correctly, this is almost certainly why.
|
|
138
|
+
|
|
139
|
+
The fix: use a personal-account PAT instead of the ambient token, so the request explicitly carries your own subscription regardless of which org's repo the workflow runs in:
|
|
140
|
+
|
|
141
|
+
1. Create a fine-grained personal access token: **Resource owner** = your personal account (not the org), **Repository access** = Public Repositories (read-only) is enough if the repo is public, **Account permissions → Copilot Requests** = Read.
|
|
142
|
+
2. Add it as a repo secret — any name works, but `COPILOT_GITHUB_TOKEN` is worth using specifically, since that's the exact env var the Copilot SDK checks *ahead of* `GITHUB_TOKEN` in its own auth precedence:
|
|
143
|
+
```yaml
|
|
144
|
+
env:
|
|
145
|
+
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Outside GitHub Actions entirely, the same PAT approach applies — set `GITHUB_TOKEN` (or `COPILOT_GITHUB_TOKEN`) to a personal access token with the "Copilot Requests" scope.
|
|
133
149
|
|
|
134
150
|
**One thing worth knowing**: only Claude and Copilot support this "subscription, no API key, works in CI too" combination — a ChatGPT or Google AI subscription can back local runs the same way (via those vendors' own CLIs), but neither vendor currently offers a way to use that subscription unattended in CI, so CI there still needs a plain API key (the existing `openai`/`gemini` providers above).
|
|
135
151
|
|
|
@@ -160,10 +176,9 @@ It checks:
|
|
|
160
176
|
|
|
161
177
|
1. **AI connectivity** — confirms `HEALER_ENABLED`/`HEALER_PROVIDER` are set correctly and actually calls your configured provider to make sure the API key and model work.
|
|
162
178
|
2. **`actionTimeout` configuration** — checks your `playwright.config.ts` for an `actionTimeout` set well below your test `timeout` (see above); flags it if missing or too close to the test timeout, since that silently starves self-healing of any time to run.
|
|
163
|
-
3. **
|
|
164
|
-
4. **
|
|
165
|
-
5. **
|
|
166
|
-
6. **Locators written directly in test files** — flags any locator defined inline in a test rather than inside a Page Object class, which is a Playwright best practice regardless of self-healing: it keeps tests readable and means a UI change only needs a fix in one place.
|
|
179
|
+
3. **Vision capability** — whether your configured model is expected to support the screenshot-based fallback (see below), based on its name.
|
|
180
|
+
4. **Missing `.describe()` labels** — scans your test files (`tests/` by default, or pass `--dir <path>`) for locators that don't have a `.describe('...')` label, and flags the ones most worth fixing (raw CSS/XPath selectors first).
|
|
181
|
+
5. **Locators written directly in test files** — flags any locator defined inline in a test rather than inside a Page Object class, which is a Playwright best practice regardless of self-healing: it keeps tests readable and means a UI change only needs a fix in one place.
|
|
167
182
|
|
|
168
183
|
If it finds issues, the fastest fix is to open the project in an AI coding assistant (Claude Code, Cursor, GitHub Copilot, etc.) and ask it to address what it flagged — add `.describe()` calls, or extract locators into Page Object classes. You can also add a standing rule to that assistant's instructions/skill file (e.g. `CLAUDE.md`, `.cursor/rules`, `.github/copilot-instructions.md`) so it follows both practices automatically on any new test code going forward.
|
|
169
184
|
|
|
@@ -263,10 +278,6 @@ Not every healed selector is equally durable. One with a real id, test id, or ac
|
|
|
263
278
|
|
|
264
279
|
Sometimes an element has nothing useful to match on by text — an icon-only button with no label, or several visually distinct elements that all look identical in the accessibility tree. If your configured model supports image input (e.g. `gpt-4o`, `claude-haiku-4-5`, `gemini-3.6-flash`), `tamash-playwright` automatically falls back to a screenshot-based search after the normal text-based attempt fails — no separate setup, it just uses the same provider and API key from Step 2. Run `npx tamash-playwright doctor` to check whether your configured model is expected to support this.
|
|
265
280
|
|
|
266
|
-
## Action recovery (optional)
|
|
267
|
-
|
|
268
|
-
Occasionally a locator heals correctly — the AI found the right element — but the *action* on it still fails, e.g. it's covered by an overlay or needs scrolling into view first. Set `HEALER_ACTION_RECOVERY_ENABLED=true` to let the AI pick a recovery tactic from a fixed, safe set (scroll into view, retry bypassing actionability checks, wait briefly and retry, or dispatch the DOM event directly) before giving up. It's off by default since it's a second, more speculative layer of intervention beyond selector healing — the AI only ever picks from that fixed menu, it never decides how to interact with the page on its own.
|
|
269
|
-
|
|
270
281
|
## Not paying for the same heal twice
|
|
271
282
|
|
|
272
283
|
Once a locator heals successfully, `tamash-playwright` remembers the fix in `.tamash-playwright/heals.jsonl` — the same file `apply-heals` reads (see below). The next time that exact locator breaks the same way, it tries the previously-confirmed selector *first*, with no ARIA snapshot and no AI call. Only if that no longer works (the page changed again) does it fall through to a fresh snapshot-and-AI-call, exactly as before — so there's no correctness risk in trying the cached selector, only a cost/time saving when it still works.
|
package/dist/cli/doctor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AA8IA,wBAAsB,SAAS,CAAC,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBlE"}
|
package/dist/cli/doctor.js
CHANGED
|
@@ -19,15 +19,6 @@ async function checkProviderConnectivity() {
|
|
|
19
19
|
console.log(' Healing is currently OFF. Set HEALER_ENABLED=true (or remove the line) to turn it back on.');
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
22
|
-
console.log(`HEALER_ACTION_RECOVERY_ENABLED: ${process.env.HEALER_ACTION_RECOVERY_ENABLED ?? '(unset — defaults to false)'}`);
|
|
23
|
-
if ((0, healer_1.isActionRecoveryEnabled)()) {
|
|
24
|
-
console.log(' Action recovery is ON — if a locator heals but the action on it still fails, the AI may retry');
|
|
25
|
-
console.log(' it (scroll into view, force, wait, or dispatch the DOM event directly) before giving up.');
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
console.log(' Action recovery is OFF (opt-in, off by default). Set HEALER_ACTION_RECOVERY_ENABLED=true to turn it on.');
|
|
29
|
-
}
|
|
30
|
-
console.log('');
|
|
31
22
|
const providerName = process.env.HEALER_PROVIDER;
|
|
32
23
|
if (!providerName) {
|
|
33
24
|
console.log('[WARN] HEALER_PROVIDER is not set. No AI provider is configured, so self-healing will never');
|
package/dist/cli/doctor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AACxB,oDAA4B;AAC5B,mDAAsD;AACtD,
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tamash-playwright",
|
|
3
|
-
"version": "0.8.0
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Plug and Play Self-healing for Playwright and automatically recovers broken selectors using an AI model (Ollama, OpenAI, Anthropic, Gemini, or a Claude/GitHub Copilot subscription).",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
package/usage.md
CHANGED
|
@@ -17,7 +17,6 @@ For a quicker, high-level overview see [README.md](README.md); this file is the
|
|
|
17
17
|
- [Finding elements by structure](#when-theres-no-name-to-match-finding-elements-by-structure)
|
|
18
18
|
- [When a fix needs a second look](#when-a-fix-needs-a-second-look)
|
|
19
19
|
- [Vision fallback](#when-text-alone-isnt-enough-vision-fallback)
|
|
20
|
-
- [Action recovery](#action-recovery-optional)
|
|
21
20
|
- [Not paying for the same heal twice](#not-paying-for-the-same-heal-twice)
|
|
22
21
|
- [Making a heal permanent: `apply-heals`](#making-a-heal-permanent-apply-heals)
|
|
23
22
|
- [Proving a fix works: `verify-heals.cjs`](#proving-a-fix-actually-works-verify-healscjs)
|
|
@@ -55,9 +54,6 @@ HEALER_ENABLED=true
|
|
|
55
54
|
# Pick one: ollama | openai | anthropic | gemini
|
|
56
55
|
HEALER_PROVIDER=ollama
|
|
57
56
|
|
|
58
|
-
# Optional, off by default — see "Action recovery" below.
|
|
59
|
-
# HEALER_ACTION_RECOVERY_ENABLED=true
|
|
60
|
-
|
|
61
57
|
# --- Ollama Cloud (https://ollama.com) ---
|
|
62
58
|
OLLAMA_MODEL=gpt-oss:120b
|
|
63
59
|
OLLAMA_API_KEY=
|
|
@@ -108,10 +104,9 @@ npx tamash-playwright doctor
|
|
|
108
104
|
|---|-------|---------------|
|
|
109
105
|
| 1 | AI connectivity | Confirms `HEALER_ENABLED`/`HEALER_PROVIDER` are set, and actually calls the provider to verify the key and model work. |
|
|
110
106
|
| 2 | `actionTimeout` | Reads `playwright.config.ts`; flags a missing or too-close-to-`timeout` value. |
|
|
111
|
-
| 3 |
|
|
112
|
-
| 4 |
|
|
113
|
-
| 5 |
|
|
114
|
-
| 6 | Inline locators | Flags locators written directly in test files rather than a Page Object class. |
|
|
107
|
+
| 3 | Vision capability | Checks by name whether your configured model is expected to support the screenshot fallback. |
|
|
108
|
+
| 4 | Missing `.describe()` | Scans `tests/` (or `--dir <path>`) for locators without a label, raw CSS/XPath first. |
|
|
109
|
+
| 5 | Inline locators | Flags locators written directly in test files rather than a Page Object class. |
|
|
115
110
|
|
|
116
111
|
If it finds issues, the fastest fix is to open the project in an AI coding assistant and ask it to address what's flagged — add `.describe()` calls, or extract locators into Page Objects. A standing rule in that assistant's instructions file (`CLAUDE.md`, `.cursor/rules`, etc.) keeps it doing both automatically going forward.
|
|
117
112
|
|
|
@@ -208,12 +203,6 @@ If the retry doesn't resolve either, healing falls through to the vision fallbac
|
|
|
208
203
|
|
|
209
204
|
Sometimes an element has nothing useful to match on by text — an icon-only button with no label, or several visually distinct elements that look identical in the accessibility tree. If your configured model supports image input (`gpt-4o`, `claude-haiku-4-5`, `gemini-3.6-flash`, …), `tamash-playwright` automatically falls back to a screenshot-based search after the normal text attempt fails — same provider, same key, no separate setup. Run `npx tamash-playwright doctor` to check whether your model is expected to support it.
|
|
210
205
|
|
|
211
|
-
## Action recovery (optional)
|
|
212
|
-
|
|
213
|
-
Occasionally a locator heals correctly — the AI found the right element — but the *action* on it still fails: covered by an overlay, needs scrolling into view first. Set `HEALER_ACTION_RECOVERY_ENABLED=true` to let the AI pick a tactic from a fixed, safe menu (scroll into view, bypass actionability checks, wait and retry, or dispatch the DOM event directly) before giving up.
|
|
214
|
-
|
|
215
|
-
Off by default — it's a second, more speculative layer beyond selector healing. The AI only ever picks from that fixed menu; it never decides how to interact with the page on its own.
|
|
216
|
-
|
|
217
206
|
## Not paying for the same heal twice
|
|
218
207
|
|
|
219
208
|
Once a locator heals successfully, `tamash-playwright` remembers the fix in `.tamash-playwright/heals.jsonl`. The next time that exact locator breaks the same way, it tries the previously-confirmed selector *first* — no ARIA snapshot, no AI call. Only if that no longer works does it fall through to a fresh snapshot-and-AI-call, exactly as before.
|
|
@@ -512,7 +501,6 @@ The same detail prints to the console as it happens:
|
|
|
512
501
|
|----------|---------|---------|
|
|
513
502
|
| `HEALER_ENABLED` | `true` | Master on/off switch. Any value other than `false`/`0` leaves healing on. |
|
|
514
503
|
| `HEALER_PROVIDER` | unset | `ollama` \| `openai` \| `anthropic` \| `gemini`. Unset or missing key/model still allows cache hits, just no fresh AI calls. |
|
|
515
|
-
| `HEALER_ACTION_RECOVERY_ENABLED` | `false` | Opt-in second-layer recovery for actionability failures on an already-correctly-healed locator. |
|
|
516
504
|
| `OLLAMA_MODEL` / `OLLAMA_API_KEY` | — | Ollama Cloud provider config. |
|
|
517
505
|
| `OPENAI_MODEL` / `OPENAI_API_KEY` | — | OpenAI provider config. |
|
|
518
506
|
| `ANTHROPIC_MODEL` / `ANTHROPIC_API_KEY` | — | Anthropic (Claude) provider config. |
|
|
@@ -522,7 +510,7 @@ The same detail prints to the console as it happens:
|
|
|
522
510
|
|
|
523
511
|
| Command | Flags | What it does |
|
|
524
512
|
|---------|-------|---------------|
|
|
525
|
-
| `npx tamash-playwright doctor` | `--dir <path>` | Pre-flight checks: AI connectivity, `actionTimeout`,
|
|
513
|
+
| `npx tamash-playwright doctor` | `--dir <path>` | Pre-flight checks: AI connectivity, `actionTimeout`, vision capability, missing `.describe()`, inline locators. |
|
|
526
514
|
| `npx tamash-playwright apply-heals` | `--dry-run` | Preview fixes without writing anything (including `verify-heals.cjs` — see below). |
|
|
527
515
|
| | `--logs-dir <path>` | Merge every `heals.jsonl` found under `<path>` (any nesting) instead of the local log — for sharded CI. |
|
|
528
516
|
|