@ia-qa/self-healing 1.7.4 → 1.7.6

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 (2) hide show
  1. package/README.md +63 -14
  2. package/package.json +16 -2
package/README.md CHANGED
@@ -1,15 +1,22 @@
1
- # @ia-qa/self-healing
1
+ # ia-qa-heal — self-healing selectors for E2E tests
2
+
3
+ [![npm](https://img.shields.io/npm/v/@ia-qa/self-healing)](https://www.npmjs.com/package/@ia-qa/self-healing)
4
+ ![license](https://img.shields.io/npm/l/@ia-qa/self-healing)
5
+ ![node](https://img.shields.io/node/v/@ia-qa/self-healing)
2
6
 
3
7
  Your E2E tests break because a selector moved, not because the app is wrong. This finds the
4
8
  element again and rewrites the test.
5
9
 
6
- A **CLI**, a **local MCP server** for AI agents, and an accessibility-tree page mapper.
7
- Framework-agnostic Playwright, Cypress, Selenium; JS/TS, Python, Java. The verdict is
8
- deterministic: no model decides whether your build passes.
10
+ **The verdict is deterministic no model decides whether your build passes.** When the repair
11
+ is not provable, the tool refuses to guess and tells you why, rather than quietly rewriting a
12
+ test into a green lie.
9
13
 
10
14
  **It runs entirely on your machine.** It brings its own headless Chromium, so it sees
11
15
  `localhost`, staging, or an app behind a VPN, and **nothing ever leaves the machine**.
12
16
 
17
+ Framework-agnostic — Playwright, Cypress, Selenium; JS/TS, Python, Java. Ships a **CLI**, a
18
+ **local MCP server** for AI agents, and an accessibility-tree page mapper.
19
+
13
20
  > **New here?** The [step-by-step tutorial](https://www.ia-qa.com/devtools/selector-drift/tutorial)
14
21
  > walks the whole thing with no jargon (same text as `TUTORIAL.md`, shipped in this package).
15
22
  > This README is the short reference.
@@ -19,33 +26,61 @@ deterministic: no model decides whether your build passes.
19
26
  [![ia-qa-heal repairing a broken Playwright suite: 3 failed, FIX verdict, selectors rewritten to getByRole, 3 passed, verified](https://www.ia-qa.com/media/heal-demo.gif)](https://www.ia-qa.com/media/heal-demo.mp4)
20
27
 
21
28
  `ia-qa-heal run` runs your suite, watches it break, diffs the live app against your baseline,
22
- rewrites the dead selectors as `getByRole(…, { exact: true })` not as fresher CSS paths —
23
- then **re-runs the suite to verify** and exits on that verdict. Nothing is committed.
29
+ rewrites the dead selectors, then **re-runs the suite to verify** and exits on that verdict.
30
+ Nothing is committed. By default a selector is replaced by the element's new selector, in the
31
+ style your suite already uses — CSS stays CSS. The demo adds `--locators`, which rewrites to
32
+ `getByRole(…, { exact: true })` where that is provably safe: a locator immune to the *next*
33
+ layout change.
24
34
 
25
35
  ▶ **[The full 49-second version](https://www.ia-qa.com/media/heal-demo.mp4)** also covers what
26
36
  deterministic healing *refuses* to guess, the MCP server answering an agent, and the HTML
27
37
  report `--report` writes for a PR.
28
38
 
29
- ## Install and run the loop
39
+ ## Install
30
40
 
31
41
  ```bash
32
42
  npm i -D @ia-qa/self-healing
33
- npx ia-qa-heal init # interactive: writes .ia-qa/config.json
34
43
  ```
35
44
 
36
- Then, **in this order**:
45
+ **Four commands to your first verdict** no baseline needed, nothing is rewritten:
46
+
47
+ ```bash
48
+ npx ia-qa-heal init # interactive: writes .ia-qa/config.json
49
+ npx ia-qa-heal ingest # inventory the selectors and names your tests use
50
+ npx ia-qa-heal map # capture the app, and bind your selectors to it
51
+ npx ia-qa-heal audit # does my suite still name things that exist?
52
+ ```
53
+
54
+ `audit` is read-only and advisory (exit 0 unless `--strict`) — it answers on day one, before
55
+ you have any history to compare against.
56
+
57
+ **Then one command, for good:**
37
58
 
38
59
  ```bash
39
- npx ia-qa-heal ingest # inventory the selectors and names your tests use
40
- npx ia-qa-heal map # capture the app, and bind your selectors to it
41
- npx ia-qa-heal baseline # promote that capture to "this is how it should be"
60
+ npx ia-qa-heal baseline # lock today's UI as the reference once
42
61
  # … someone changes the UI …
62
+ npx ia-qa-heal run # runs your suite → diffs → fixes → re-runs to verify
63
+ ```
64
+
65
+ `run` is the whole loop in one verb: it runs your suite, watches it break, diffs the live app
66
+ against the baseline, rewrites the dead selectors, then **re-runs the suite to verify** and
67
+ exits on that verdict. Nothing is committed.
68
+
69
+ <details>
70
+ <summary>Prefer the steps unbundled — <code>map</code> → <code>diff</code> → <code>fix</code></summary>
71
+
72
+ ```bash
43
73
  npx ia-qa-heal map
44
- npx ia-qa-heal diff # PASS / FIX / BLOCK
74
+ npx ia-qa-heal diff # PASS / FIX / BLOCK — this is the CI gate
45
75
  npx ia-qa-heal fix --dry-run
46
76
  npx ia-qa-heal fix
47
77
  ```
48
78
 
79
+ Use this when your suite is slow (`run` runs it twice), or when CI already captures with
80
+ `IAQA_CAPTURE=1` — then `diff` alone costs nothing extra.
81
+
82
+ </details>
83
+
49
84
  `ingest` comes **first**, and it is not optional if your tests locate by CSS: it is what lets
50
85
  `map` bind the strings your tests write to real elements. Re-run it when your test files
51
86
  change — `map` says so when they have. Commit `.ia-qa/` (except `session.json`): the baseline
@@ -122,7 +157,21 @@ What `fix` **refuses** is the point of the tool:
122
157
  | `unattributable` | `getByText`, `cy.contains`, `getByTitle`… name a **string, not an element**. Nothing proves the test meant the renamed button rather than a heading that never moved, so editing one would break a *passing* test |
123
158
 
124
159
  `--locators` rewrites to `getByRole(role, { name })` instead of a fresher CSS path, where that
125
- is provably safe — a selector that survives the next layout change.
160
+ is provably safe — a selector that survives the next layout change. Without it, a CSS selector
161
+ is replaced by a CSS selector: the tool does not impose a locator style on your suite.
162
+
163
+ ### At runtime, if you want it — `aiClick` / `aiFill`
164
+
165
+ ```ts
166
+ import { aiClick } from '@ia-qa/self-healing';
167
+ await aiClick(page, 'button#login');
168
+ ```
169
+
170
+ If the normal action times out, these read the page contract, re-scan the live page, retry on
171
+ the element that semantically matches, and log a loud warning that the test needs updating.
172
+ Useful to keep a suite green while you triage — but it is a **stopgap, not the loop**: healing
173
+ in memory hides the drift instead of putting it in a pull request. The verbs above edit your
174
+ files so a human reviews the change.
126
175
 
127
176
  ## Page Objects written in CSS
128
177
 
package/package.json CHANGED
@@ -1,12 +1,19 @@
1
1
  {
2
2
  "name": "@ia-qa/self-healing",
3
- "version": "1.7.4",
4
- "description": "Local-first self-healing for UI tests: a local MCP server + CLI that map your app's pages to a role/name/selector contract, diff selector drift (PASS/FIX/BLOCK), and apply deterministic fixes to Cypress/Playwright/Selenium tests. Runs on your machine — your app, your tests and your results never leave it.",
3
+ "version": "1.7.6",
4
+ "description": "Your Playwright, Cypress or Selenium tests break when a selector moves this finds the element again and rewrites the test. Deterministic: no LLM decides whether your build passes. Runs entirely on your machine, with a local MCP server for agents.",
5
5
  "keywords": [
6
6
  "self-healing",
7
7
  "selectors",
8
+ "broken-selectors",
9
+ "selector-drift",
10
+ "locators",
11
+ "flaky-tests",
12
+ "flaky",
8
13
  "e2e",
14
+ "e2e-testing",
9
15
  "testing",
16
+ "test-automation",
10
17
  "qa",
11
18
  "playwright",
12
19
  "cypress",
@@ -20,6 +27,13 @@
20
27
  "license": "MIT",
21
28
  "author": "Jean-Christophe Jamet",
22
29
  "homepage": "https://www.ia-qa.com",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/JcJamet/ia-qa-heal.git"
33
+ },
34
+ "bugs": {
35
+ "url": "https://github.com/JcJamet/ia-qa-heal/issues"
36
+ },
23
37
  "type": "commonjs",
24
38
  "main": "dist/index.js",
25
39
  "types": "dist/index.d.ts",