@ia-qa/self-healing 0.10.2 → 1.0.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/README.md +61 -1
- package/TUTORIAL.md +8 -3
- package/dist/htmlReport.js +44 -0
- package/dist/htmlReport.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -132,7 +132,7 @@ Only if all four fail does it error, listing the three fixes. `map_app` exposes
|
|
|
132
132
|
```
|
|
133
133
|
Exit codes for pipelines: `0` = PASS or FIX, `1` = BLOCK — lost, ambiguous, or rebound (add `--strict` to fail on FIX too), `2` = bad input, no baseline, or nothing to compare. Use `--json` for machine-readable output. Same diff engine as the web tool (`src/browser/match.js`).
|
|
134
134
|
|
|
135
|
-
**`--report [file.html]`** also writes a self-contained, ia-qa.com-branded HTML report of the run — the PASS/FIX/BLOCK verdict, totals, a per-page table and every drifted selector with its `old → new` transition and test-usage annotation — the artefact to attach to a PR instead of a console screenshot (default `ia-qa-heal-report.html`). Add **`--open`** to open it in your browser (local use; leave it off in CI). Works on `diff` and `run`.
|
|
135
|
+
**`--report [file.html]`** also writes a self-contained, ia-qa.com-branded HTML report of the run — a plain-language summary of what the run checked and found (how many elements across how many pages, what drifted, how many of your test files it touches, and the next action), the PASS/FIX/BLOCK verdict, totals, a per-page table and every drifted selector with its `old → new` transition and test-usage annotation — the artefact to attach to a PR instead of a console screenshot (default `ia-qa-heal-report.html`). Add **`--open`** to open it in your browser (local use; leave it off in CI). Works on `diff` and `run`.
|
|
136
136
|
|
|
137
137
|
A contract that was **not re-mapped** since the baseline carries the baseline's own `capturedAt`, so it cannot show drift. Those are listed and left **out** of the verdict rather than counted as `ok` — padding a gate with comparisons that never happened is the same lie in smaller print. `--json` reports them as `staleExcluded`.
|
|
138
138
|
|
|
@@ -151,6 +151,66 @@ Only if all four fail does it error, listing the three fixes. `map_app` exposes
|
|
|
151
151
|
```
|
|
152
152
|
If the selector fails, the helper re-scans the live page, matches the element by role + accessible name (exact, then fuzzy Dice ≥ 0.6 — or your own `llmResolver`), retries on the healed selector, and logs a warning telling you to update the test and re-map.
|
|
153
153
|
|
|
154
|
+
## Page Object Models — one file to keep in sync
|
|
155
|
+
|
|
156
|
+
A POM already does what this tool wants: it lifts every selector out of the tests and into **one file**. That is also the one file drift keeps breaking. `map` → `diff` → `fix` treats it like any other test file — the selector is a quoted string literal, so `fix` rewrites it in place.
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
// login.page.ts — the only place a selector is written
|
|
160
|
+
export class LoginPage {
|
|
161
|
+
readonly emailSelector = '#email';
|
|
162
|
+
readonly passwordSelector = '#password';
|
|
163
|
+
readonly submitSelector = 'button#login';
|
|
164
|
+
// used everywhere as page.fill(this.emailSelector, …)
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
A developer reworks the login form: `button#login` becomes `button.btn-primary`. The whole suite goes red through this one file. Heal it:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
npx ia-qa-heal map # capture the new contract
|
|
172
|
+
npx ia-qa-heal diff # 🔧 healable button "Log in" button#login → button.btn-primary
|
|
173
|
+
npx ia-qa-heal ingest # inventory the POM's selector literals (optional — lets fix find the file itself)
|
|
174
|
+
npx ia-qa-heal fix .ia-qa/baseline/login.json .ia-qa/mapping/login.json login.page.ts
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
```diff
|
|
178
|
+
export class LoginPage {
|
|
179
|
+
readonly emailSelector = '#email';
|
|
180
|
+
readonly passwordSelector = '#password';
|
|
181
|
+
- readonly submitSelector = 'button#login';
|
|
182
|
+
+ readonly submitSelector = 'button.btn-primary';
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
One line changes and every test that goes through `LoginPage` is fixed at once — the POM is exactly the leverage `fix` is built for. Review with `git diff`, run your suite, commit. Nothing was committed for you.
|
|
187
|
+
|
|
188
|
+
**One naming detail.** `ingest` recognises a POM property as a selector when its name contains `selector`/`Selector` (`submitSelector`, above) or when the value is a framework call it already knows (`this.page.locator('#login')`). That is what lists the file in `.ia-qa/usage.json`, so `diff` can annotate it and `fix` can find it with no path given. A plainly-named property (`loginButton = '#login'`) is invisible to that inventory — but `fix` still rewrites its literal when you pass the POM file on the command line, because the rewrite is keyed on the string, not the property name.
|
|
189
|
+
|
|
190
|
+
## In CI
|
|
191
|
+
|
|
192
|
+
`diff` returns an exit code, so a pipeline can gate on drift — `0` = PASS/FIX, `1` = BLOCK, `2` = bad input:
|
|
193
|
+
|
|
194
|
+
```yaml
|
|
195
|
+
# .github/workflows/selector-drift.yml
|
|
196
|
+
name: Selector drift
|
|
197
|
+
on: [pull_request]
|
|
198
|
+
jobs:
|
|
199
|
+
drift:
|
|
200
|
+
runs-on: ubuntu-latest
|
|
201
|
+
steps:
|
|
202
|
+
- uses: actions/checkout@v4
|
|
203
|
+
- uses: actions/setup-node@v4
|
|
204
|
+
with: { node-version: '20' }
|
|
205
|
+
- run: npm ci
|
|
206
|
+
- run: npx playwright install --with-deps chromium
|
|
207
|
+
- run: npm start & # your app on its usual port
|
|
208
|
+
- run: npx ia-qa-heal map # re-capture into .ia-qa/mapping/
|
|
209
|
+
- run: npx ia-qa-heal diff # 0 = PASS/FIX · 1 = BLOCK · 2 = bad input
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
`diff` with no arguments compares the committed `.ia-qa/baseline/` against what `map` just re-captured — which is why the baseline has to be in git. Add `--report drift-report.html` to attach a branded HTML report to the build, and `--strict` to fail on FIX too. The full workflow (report upload, artifact, `--strict`) is in **[TUTORIAL.md → Putting it in CI](TUTORIAL.md#8-putting-it-in-ci)**.
|
|
213
|
+
|
|
154
214
|
## Map artifacts
|
|
155
215
|
|
|
156
216
|
Beyond one contract per page, every `map` run rebuilds two views of the whole app. Both are derived entirely from the mappings on disk (no extra page visit) and rebuilt on every run, including `map <page>`, so they never drift out of date.
|
package/TUTORIAL.md
CHANGED
|
@@ -403,9 +403,11 @@ jobs:
|
|
|
403
403
|
```
|
|
404
404
|
|
|
405
405
|
`--report [file.html]` writes a self-contained, ia-qa.com-branded HTML report of the run —
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
406
|
+
a plain-language summary of what the run checked and found (elements, pages, what drifted, how many
|
|
407
|
+
of your test files it touches, and the next action), then the verdict, per-page table, and every
|
|
408
|
+
drifted selector with its `old → new` transition — so you can attach it to the build (as above)
|
|
409
|
+
instead of scrolling the log. Add `--open` locally to pop it straight into your browser; leave it
|
|
410
|
+
off in CI, which has no browser to open.
|
|
409
411
|
|
|
410
412
|
`diff` with no arguments compares the committed `.ia-qa/baseline/` against the `.ia-qa/mapping/`
|
|
411
413
|
the previous step just re-captured — which is why the baseline has to be in git for CI to have
|
|
@@ -461,6 +463,9 @@ No. This tool brings its own browser. One install, not two.
|
|
|
461
463
|
**Cypress or Playwright or Selenium?**
|
|
462
464
|
All of them, and any language. The `fix` command replaces the selector wherever it appears as a quoted string — that's the same in JavaScript, Python, Java, C#, Ruby.
|
|
463
465
|
|
|
466
|
+
**I use a Page Object Model — does that work?**
|
|
467
|
+
That's the best case. A POM keeps every selector in one file, so a broken selector is one property to fix, not a hunt across the suite. `fix` rewrites the selector string right there in the POM, and every test that uses it is fixed at once. (Tip: if your selector properties are named `…Selector`, `ia-qa-heal ingest` inventories them too, so `fix` finds the file on its own — otherwise just pass the POM file to `fix`.)
|
|
468
|
+
|
|
464
469
|
**Why is my "renamed" element not fixed automatically?**
|
|
465
470
|
Because the selector still works — your test isn't broken. But the button now says something different, which might be a real change worth failing on. Only a human knows.
|
|
466
471
|
|
package/dist/htmlReport.js
CHANGED
|
@@ -81,6 +81,46 @@ const COUNT_FIELDS = [
|
|
|
81
81
|
{ key: 'rebound', label: 'Rebound', tone: 'fail' },
|
|
82
82
|
{ key: 'added', label: 'New', tone: 'info' },
|
|
83
83
|
];
|
|
84
|
+
function plural(n, one) {
|
|
85
|
+
return `${n} ${one}${n === 1 ? '' : 's'}`;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* A plain-language sentence describing what this run checked and found, driven
|
|
89
|
+
* entirely by the same totals the console prints. `diff` detects — it never
|
|
90
|
+
* writes — so the wording says what drifted and what the next action is; it
|
|
91
|
+
* never claims a rewrite this run did not perform.
|
|
92
|
+
*/
|
|
93
|
+
function renderRunSummary(agg, reports, meta) {
|
|
94
|
+
const elements = agg.totals.total;
|
|
95
|
+
const pages = agg.pageReports.length;
|
|
96
|
+
const scope = `Checked ${plural(elements, 'element')} across ${plural(pages, 'page')} against your baseline`;
|
|
97
|
+
const driftRows = reports.flatMap(({ report }) => report.rows.filter((r) => r.status !== 'ok'));
|
|
98
|
+
const filesTouched = new Set();
|
|
99
|
+
if (meta.usage) {
|
|
100
|
+
for (const r of driftRows) {
|
|
101
|
+
const sites = meta.usage.selectors[r.selector];
|
|
102
|
+
if (sites)
|
|
103
|
+
for (const s of sites)
|
|
104
|
+
filesTouched.add(s.file);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const usageFiles = filesTouched.size > 0 ? `, touching ${plural(filesTouched.size, 'of your test file')}` : '';
|
|
108
|
+
const healable = agg.totals.healable;
|
|
109
|
+
const blockers = agg.totals.lost + agg.totals.ambiguous + agg.totals.rebound;
|
|
110
|
+
let body;
|
|
111
|
+
if (agg.verdict === 'PASS') {
|
|
112
|
+
body = `${scope}. No selector drifted — nothing in your tests needs touching.`;
|
|
113
|
+
}
|
|
114
|
+
else if (agg.verdict === 'FIX') {
|
|
115
|
+
body = `${scope}. ${plural(healable, 'selector')} drifted but heal deterministically${usageFiles}. Run <code>ia-qa-heal fix</code> to rewrite them old→new in place.`;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
const blockPart = `${scope}. ${plural(blockers, 'selector')} broke with no safe match${usageFiles} — a human must fix or delete those tests before anything is rewritten.`;
|
|
119
|
+
const healPart = healable > 0 ? ` ${plural(healable, 'other selector')} heal automatically once the blockers are resolved.` : '';
|
|
120
|
+
body = blockPart + healPart;
|
|
121
|
+
}
|
|
122
|
+
return `<p class="run-summary">${body}</p>`;
|
|
123
|
+
}
|
|
84
124
|
function renderDriftReportHtml(agg, reports, meta) {
|
|
85
125
|
const generated = new Date().toLocaleString('en-US', { dateStyle: 'medium', timeStyle: 'short' });
|
|
86
126
|
const tone = verdictTone(agg.verdict);
|
|
@@ -138,6 +178,7 @@ function renderDriftReportHtml(agg, reports, meta) {
|
|
|
138
178
|
const verdictLine = agg.verdict === 'PASS' ? 'No drift — your suite is safe to run.'
|
|
139
179
|
: agg.verdict === 'FIX' ? 'Healable drift — deterministic old→new rewrites available via ia-qa-heal fix.'
|
|
140
180
|
: 'A selector broke with no safe match — a human must fix or delete the test before anything is rewritten.';
|
|
181
|
+
const runSummary = renderRunSummary(agg, reports, meta);
|
|
141
182
|
return `<!DOCTYPE html>
|
|
142
183
|
<html lang="en">
|
|
143
184
|
<head>
|
|
@@ -167,6 +208,8 @@ function renderDriftReportHtml(agg, reports, meta) {
|
|
|
167
208
|
section{background:var(--surface);border:1px solid var(--border);border-radius:14px;padding:20px;margin-bottom:18px}
|
|
168
209
|
section>h2{font-size:12px;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);margin-bottom:14px;font-weight:700}
|
|
169
210
|
.hero{border-left:3px solid var(--orange);display:flex;flex-direction:column;gap:14px}
|
|
211
|
+
.run-summary{color:var(--muted);font-size:13.5px;line-height:1.6;max-width:74ch;margin:-2px 0 2px}
|
|
212
|
+
.run-summary code{background:var(--surface2);border:1px solid var(--border);border-radius:6px;padding:1px 6px;color:var(--orange2)}
|
|
170
213
|
.verdict{display:inline-flex;align-items:center;gap:12px;font-size:15px;color:var(--muted)}
|
|
171
214
|
.verdict .big{font-size:26px;font-weight:800;letter-spacing:.04em;padding:8px 22px;border-radius:12px}
|
|
172
215
|
.verdict-pass .big,.verdict-pass{color:var(--pass)}.verdict-pass .big{background:#10b98118;border:1px solid #10b98155}
|
|
@@ -232,6 +275,7 @@ function renderDriftReportHtml(agg, reports, meta) {
|
|
|
232
275
|
<main><div class="wrap">
|
|
233
276
|
<section class="hero verdict-${tone}">
|
|
234
277
|
<div class="verdict verdict-${tone}"><span class="big">${esc(agg.verdict)}</span><span>${esc(verdictLine)}</span></div>
|
|
278
|
+
${runSummary}
|
|
235
279
|
<div class="stats">${statsHtml}</div>
|
|
236
280
|
</section>
|
|
237
281
|
${layoutHtml}
|
package/dist/htmlReport.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"htmlReport.js","sourceRoot":"","sources":["../src/htmlReport.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"htmlReport.js","sourceRoot":"","sources":["../src/htmlReport.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ia-qa/self-healing",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
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 — nothing leaves it.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"self-healing",
|