tamash-playwright 0.1.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.
Files changed (47) hide show
  1. package/.env.example +26 -0
  2. package/README.md +108 -0
  3. package/dist/bindings/index.d.ts +8 -0
  4. package/dist/bindings/index.d.ts.map +1 -0
  5. package/dist/bindings/index.js +20 -0
  6. package/dist/bindings/index.js.map +1 -0
  7. package/dist/bindings/locator.binding.d.ts +8 -0
  8. package/dist/bindings/locator.binding.d.ts.map +1 -0
  9. package/dist/bindings/locator.binding.js +141 -0
  10. package/dist/bindings/locator.binding.js.map +1 -0
  11. package/dist/healer/index.d.ts +29 -0
  12. package/dist/healer/index.d.ts.map +1 -0
  13. package/dist/healer/index.js +256 -0
  14. package/dist/healer/index.js.map +1 -0
  15. package/dist/healer/providers/anthropic.d.ts +3 -0
  16. package/dist/healer/providers/anthropic.d.ts.map +1 -0
  17. package/dist/healer/providers/anthropic.js +52 -0
  18. package/dist/healer/providers/anthropic.js.map +1 -0
  19. package/dist/healer/providers/gemini.d.ts +3 -0
  20. package/dist/healer/providers/gemini.d.ts.map +1 -0
  21. package/dist/healer/providers/gemini.js +66 -0
  22. package/dist/healer/providers/gemini.js.map +1 -0
  23. package/dist/healer/providers/index.d.ts +4 -0
  24. package/dist/healer/providers/index.d.ts.map +1 -0
  25. package/dist/healer/providers/index.js +34 -0
  26. package/dist/healer/providers/index.js.map +1 -0
  27. package/dist/healer/providers/ollama.d.ts +3 -0
  28. package/dist/healer/providers/ollama.d.ts.map +1 -0
  29. package/dist/healer/providers/ollama.js +76 -0
  30. package/dist/healer/providers/ollama.js.map +1 -0
  31. package/dist/healer/providers/openai.d.ts +3 -0
  32. package/dist/healer/providers/openai.d.ts.map +1 -0
  33. package/dist/healer/providers/openai.js +64 -0
  34. package/dist/healer/providers/openai.js.map +1 -0
  35. package/dist/healer/providers/prompt.d.ts +12 -0
  36. package/dist/healer/providers/prompt.d.ts.map +1 -0
  37. package/dist/healer/providers/prompt.js +87 -0
  38. package/dist/healer/providers/prompt.js.map +1 -0
  39. package/dist/healer/providers/types.d.ts +43 -0
  40. package/dist/healer/providers/types.d.ts.map +1 -0
  41. package/dist/healer/providers/types.js +3 -0
  42. package/dist/healer/providers/types.js.map +1 -0
  43. package/dist/index.d.ts +7 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +15 -0
  46. package/dist/index.js.map +1 -0
  47. package/package.json +40 -0
