tamash-playwright 0.6.0 → 0.6.1

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/README.md CHANGED
@@ -1,207 +1,207 @@
1
- # tamash-playwright
2
-
3
- `tamash-playwright` is a plug and play self-healing solution for any Playwright test framework. All you need to do is install the package, update your AI API key details, and import `test` from `tamash-playwright`.
4
-
5
- That's it. No code changes required if you're following standard Playwright best practices.
6
-
7
- ### Why you need this
8
-
9
- Websites change often. A button gets renamed or moved, and your test can't find it anymore — even though the app still works fine for real users. Normally, that just means a broken test.
10
-
11
- `tamash-playwright` fixes this automatically. When a test can't find an element, it asks an AI model to find it on the current page and tries again. If it succeeds, your test keeps going. If not, it fails normally, just like before.
12
-
13
- **Want to see it working before you set it up yourself?** Clone the sample repo — [github.com/qtpsudhakarproducts/tamash-playwright-typescript-playwright](https://github.com/qtpsudhakarproducts/tamash-playwright-typescript-playwright) — a full worked example with both a plain-locator test and a Page Object Model test, an intentionally broken selector, and step-by-step setup instructions.
14
-
15
- Here are the detailed steps to use this package.
16
-
17
- ## Step 1: Install it
18
-
19
- ```sh
20
- npm install tamash-playwright
21
- ```
22
-
23
- You also need Playwright's own test package, if you don't already have it:
24
-
25
- ```sh
26
- npm install -D @playwright/test
27
- ```
28
-
29
- ## Step 2: Connect an AI model
30
-
31
- `tamash-playwright` needs an AI model to decide where a broken element actually went. Pick one of Ollama, OpenAI, Anthropic (Claude), or Google Gemini, and give it an API key.
32
-
33
- Create a file named `.env` in your project folder:
34
-
35
- ```sh
36
- # Master on/off switch. Leave this as true, or remove the line entirely.
37
- HEALER_ENABLED=true
38
-
39
- # Pick one: ollama | openai | anthropic | gemini
40
- HEALER_PROVIDER=ollama
41
-
42
- # Optional, off by default — see "Action recovery" below.
43
- # HEALER_ACTION_RECOVERY_ENABLED=true
44
-
45
- # --- Ollama Cloud (https://ollama.com) ---
46
- OLLAMA_MODEL=gpt-oss:120b
47
- OLLAMA_API_KEY=
48
-
49
- # --- OpenAI ---
50
- # OPENAI_MODEL=gpt-4.1-mini
51
- # OPENAI_API_KEY=
52
-
53
- # --- Anthropic (Claude) ---
54
- # ANTHROPIC_MODEL=claude-haiku-4-5
55
- # ANTHROPIC_API_KEY=
56
-
57
- # --- Google Gemini ---
58
- # GEMINI_MODEL=
59
- # GEMINI_API_KEY=
60
- ```
61
-
62
- Just fill in the API key and model for whichever one you want to use, and leave the rest as-is (or delete them).
63
-
64
- ### Getting a free Ollama key (fastest way to get started)
65
-
66
- Ollama Cloud is a quick, free way to get an API key without signing up for OpenAI/Anthropic/Gemini billing.
67
-
68
- 1. Go to [ollama.com](https://ollama.com/) and create an account.
69
- 2. Once signed in, go to [ollama.com/settings/keys](https://ollama.com/settings/keys).
70
- 3. Create a new API key and copy it.
71
- 4. Paste it into your `.env` file:
72
-
73
- ```sh
74
- HEALER_ENABLED=true
75
- HEALER_PROVIDER=ollama
76
- OLLAMA_MODEL=gpt-oss:120b
77
- OLLAMA_API_KEY=paste_your_key_here
78
- ```
79
-
80
- That's all you need — no other variables required.
81
-
82
- ### Important: set `actionTimeout` in your `playwright.config.ts`
83
-
84
- By default, Playwright lets a broken locator retry silently for your *entire* test timeout before it ever throws an error — which means self-healing never gets a turn at all, since it only kicks in once an action actually fails. Set `actionTimeout` to something well below your test timeout so a broken locator fails fast, leaving real time for healing to run:
85
-
86
- ```ts
87
- export default defineConfig({
88
- timeout: 60000, // your overall test timeout
89
- use: {
90
- actionTimeout: 8000, // must be comfortably less than the test timeout above
91
- },
92
- });
93
- ```
94
-
95
- Without this, healing attempts will show `stage=no_snapshot` in the console and never recover anything — not because healing failed, but because it never had time to run before the whole test was torn down.
96
-
97
- ## Step 3: Check your setup
98
-
99
- Run the built-in doctor command to confirm everything's wired up correctly before you rely on it:
100
-
101
- ```sh
102
- npx tamash-playwright doctor
103
- ```
104
-
105
- It checks:
106
-
107
- 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.
108
- 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.
109
- 3. **Action recovery status** — whether `HEALER_ACTION_RECOVERY_ENABLED` is on (see below).
110
- 4. **Vision capability** — whether your configured model is expected to support the screenshot-based fallback (see below), based on its name.
111
- 5. **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).
112
- 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.
113
-
114
- 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.
115
-
116
- ## Step 4: Use it in your tests
117
-
118
- Change one line at the top of your test file — everything else about how you write tests stays exactly the same:
119
-
120
- ```ts
121
- // Before
122
- import { test, expect } from '@playwright/test';
123
-
124
- // After
125
- import { test, expect } from 'tamash-playwright';
126
- ```
127
-
128
- That's it. Write your tests as normal:
129
-
130
- ```ts
131
- import { test, expect } from 'tamash-playwright';
132
-
133
- test('logs in', async ({ page }) => {
134
- await page.goto('/');
135
- const txtUserName = page.locator('input[name="username"]').describe('User Name Textbox');
136
- await txtUserName.fill('testadmin');
137
-
138
- const txtPassword = page.locator('input[placeholder="Password"]').describe('Password Textbox');
139
- await txtPassword.fill('secret');
140
-
141
- const btnLogin = page.locator('button[type="submit"]').describe('Login Button');
142
- await btnLogin.click();
143
-
144
- await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
145
- });
146
- ```
147
-
148
- ### A quick tip for better results
149
-
150
- If you're using plain CSS selectors (like `page.locator('input[name="username"]')`) rather than Playwright's more descriptive locators (`getByRole`, `getByPlaceholder`, etc.), it helps to add a short, human-readable label so the healer knows what it's actually looking for. Chain `.describe('...')` right onto the locator:
151
-
152
- ```ts
153
- test('login test using CSS Selectors', async ({ page }) => {
154
- await page.goto('https://example.com/auth/login');
155
-
156
- const txtUserName = page.locator('input[name="username"]').describe('User Name Textbox');
157
- await txtUserName.fill('testadmin');
158
-
159
- const txtPassword = page.locator('input[placeholder="Password"]').describe('Password Textbox');
160
- await txtPassword.fill('secret');
161
-
162
- const btnLogin = page.locator('button[type="submit"]').describe('Login Button');
163
- await btnLogin.click();
164
-
165
- await expect(page.locator('h6')).toHaveText('Dashboard');
166
- });
167
- ```
168
-
169
- This step is optional, but recommended — without it, the healer has to guess purely from a broken CSS selector, which gives it a lot less to work with.
170
-
171
- ## What else it heals — no extra setup needed
172
-
173
- Beyond a single broken `click`/`fill`/`getByRole` on the main page, all of this works automatically once you've done Steps 1–2:
174
-
175
- - **Popups and extra tabs.** A page opened via `context.newPage()`, `window.open`, or a `target="_blank"` link is just as healing-aware as your main `page` — no manual wrapping needed.
176
- - **Elements inside `<iframe>`s.** `page.frameLocator('#my-iframe')` and anything chained off it heals the same way, scoped correctly to the iframe's own document.
177
- - **Most of the Playwright API surface**, not just clicks and fills — `check`, `selectOption`, `dragTo`, `dispatchEvent`, read methods like `textContent`/`getAttribute`/`isChecked`, `screenshot`, and more. Methods that can't be safely healed by guessing a replacement element (`dragTo`, `drop`) are still reported honestly on failure, they're just never silently retried with a different element.
178
-
179
- ## When text alone isn't enough: vision fallback
180
-
181
- 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-2.0-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.
182
-
183
- ## Action recovery (optional)
184
-
185
- 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.
186
-
187
- ## Checking what actually happened
188
-
189
- Every healing attempt — whether it succeeded or not — shows up in Playwright's own HTML report (`npx playwright show-report`), no separate report to check:
190
-
191
- - An annotation on the test summarizing what happened, e.g. `Recovered using ollama:gpt-oss:120b (role:button:Submit)`.
192
- - A JSON attachment with the full detail: which provider was used, whether the vision or action-recovery fallback was involved, the AI's suggested selector, token cost, and — if it didn't heal — which stage it stopped at (e.g. `ai_declined`, `replay_failed`).
193
- - Exactly where in your own code the locator was created — a test file or a Page Object class, whichever it really is — so you know which line to go fix even if you never look at the healing report again.
194
-
195
- The same detail is also printed to the console as it happens, one line per attempt:
196
-
197
- ```
198
- [self-healer] src/pages/loginpage.ts:11 — locator.fill "Username Textbox" -> HEALED [provider=ollama:gpt-oss:120b, vision=no, actionRecovery=no, suggested="role:textbox:Username", 620 tokens (489 input + 131 output)] — locator.fill: Timeout 8000ms exceeded.
199
- ```
200
-
201
- ## License
202
-
203
- Free to use, including commercially. The source code may not be copied, modified, redistributed, or resold without prior written permission. See the LICENSE file included in this package for the full terms.
204
-
205
- ## Support
206
-
207
- For questions or concerns, contact us at support@vibetestq.com.
1
+ # tamash-playwright
2
+
3
+ `tamash-playwright` is a plug and play self-healing solution for any Playwright test framework. All you need to do is install the package, update your AI API key details, and import `test` from `tamash-playwright`.
4
+
5
+ That's it. No code changes required if you're following standard Playwright best practices.
6
+
7
+ ### Why you need this
8
+
9
+ Websites change often. A button gets renamed or moved, and your test can't find it anymore — even though the app still works fine for real users. Normally, that just means a broken test.
10
+
11
+ `tamash-playwright` fixes this automatically. When a test can't find an element, it asks an AI model to find it on the current page and tries again. If it succeeds, your test keeps going. If not, it fails normally, just like before.
12
+
13
+ **Want to see it working before you set it up yourself?** Clone the sample repo — [github.com/qtpsudhakarproducts/tamash-playwright-typescript-playwright](https://github.com/qtpsudhakarproducts/tamash-playwright-typescript-playwright) — a full worked example with both a plain-locator test and a Page Object Model test, an intentionally broken selector, and step-by-step setup instructions.
14
+
15
+ Here are the detailed steps to use this package.
16
+
17
+ ## Step 1: Install it
18
+
19
+ ```sh
20
+ npm install tamash-playwright
21
+ ```
22
+
23
+ You also need Playwright's own test package, if you don't already have it:
24
+
25
+ ```sh
26
+ npm install -D @playwright/test
27
+ ```
28
+
29
+ ## Step 2: Connect an AI model
30
+
31
+ `tamash-playwright` needs an AI model to decide where a broken element actually went. Pick one of Ollama, OpenAI, Anthropic (Claude), or Google Gemini, and give it an API key.
32
+
33
+ Create a file named `.env` in your project folder:
34
+
35
+ ```sh
36
+ # Master on/off switch. Leave this as true, or remove the line entirely.
37
+ HEALER_ENABLED=true
38
+
39
+ # Pick one: ollama | openai | anthropic | gemini
40
+ HEALER_PROVIDER=ollama
41
+
42
+ # Optional, off by default — see "Action recovery" below.
43
+ # HEALER_ACTION_RECOVERY_ENABLED=true
44
+
45
+ # --- Ollama Cloud (https://ollama.com) ---
46
+ OLLAMA_MODEL=gpt-oss:120b
47
+ OLLAMA_API_KEY=
48
+
49
+ # --- OpenAI ---
50
+ # OPENAI_MODEL=gpt-4.1-mini
51
+ # OPENAI_API_KEY=
52
+
53
+ # --- Anthropic (Claude) ---
54
+ # ANTHROPIC_MODEL=claude-haiku-4-5
55
+ # ANTHROPIC_API_KEY=
56
+
57
+ # --- Google Gemini ---
58
+ # GEMINI_MODEL=
59
+ # GEMINI_API_KEY=
60
+ ```
61
+
62
+ Just fill in the API key and model for whichever one you want to use, and leave the rest as-is (or delete them).
63
+
64
+ ### Getting a free Ollama key (fastest way to get started)
65
+
66
+ Ollama Cloud is a quick, free way to get an API key without signing up for OpenAI/Anthropic/Gemini billing.
67
+
68
+ 1. Go to [ollama.com](https://ollama.com/) and create an account.
69
+ 2. Once signed in, go to [ollama.com/settings/keys](https://ollama.com/settings/keys).
70
+ 3. Create a new API key and copy it.
71
+ 4. Paste it into your `.env` file:
72
+
73
+ ```sh
74
+ HEALER_ENABLED=true
75
+ HEALER_PROVIDER=ollama
76
+ OLLAMA_MODEL=gpt-oss:120b
77
+ OLLAMA_API_KEY=paste_your_key_here
78
+ ```
79
+
80
+ That's all you need — no other variables required.
81
+
82
+ ### Important: set `actionTimeout` in your `playwright.config.ts`
83
+
84
+ By default, Playwright lets a broken locator retry silently for your *entire* test timeout before it ever throws an error — which means self-healing never gets a turn at all, since it only kicks in once an action actually fails. Set `actionTimeout` to something well below your test timeout so a broken locator fails fast, leaving real time for healing to run:
85
+
86
+ ```ts
87
+ export default defineConfig({
88
+ timeout: 60000, // your overall test timeout
89
+ use: {
90
+ actionTimeout: 8000, // must be comfortably less than the test timeout above
91
+ },
92
+ });
93
+ ```
94
+
95
+ Without this, healing attempts will show `stage=no_snapshot` in the console and never recover anything — not because healing failed, but because it never had time to run before the whole test was torn down.
96
+
97
+ ## Step 3: Check your setup
98
+
99
+ Run the built-in doctor command to confirm everything's wired up correctly before you rely on it:
100
+
101
+ ```sh
102
+ npx tamash-playwright doctor
103
+ ```
104
+
105
+ It checks:
106
+
107
+ 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.
108
+ 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.
109
+ 3. **Action recovery status** — whether `HEALER_ACTION_RECOVERY_ENABLED` is on (see below).
110
+ 4. **Vision capability** — whether your configured model is expected to support the screenshot-based fallback (see below), based on its name.
111
+ 5. **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).
112
+ 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.
113
+
114
+ 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.
115
+
116
+ ## Step 4: Use it in your tests
117
+
118
+ Change one line at the top of your test file — everything else about how you write tests stays exactly the same:
119
+
120
+ ```ts
121
+ // Before
122
+ import { test, expect } from '@playwright/test';
123
+
124
+ // After
125
+ import { test, expect } from 'tamash-playwright';
126
+ ```
127
+
128
+ That's it. Write your tests as normal:
129
+
130
+ ```ts
131
+ import { test, expect } from 'tamash-playwright';
132
+
133
+ test('logs in', async ({ page }) => {
134
+ await page.goto('/');
135
+ const txtUserName = page.locator('input[name="username"]').describe('User Name Textbox');
136
+ await txtUserName.fill('testadmin');
137
+
138
+ const txtPassword = page.locator('input[placeholder="Password"]').describe('Password Textbox');
139
+ await txtPassword.fill('secret');
140
+
141
+ const btnLogin = page.locator('button[type="submit"]').describe('Login Button');
142
+ await btnLogin.click();
143
+
144
+ await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
145
+ });
146
+ ```
147
+
148
+ ### A quick tip for better results
149
+
150
+ If you're using plain CSS selectors (like `page.locator('input[name="username"]')`) rather than Playwright's more descriptive locators (`getByRole`, `getByPlaceholder`, etc.), it helps to add a short, human-readable label so the healer knows what it's actually looking for. Chain `.describe('...')` right onto the locator:
151
+
152
+ ```ts
153
+ test('login test using CSS Selectors', async ({ page }) => {
154
+ await page.goto('https://example.com/auth/login');
155
+
156
+ const txtUserName = page.locator('input[name="username"]').describe('User Name Textbox');
157
+ await txtUserName.fill('testadmin');
158
+
159
+ const txtPassword = page.locator('input[placeholder="Password"]').describe('Password Textbox');
160
+ await txtPassword.fill('secret');
161
+
162
+ const btnLogin = page.locator('button[type="submit"]').describe('Login Button');
163
+ await btnLogin.click();
164
+
165
+ await expect(page.locator('h6')).toHaveText('Dashboard');
166
+ });
167
+ ```
168
+
169
+ This step is optional, but recommended — without it, the healer has to guess purely from a broken CSS selector, which gives it a lot less to work with.
170
+
171
+ ## What else it heals — no extra setup needed
172
+
173
+ Beyond a single broken `click`/`fill`/`getByRole` on the main page, all of this works automatically once you've done Steps 1–2:
174
+
175
+ - **Popups and extra tabs.** A page opened via `context.newPage()`, `window.open`, or a `target="_blank"` link is just as healing-aware as your main `page` — no manual wrapping needed.
176
+ - **Elements inside `<iframe>`s.** `page.frameLocator('#my-iframe')` and anything chained off it heals the same way, scoped correctly to the iframe's own document.
177
+ - **Most of the Playwright API surface**, not just clicks and fills — `check`, `selectOption`, `dragTo`, `dispatchEvent`, read methods like `textContent`/`getAttribute`/`isChecked`, `screenshot`, and more. Methods that can't be safely healed by guessing a replacement element (`dragTo`, `drop`) are still reported honestly on failure, they're just never silently retried with a different element.
178
+
179
+ ## When text alone isn't enough: vision fallback
180
+
181
+ 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-2.0-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.
182
+
183
+ ## Action recovery (optional)
184
+
185
+ 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.
186
+
187
+ ## Checking what actually happened
188
+
189
+ Every healing attempt — whether it succeeded or not — shows up in Playwright's own HTML report (`npx playwright show-report`), no separate report to check:
190
+
191
+ - An annotation on the test summarizing what happened, e.g. `Recovered using ollama:gpt-oss:120b (role:button:Submit)`.
192
+ - A JSON attachment with the full detail: which provider was used, whether the vision or action-recovery fallback was involved, the AI's suggested selector, token cost, and — if it didn't heal — which stage it stopped at (e.g. `ai_declined`, `replay_failed`).
193
+ - Exactly where in your own code the locator was created — a test file or a Page Object class, whichever it really is — so you know which line to go fix even if you never look at the healing report again.
194
+
195
+ The same detail is also printed to the console as it happens, one line per attempt:
196
+
197
+ ```
198
+ [self-healer] src/pages/loginpage.ts:11 — locator.fill "Username Textbox" -> HEALED [provider=ollama:gpt-oss:120b, vision=no, actionRecovery=no, suggested="role:textbox:Username", 620 tokens (489 input + 131 output)] — locator.fill: Timeout 8000ms exceeded.
199
+ ```
200
+
201
+ ## License
202
+
203
+ Free to use, including commercially. The source code may not be copied, modified, redistributed, or resold without prior written permission. See the LICENSE file included in this package for the full terms.
204
+
205
+ ## Support
206
+
207
+ For questions or concerns, contact us at support@vibetestq.com.
@@ -1 +1 @@
1
- {"version":3,"file":"scanActionTimeout.d.ts","sourceRoot":"","sources":["../../src/cli/scanActionTimeout.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,kBAAkB,GAC1B;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,GACvB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GACzC;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAuB5F,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAsB,GAAG,kBAAkB,CAoBlF"}
1
+ {"version":3,"file":"scanActionTimeout.d.ts","sourceRoot":"","sources":["../../src/cli/scanActionTimeout.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,kBAAkB,GAC1B;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,GACvB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GACzC;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AA6E5F,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAsB,GAAG,kBAAkB,CAoBlF"}
@@ -22,6 +22,54 @@ function extractNumber(content, key) {
22
22
  const match = content.match(new RegExp(`\\b${key}\\s*:\\s*(\\d+)`));
23
23
  return match ? Number(match[1]) : undefined;
24
24
  }
25
+ // Strips `//` and `/* */` comments before extractNumber ever sees the text — otherwise a
26
+ // commented-out `// actionTimeout: 8000,` reads as active, which is worse than not checking at
27
+ // all (a confident false "OK" on the exact footgun this check exists to catch). Has to respect
28
+ // string boundaries so a `//` inside a legitimate value (e.g. `baseURL: 'https://...'`) is never
29
+ // mistaken for a comment start — same character-scanning approach as findFactoryCallOnLine in
30
+ // applyHeals.ts, not a real parser, just comment/string-aware instead of comment-blind.
31
+ function stripComments(content) {
32
+ let result = '';
33
+ let i = 0;
34
+ let inString = null;
35
+ while (i < content.length) {
36
+ const ch = content[i];
37
+ if (inString) {
38
+ result += ch;
39
+ if (ch === '\\') {
40
+ result += content[i + 1] ?? '';
41
+ i += 2;
42
+ continue;
43
+ }
44
+ if (ch === inString) {
45
+ inString = null;
46
+ }
47
+ i++;
48
+ continue;
49
+ }
50
+ if (ch === '"' || ch === "'" || ch === '`') {
51
+ inString = ch;
52
+ result += ch;
53
+ i++;
54
+ continue;
55
+ }
56
+ if (ch === '/' && content[i + 1] === '/') {
57
+ while (i < content.length && content[i] !== '\n')
58
+ i++;
59
+ continue;
60
+ }
61
+ if (ch === '/' && content[i + 1] === '*') {
62
+ i += 2;
63
+ while (i < content.length && !(content[i] === '*' && content[i + 1] === '/'))
64
+ i++;
65
+ i += 2;
66
+ continue;
67
+ }
68
+ result += ch;
69
+ i++;
70
+ }
71
+ return result;
72
+ }
25
73
  // A plain regex scan over the config file's text, not a real parser — same "good enough for a
26
74
  // human to review" philosophy as scanDescribe.ts. Exists to catch the single most common
27
75
  // self-healing footgun: without an `actionTimeout` well below the test `timeout`, a broken locator
@@ -32,7 +80,7 @@ function checkActionTimeout(cwd = process.cwd()) {
32
80
  if (!configFile) {
33
81
  return { status: 'no_config' };
34
82
  }
35
- const content = fs_1.default.readFileSync(configFile, 'utf-8');
83
+ const content = stripComments(fs_1.default.readFileSync(configFile, 'utf-8'));
36
84
  const relativeFile = path_1.default.relative(cwd, configFile);
37
85
  const actionTimeout = extractNumber(content, 'actionTimeout');
38
86
  if (actionTimeout === undefined) {
@@ -1 +1 @@
1
- {"version":3,"file":"scanActionTimeout.js","sourceRoot":"","sources":["../../src/cli/scanActionTimeout.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,gDAAwB;AAExB,MAAM,gBAAgB,GAAG,CAAC,sBAAsB,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,uBAAuB,CAAC,CAAC;AAQ5H,SAAS,cAAc,CAAC,GAAW;IACjC,KAAK,MAAM,IAAI,IAAI,gBAAgB,EAAE,CAAC;QACpC,MAAM,IAAI,GAAG,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAClC,IAAI,YAAE,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IACvC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,+FAA+F;AAC/F,+FAA+F;AAC/F,mEAAmE;AACnE,SAAS,aAAa,CAAC,OAAe,EAAE,GAAW;IACjD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,iBAAiB,CAAC,CAAC,CAAC;IACpE,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9C,CAAC;AAED,8FAA8F;AAC9F,yFAAyF;AACzF,mGAAmG;AACnG,iGAAiG;AACjG,uFAAuF;AACvF,4BAAmC,GAAG,GAAW,OAAO,CAAC,GAAG,EAAE;IAC5D,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACvC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACjC,CAAC;IAED,MAAM,OAAO,GAAG,YAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACrD,MAAM,YAAY,GAAG,cAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IACpD,MAAM,aAAa,GAAG,aAAa,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IAE9D,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC;IACzD,CAAC;IAED,MAAM,WAAW,GAAG,aAAa,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACtD,IAAI,WAAW,KAAK,SAAS,IAAI,aAAa,IAAI,WAAW,EAAE,CAAC;QAC9D,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC;IACvF,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC;AACnE,CAAC"}
1
+ {"version":3,"file":"scanActionTimeout.js","sourceRoot":"","sources":["../../src/cli/scanActionTimeout.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,43 +1,43 @@
1
- {
2
- "name": "tamash-playwright",
3
- "version": "0.6.0",
4
- "description": "Plug and Play Self-healing for Playwright and automatically recovers broken selectors using an AI model (Ollama, OpenAI, Anthropic, or Gemini).",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "bin": {
8
- "tamash-playwright": "dist/cli/index.js"
9
- },
10
- "files": [
11
- "dist",
12
- "README.md",
13
- ".env.example"
14
- ],
15
- "scripts": {
16
- "build": "tsc -p tsconfig.json",
17
- "prepublishOnly": "npm run build"
18
- },
19
- "keywords": [
20
- "playwright",
21
- "self-healing",
22
- "test-automation",
23
- "llm",
24
- "ollama",
25
- "openai",
26
- "anthropic",
27
- "gemini"
28
- ],
29
- "author": "QtpSudhakar / VibeTestQ",
30
- "license": "SEE LICENSE IN LICENSE",
31
- "peerDependencies": {
32
- "@playwright/test": ">=1.40.0"
33
- },
34
- "dependencies": {
35
- "@anthropic-ai/sdk": "^0.115.0",
36
- "dotenv": "^16.0.1"
37
- },
38
- "devDependencies": {
39
- "@playwright/test": "^1.62.1",
40
- "@types/node": "^26.1.2",
41
- "typescript": "^7.0.2"
42
- }
43
- }
1
+ {
2
+ "name": "tamash-playwright",
3
+ "version": "0.6.1",
4
+ "description": "Plug and Play Self-healing for Playwright and automatically recovers broken selectors using an AI model (Ollama, OpenAI, Anthropic, or Gemini).",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "tamash-playwright": "dist/cli/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "README.md",
13
+ ".env.example"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsc -p tsconfig.json",
17
+ "prepublishOnly": "npm run build"
18
+ },
19
+ "keywords": [
20
+ "playwright",
21
+ "self-healing",
22
+ "test-automation",
23
+ "llm",
24
+ "ollama",
25
+ "openai",
26
+ "anthropic",
27
+ "gemini"
28
+ ],
29
+ "author": "QtpSudhakar / VibeTestQ",
30
+ "license": "SEE LICENSE IN LICENSE",
31
+ "peerDependencies": {
32
+ "@playwright/test": ">=1.40.0"
33
+ },
34
+ "dependencies": {
35
+ "@anthropic-ai/sdk": "^0.115.0",
36
+ "dotenv": "^16.0.1"
37
+ },
38
+ "devDependencies": {
39
+ "@playwright/test": "^1.62.1",
40
+ "@types/node": "^26.1.2",
41
+ "typescript": "^7.0.2"
42
+ }
43
+ }