package/.env.example ADDED
@@ -0,0 +1,26 @@
1
+ # Master on/off switch for self-healing. Unset or anything other than false/0 leaves it on.
2
+ HEALER_ENABLED=true
3
+
4
+ # Which AI provider backs self-healing: ollama | openai | anthropic | gemini
5
+ # Unset, unknown, or a provider whose key/model below is missing disables self-healing —
6
+ # a failed action just fails normally, since there's no AI model configured to recover it.
7
+ HEALER_PROVIDER=ollama
8
+
9
+ # --- Ollama Cloud (https://ollama.com) ---
10
+ OLLAMA_MODEL=gpt-oss:120b
11
+ OLLAMA_API_KEY=
12
+ # OLLAMA_BASE_URL=https://ollama.com
13
+
14
+ # --- OpenAI ---
15
+ # OPENAI_MODEL=gpt-4.1-mini
16
+ # OPENAI_API_KEY=
17
+ # OPENAI_BASE_URL=https://api.openai.com/v1
18
+
19
+ # --- Anthropic (uses the official @anthropic-ai/sdk) ---
20
+ # ANTHROPIC_MODEL=claude-haiku-4-5
21
+ # ANTHROPIC_API_KEY=
22
+
23
+ # --- Google Gemini ---
24
+ # GEMINI_MODEL= # check https://ai.google.dev/gemini-api/docs/models for the current model id
25
+ # GEMINI_API_KEY=
26
+ # GEMINI_BASE_URL=https://generativelanguage.googleapis.com/v1beta/openai
package/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # tamash-playwright
2
+
3
+ **Self-healing tests for Playwright.**
4
+
5
+ When you write an automated test, you tell it exactly where to find things on a webpage — a button, a text box, a link. But websites change all the time. A developer renames a field, moves a button, or tweaks the page layout, and suddenly your test can't find what it's looking for anymore. It fails — even though the feature itself works perfectly fine for real users.
6
+
7
+ `tamash-playwright` fixes that. It's a drop-in replacement for `@playwright/test` — you barely change your test code at all. Whenever a test action fails because it can't find something, `tamash-playwright` sends a snapshot of the current page to an AI model, which figures out where the element probably moved to, and tries the action again before giving up. If it finds a good match, your test keeps running like nothing happened. If it can't find anything sensible, your test fails normally — it never pretends something worked when it didn't.
8
+
9
+ ## Step 1: Install it
10
+
11
+ ```sh
12
+ npm install tamash-playwright
13
+ ```
14
+
15
+ You also need Playwright's own test package, if you don't already have it:
16
+
17
+ ```sh
18
+ npm install -D @playwright/test
19
+ ```
20
+
21
+ ## Step 2: Connect an AI model
22
+
23
+ `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.
24
+
25
+ Create a file named `.env` in your project folder:
26
+
27
+ ```sh
28
+ # Master on/off switch. Leave this as true, or remove the line entirely.
29
+ HEALER_ENABLED=true
30
+
31
+ # Pick one: ollama | openai | anthropic | gemini
32
+ HEALER_PROVIDER=ollama
33
+
34
+ # --- Ollama Cloud (https://ollama.com) ---
35
+ OLLAMA_MODEL=gpt-oss:120b
36
+ OLLAMA_API_KEY=
37
+
38
+ # --- OpenAI ---
39
+ # OPENAI_MODEL=gpt-4.1-mini
40
+ # OPENAI_API_KEY=
41
+
42
+ # --- Anthropic (Claude) ---
43
+ # ANTHROPIC_MODEL=claude-haiku-4-5
44
+ # ANTHROPIC_API_KEY=
45
+
46
+ # --- Google Gemini ---
47
+ # GEMINI_MODEL=
48
+ # GEMINI_API_KEY=
49
+ ```
50
+
51
+ Just fill in the API key and model for whichever one you want to use, and leave the rest as-is (or delete them).
52
+
53
+ ### Getting a free Ollama key (fastest way to get started)
54
+
55
+ Ollama Cloud is a quick, free way to get an API key without signing up for OpenAI/Anthropic/Gemini billing.
56
+
57
+ 1. Go to [ollama.com](https://ollama.com/) and create an account.
58
+ 2. Once signed in, go to [ollama.com/settings/keys](https://ollama.com/settings/keys).
59
+ 3. Create a new API key and copy it.
60
+ 4. Paste it into your `.env` file:
61
+
62
+ ```sh
63
+ HEALER_ENABLED=true
64
+ HEALER_PROVIDER=ollama
65
+ OLLAMA_MODEL=gpt-oss:120b
66
+ OLLAMA_API_KEY=paste_your_key_here
67
+ ```
68
+
69
+ That's all you need — no other variables required.
70
+
71
+ ## Step 3: Use it in your tests
72
+
73
+ Change one line at the top of your test file — everything else about how you write tests stays exactly the same:
74
+
75
+ ```ts
76
+ // Before
77
+ import { test, expect } from '@playwright/test';
78
+
79
+ // After
80
+ import { test, expect } from 'tamash-playwright';
81
+ ```
82
+
83
+ That's it. Write your tests as normal:
84
+
85
+ ```ts
86
+ import { test, expect } from 'tamash-playwright';
87
+
88
+ test('logs in', async ({ page }) => {
89
+ await page.goto('/');
90
+ await page.getByPlaceholder('Username').fill('Admin'); // fixed automatically if this breaks
91
+ await page.getByRole('button', { name: 'Login' }).click();
92
+ await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
93
+ });
94
+ ```
95
+
96
+ ### A quick tip for better results
97
+
98
+ 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:
99
+
100
+ ```ts
101
+ page.locator('input[name="username"]').describe('Username Textbox')
102
+ ```
103
+
104
+ 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.
105
+
106
+ ## License
107
+
108
+ ISC
@@ -0,0 +1,8 @@
1
+ import { type Page, type Frame } from '@playwright/test';
2
+ export type BindingFixtures = {
3
+ boundPage: Page;
4
+ boundFrame: Frame;
5
+ };
6
+ export declare const test: import("playwright/test").TestType<import("playwright/test").PlaywrightTestArgs & import("playwright/test").PlaywrightTestOptions & BindingFixtures, import("playwright/test").PlaywrightWorkerArgs & import("playwright/test").PlaywrightWorkerOptions>;
7
+ export { expect } from '@playwright/test';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bindings/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,IAAI,EAAE,KAAK,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAGvE,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,KAAK,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,IAAI,0PAWf,CAAC;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.expect = exports.test = void 0;
4
+ const test_1 = require("@playwright/test");
5
+ const locator_binding_1 = require("./locator.binding");
6
+ exports.test = test_1.test.extend({
7
+ page: async ({ page }, use) => {
8
+ await use((0, locator_binding_1.bindPageActions)(page));
9
+ },
10
+ boundPage: async ({ page }, use) => {
11
+ await use(page);
12
+ },
13
+ boundFrame: async ({ page }, use) => {
14
+ const frame = page.mainFrame();
15
+ await use((0, locator_binding_1.bindFrameActions)(frame));
16
+ },
17
+ });
18
+ var test_2 = require("@playwright/test");
19
+ Object.defineProperty(exports, "expect", { enumerable: true, get: function () { return test_2.expect; } });
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bindings/index.ts"],"names":[],"mappings":";;;AAAA,2CAAuE;AACvE,uDAAsE;AAOzD,QAAA,IAAI,GAAG,WAAI,CAAC,MAAM,CAAkB;IAC/C,IAAI,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,EAAE;QAC5B,MAAM,GAAG,CAAC,IAAA,iCAAe,EAAC,IAAI,CAAC,CAAC,CAAC;IACnC,CAAC;IACD,SAAS,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,EAAE;QACjC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IACD,UAAU,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,EAAE;QAClC,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC/B,MAAM,GAAG,CAAC,IAAA,kCAAgB,EAAC,KAAK,CAAC,CAAC,CAAC;IACrC,CAAC;CACF,CAAC,CAAC;AAEH,yCAA0C;AAAjC,8FAAA,MAAM,OAAA"}
@@ -0,0 +1,8 @@
1
+ import type { Frame, Locator, Page } from '@playwright/test';
2
+ type BindingKind = 'locator' | 'page' | 'frame';
3
+ export declare function bindTargetActions<T extends Locator | Page | Frame>(target: T, kind?: BindingKind, description?: string): T;
4
+ export declare function bindLocatorActions(locator: Locator): Locator;
5
+ export declare function bindPageActions(page: Page): Page;
6
+ export declare function bindFrameActions(frame: Frame): Frame;
7
+ export {};
8
+ //# sourceMappingURL=locator.binding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locator.binding.d.ts","sourceRoot":"","sources":["../../src/bindings/locator.binding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAsC7D,KAAK,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AA6BhD,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,OAAO,GAAG,IAAI,GAAG,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,GAAE,WAAuB,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,CAAC,CAwErI;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAE5D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAEhD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAEpD"}
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.bindTargetActions = bindTargetActions;
4
+ exports.bindLocatorActions = bindLocatorActions;
5
+ exports.bindPageActions = bindPageActions;
6
+ exports.bindFrameActions = bindFrameActions;
7
+ const healer_1 = require("../healer");
8
+ const ACTIONS = [
9
+ 'click',
10
+ 'dblclick',
11
+ 'tap',
12
+ 'hover',
13
+ 'fill',
14
+ 'clear',
15
+ 'press',
16
+ 'check',
17
+ 'uncheck',
18
+ 'selectOption',
19
+ 'setInputFiles',
20
+ 'dragTo',
21
+ 'focus',
22
+ 'blur',
23
+ ];
24
+ const LOCATOR_FACTORY_METHODS = [
25
+ 'locator',
26
+ 'getByRole',
27
+ 'getByLabel',
28
+ 'getByPlaceholder',
29
+ 'getByText',
30
+ 'getByAltText',
31
+ 'getByTitle',
32
+ 'getByTestId',
33
+ ];
34
+ // Methods that return a *new* Locator derived from the current one. Playwright's own
35
+ // implementations are immutable (they don't mutate `target`), so if we don't intercept these
36
+ // and re-wrap the result, the returned Locator silently loses its healing Proxy. This mattered
37
+ // in practice: every page object in this repo chains `.describe(...)` right after a factory call,
38
+ // which was exactly this bug.
39
+ const CHAIN_METHODS = ['describe', 'first', 'last', 'nth', 'filter', 'and', 'or'];
40
+ function describeFactoryCall(prop, args) {
41
+ const [first, second] = args;
42
+ switch (prop) {
43
+ case 'getByRole': {
44
+ const name = second?.name;
45
+ return name ? `role:${String(first)} "${String(name)}"` : `role:${String(first)}`;
46
+ }
47
+ case 'getByLabel':
48
+ return `label "${String(first)}"`;
49
+ case 'getByPlaceholder':
50
+ return `placeholder "${String(first)}"`;
51
+ case 'getByText':
52
+ return `text "${String(first)}"`;
53
+ case 'getByAltText':
54
+ return `alt text "${String(first)}"`;
55
+ case 'getByTitle':
56
+ return `title "${String(first)}"`;
57
+ case 'getByTestId':
58
+ return `testid "${String(first)}"`;
59
+ case 'locator':
60
+ return `selector "${String(first)}"`;
61
+ default:
62
+ return undefined;
63
+ }
64
+ }
65
+ function bindTargetActions(target, kind = 'locator', description) {
66
+ return new Proxy(target, {
67
+ get(target, prop, receiver) {
68
+ if (typeof prop === 'string') {
69
+ const targetObject = target;
70
+ if (kind !== 'locator' && LOCATOR_FACTORY_METHODS.includes(prop)) {
71
+ return (...args) => {
72
+ const factory = targetObject[prop];
73
+ if (typeof factory !== 'function') {
74
+ throw new Error(`The locator factory "${String(prop)}" is not available on this ${kind}.`);
75
+ }
76
+ const locator = factory.apply(target, args);
77
+ return bindTargetActions(locator, 'locator', describeFactoryCall(prop, args));
78
+ };
79
+ }
80
+ if (kind === 'locator' && CHAIN_METHODS.includes(prop)) {
81
+ return (...args) => {
82
+ const chainMethod = targetObject[prop];
83
+ if (typeof chainMethod !== 'function') {
84
+ throw new Error(`The locator method "${String(prop)}" is not available on this ${kind}.`);
85
+ }
86
+ const result = chainMethod.apply(target, args);
87
+ const nextDescription = prop === 'describe' ? String(args[0] ?? '') : description;
88
+ return bindTargetActions(result, 'locator', nextDescription);
89
+ };
90
+ }
91
+ if (ACTIONS.includes(prop)) {
92
+ const action = targetObject[prop];
93
+ if (typeof action !== 'function') {
94
+ throw new Error(`The action "${String(prop)}" is not available on this ${kind}.`);
95
+ }
96
+ return async (...callArgs) => {
97
+ try {
98
+ // Playwright infers the "apiName" shown in its own error messages (e.g.
99
+ // "locator.fill: Timeout ...") from the call-site stack frame. Invoking via
100
+ // `action.apply(target, callArgs)` put `Function.prototype.apply` on that frame, so
101
+ // every failure was reported as "locator.apply" instead of the real action name.
102
+ // A plain method call (`target[prop](...)`) keeps `this` bound to `target` and keeps
103
+ // the real method name in the stack, e.g. "locator.fill" again.
104
+ return await target[prop](...callArgs);
105
+ }
106
+ catch (error) {
107
+ const healing = await (0, healer_1.healActionFailure)({
108
+ action: String(prop),
109
+ kind,
110
+ description: description ?? `${kind} action ${String(prop)}`,
111
+ error,
112
+ target,
113
+ callArgs,
114
+ });
115
+ // NOTE: most Playwright actions (click/fill/check/hover/...) resolve to `undefined`
116
+ // on success, so `healing.recovered` alone is the correct success signal here —
117
+ // checking `healing.result !== undefined` would treat every successful heal of a
118
+ // void action as a failure and rethrow anyway.
119
+ if (healing.recovered) {
120
+ return healing.result;
121
+ }
122
+ throw error;
123
+ }
124
+ };
125
+ }
126
+ }
127
+ const value = Reflect.get(target, prop, receiver);
128
+ return typeof value === 'function' ? value.bind(target) : value;
129
+ },
130
+ });
131
+ }
132
+ function bindLocatorActions(locator) {
133
+ return bindTargetActions(locator, 'locator');
134
+ }
135
+ function bindPageActions(page) {
136
+ return bindTargetActions(page, 'page');
137
+ }
138
+ function bindFrameActions(frame) {
139
+ return bindTargetActions(frame, 'frame');
140
+ }
141
+ //# sourceMappingURL=locator.binding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locator.binding.js","sourceRoot":"","sources":["../../src/bindings/locator.binding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { Frame, Locator, Page } from '@playwright/test';
2
+ import type { TokenUsage } from './providers/types';
3
+ type BindingKind = 'locator' | 'page' | 'frame';
4
+ export type SelfHealingReport = {
5
+ action: string;
6
+ kind: BindingKind;
7
+ description?: string;
8
+ provider: string;
9
+ healed: boolean;
10
+ warning: string;
11
+ reason: string;
12
+ suggestedSelector?: string;
13
+ tokenUsage?: TokenUsage;
14
+ };
15
+ export declare function healActionFailure(context: {
16
+ action: string;
17
+ kind: BindingKind;
18
+ description?: string;
19
+ error: unknown;
20
+ target?: Locator | Page | Frame;
21
+ callArgs?: unknown[];
22
+ }): Promise<{
23
+ report: SelfHealingReport;
24
+ recovered: boolean;
25
+ result?: unknown;
26
+ }>;
27
+ export declare function getHealingReports(): SelfHealingReport[];
28
+ export {};
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/healer/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAI7D,OAAO,KAAK,EAAsB,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAIxE,KAAK,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAEhD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,WAAW,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB,CAAC;AAoOF,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,WAAW,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,KAAK,CAAC;IAChC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;CACtB,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,iBAAiB,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAyC/E;AAED,wBAAgB,iBAAiB,IAAI,iBAAiB,EAAE,CAEvD"}
@@ -0,0 +1,256 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.healActionFailure = healActionFailure;
7
+ exports.getHealingReports = getHealingReports;
8
+ const path_1 = __importDefault(require("path"));
9
+ const test_1 = require("@playwright/test");
10
+ const dotenv_1 = __importDefault(require("dotenv"));
11
+ const providers_1 = require("./providers");
12
+ dotenv_1.default.config({ path: path_1.default.resolve(process.cwd(), '.env') });
13
+ const reports = [];
14
+ function normalizeError(error) {
15
+ if (error instanceof Error) {
16
+ return error.message;
17
+ }
18
+ if (typeof error === 'string') {
19
+ return error;
20
+ }
21
+ return 'Unknown action failure';
22
+ }
23
+ function escapeRegExp(value) {
24
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
25
+ }
26
+ // Reuses the project's configured `use.actionTimeout` (playwright.config.ts) as the budget for
27
+ // the healer's own ARIA snapshot capture and provider request, instead of a timeout picked
28
+ // independently of it — otherwise a provider call could easily outlast the action it's healing.
29
+ // Returns undefined (letting callers fall back to their own default) when actionTimeout is
30
+ // unset/0, i.e. Playwright's "no timeout".
31
+ function resolveActionTimeoutMs() {
32
+ try {
33
+ const actionTimeout = test_1.test.info().project.use.actionTimeout;
34
+ return typeof actionTimeout === 'number' && actionTimeout > 0 ? actionTimeout : undefined;
35
+ }
36
+ catch {
37
+ return undefined;
38
+ }
39
+ }
40
+ async function resolvePageContext(target) {
41
+ if (!target) {
42
+ return undefined;
43
+ }
44
+ if (typeof target.page === 'function') {
45
+ try {
46
+ return await target.page();
47
+ }
48
+ catch {
49
+ return undefined;
50
+ }
51
+ }
52
+ return target;
53
+ }
54
+ // `page.accessibility` was removed from Playwright (confirmed absent in the installed
55
+ // playwright-core@1.62.1). `ariaSnapshot()` is the supported replacement and works on any
56
+ // Locator, so we snapshot the whole document via `locator('body')`.
57
+ async function captureAriaSnapshot(pageContext, timeoutMs) {
58
+ if (!pageContext) {
59
+ return undefined;
60
+ }
61
+ try {
62
+ return await pageContext.locator('body').ariaSnapshot({ timeout: timeoutMs });
63
+ }
64
+ catch {
65
+ try {
66
+ return await pageContext.locator(':root').ariaSnapshot({ timeout: timeoutMs });
67
+ }
68
+ catch {
69
+ return undefined;
70
+ }
71
+ }
72
+ }
73
+ function buildLocatorFromSuggestion(pageContext, suggestion) {
74
+ switch (suggestion.strategy) {
75
+ case 'role':
76
+ return pageContext.getByRole(suggestion.role, suggestion.name ? { name: new RegExp(escapeRegExp(suggestion.name), 'i') } : undefined);
77
+ case 'text':
78
+ return pageContext.getByText(suggestion.text, { exact: false });
79
+ case 'testId':
80
+ return pageContext.getByTestId(suggestion.testId);
81
+ case 'label':
82
+ return pageContext.getByLabel(suggestion.label, { exact: false });
83
+ case 'placeholder':
84
+ return pageContext.getByPlaceholder(suggestion.placeholder, { exact: false });
85
+ case 'css':
86
+ return pageContext.locator(suggestion.css);
87
+ default:
88
+ return undefined;
89
+ }
90
+ }
91
+ function describeSuggestion(suggestion) {
92
+ switch (suggestion.strategy) {
93
+ case 'role':
94
+ return `role:${suggestion.role}${suggestion.name ? `:${suggestion.name}` : ''}`;
95
+ case 'text':
96
+ return `text:${suggestion.text}`;
97
+ case 'testId':
98
+ return `testid:${suggestion.testId}`;
99
+ case 'label':
100
+ return `label:${suggestion.label}`;
101
+ case 'placeholder':
102
+ return `placeholder:${suggestion.placeholder}`;
103
+ case 'css':
104
+ return `css:${suggestion.css}`;
105
+ default:
106
+ return undefined;
107
+ }
108
+ }
109
+ // `dragTo` (and anything else outside this list) can't be safely "healed" by guessing a
110
+ // substitute locator and clicking it — that would silently perform the wrong action and report
111
+ // a false recovery, so those actions are excluded rather than defaulted to `.click()`.
112
+ async function replayAction(locator, action, callArgs = []) {
113
+ const [firstArg] = callArgs;
114
+ switch (action) {
115
+ case 'click':
116
+ return locator.click();
117
+ case 'dblclick':
118
+ return locator.dblclick();
119
+ case 'tap':
120
+ return locator.tap();
121
+ case 'hover':
122
+ return locator.hover();
123
+ case 'fill':
124
+ return locator.fill(String(firstArg ?? ''));
125
+ case 'clear':
126
+ return locator.clear();
127
+ case 'press':
128
+ return locator.press(String(firstArg ?? ''));
129
+ case 'check':
130
+ return locator.check();
131
+ case 'uncheck':
132
+ return locator.uncheck();
133
+ case 'selectOption':
134
+ return locator.selectOption(firstArg);
135
+ case 'setInputFiles':
136
+ return locator.setInputFiles(firstArg);
137
+ case 'focus':
138
+ return locator.focus();
139
+ case 'blur':
140
+ return locator.blur();
141
+ default:
142
+ throw new Error(`Action "${action}" cannot be safely replayed by the self-healer.`);
143
+ }
144
+ }
145
+ // Token usage is captured whenever the provider call itself succeeded, independent of whether
146
+ // the suggested selector actually worked — the tokens were spent either way, so a failed heal
147
+ // still needs to be reported for cost tracking.
148
+ async function tryRecoverWithProvider(pageContext, action, description, ariaSnapshot, callArgs, timeoutMs) {
149
+ const provider = (0, providers_1.getHealProvider)();
150
+ if (!provider || !pageContext || !ariaSnapshot) {
151
+ return { healing: null };
152
+ }
153
+ const result = await provider.suggestSelector({ action, description, ariaSnapshot, timeoutMs });
154
+ if (!result) {
155
+ return { healing: null };
156
+ }
157
+ const { suggestion, usage } = result;
158
+ if (!suggestion || suggestion.strategy === 'none') {
159
+ return { healing: null, usage };
160
+ }
161
+ const locator = buildLocatorFromSuggestion(pageContext, suggestion);
162
+ if (!locator) {
163
+ return { healing: null, usage };
164
+ }
165
+ try {
166
+ const replayResult = await replayAction(locator, action, callArgs);
167
+ return {
168
+ healing: {
169
+ provider: provider.name,
170
+ healed: true,
171
+ warning: `Recovered using ${provider.name} (${describeSuggestion(suggestion) ?? 'suggested selector'}).`,
172
+ suggestedSelector: describeSuggestion(suggestion),
173
+ result: replayResult,
174
+ },
175
+ usage,
176
+ };
177
+ }
178
+ catch {
179
+ return { healing: null, usage };
180
+ }
181
+ }
182
+ // HEALER_ENABLED is the master on/off switch: unset or any value other than "false"/"0" leaves
183
+ // healing on, so existing setups keep working without needing to add the var at all.
184
+ function isHealingEnabled() {
185
+ const value = process.env.HEALER_ENABLED?.trim().toLowerCase();
186
+ return value !== 'false' && value !== '0';
187
+ }
188
+ function formatTokenUsage(usage) {
189
+ const parts = [];
190
+ if (usage.inputTokens !== undefined)
191
+ parts.push(`${usage.inputTokens} input`);
192
+ if (usage.outputTokens !== undefined)
193
+ parts.push(`${usage.outputTokens} output`);
194
+ const breakdown = parts.length ? ` (${parts.join(' + ')})` : '';
195
+ return usage.totalTokens !== undefined ? `${usage.totalTokens} tokens${breakdown}` : `tokens${breakdown}`;
196
+ }
197
+ function attachReportToRunningTest(report) {
198
+ try {
199
+ const testInfo = test_1.test.info();
200
+ testInfo.annotations.push({ type: report.healed ? 'self-healed' : 'self-heal-failed', description: report.warning });
201
+ if (report.tokenUsage) {
202
+ testInfo.annotations.push({
203
+ type: 'llm-tokens-used',
204
+ description: `${report.provider} — ${report.action}: ${formatTokenUsage(report.tokenUsage)}`,
205
+ });
206
+ }
207
+ void testInfo.attach(`self-healing-${report.action}`, {
208
+ body: JSON.stringify(report, null, 2),
209
+ contentType: 'application/json',
210
+ });
211
+ }
212
+ catch {
213
+ // Not running inside a Playwright test worker (e.g. a unit test calling this directly) — skip.
214
+ }
215
+ }
216
+ async function healActionFailure(context) {
217
+ const reason = normalizeError(context.error);
218
+ const callArgs = context.callArgs ?? [];
219
+ const healingEnabled = isHealingEnabled();
220
+ // Skip the ARIA snapshot capture and provider lookup entirely when disabled — no point paying
221
+ // for a snapshot (or an LLM call) just to throw the result away.
222
+ const actionTimeoutMs = resolveActionTimeoutMs();
223
+ const pageContext = healingEnabled ? await resolvePageContext(context.target) : undefined;
224
+ const ariaSnapshot = healingEnabled ? await captureAriaSnapshot(pageContext, actionTimeoutMs ?? 2000) : undefined;
225
+ const providerAttempt = healingEnabled
226
+ ? await tryRecoverWithProvider(pageContext, context.action, context.description, ariaSnapshot, callArgs, actionTimeoutMs)
227
+ : { healing: null, usage: undefined };
228
+ const healing = providerAttempt.healing;
229
+ const warning = healing?.warning
230
+ ?? (healingEnabled
231
+ ? `Action "${context.action}" failed: ${reason}.`
232
+ : `Self-healing is disabled (HEALER_ENABLED=false); action "${context.action}" failed: ${reason}.`);
233
+ const report = {
234
+ action: context.action,
235
+ kind: context.kind,
236
+ description: context.description,
237
+ provider: healing?.provider ?? (healingEnabled ? 'none' : 'disabled'),
238
+ tokenUsage: providerAttempt.usage,
239
+ healed: Boolean(healing?.healed),
240
+ warning,
241
+ reason,
242
+ suggestedSelector: healing?.suggestedSelector,
243
+ };
244
+ reports.push(report);
245
+ console.warn(`[self-healer] ${report.warning}`);
246
+ attachReportToRunningTest(report);
247
+ return {
248
+ report,
249
+ recovered: Boolean(healing?.healed),
250
+ result: healing?.result,
251
+ };
252
+ }
253
+ function getHealingReports() {
254
+ return reports.slice();
255
+ }
256
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/healer/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { HealProvider } from './types';
2
+ export declare function createAnthropicProvider(): HealProvider | null;
3
+ //# sourceMappingURL=anthropic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/healer/providers/anthropic.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAwC,MAAM,SAAS,CAAC;AAOlF,wBAAgB,uBAAuB,IAAI,YAAY,GAAG,IAAI,CA+C7D"}