@ia-qa/self-healing 1.6.1 → 1.6.3
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 +17 -0
- package/TUTORIAL.md +49 -1
- package/dist/cli/args.js +1 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/audit.js +5 -0
- package/dist/cli/audit.js.map +1 -1
- package/dist/cli/check.js +5 -0
- package/dist/cli/check.js.map +1 -1
- package/dist/cli/diff.d.ts +8 -0
- package/dist/cli/diff.js +48 -8
- package/dist/cli/diff.js.map +1 -1
- package/dist/cli/index.js +18 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/skill.d.ts +33 -0
- package/dist/cli/skill.js +149 -0
- package/dist/cli/skill.js.map +1 -0
- package/dist/cli/summary.d.ts +13 -0
- package/dist/cli/summary.js +18 -0
- package/dist/cli/summary.js.map +1 -1
- package/dist/cli-ai/index.js +13 -1
- package/dist/cli-ai/index.js.map +1 -1
- package/dist/config.d.ts +7 -0
- package/dist/config.js +15 -0
- package/dist/config.js.map +1 -1
- package/dist/htmlReport.d.ts +19 -0
- package/dist/htmlReport.js +31 -3
- package/dist/htmlReport.js.map +1 -1
- package/package.json +2 -1
- package/skills/ia-qa-heal/SKILL.md +101 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ia-qa-heal
|
|
3
|
+
description: >-
|
|
4
|
+
Repair, audit and reason about E2E test locators (Playwright, Cypress, Selenium) by
|
|
5
|
+
reading a local page contract instead of opening a browser. Use when a UI test fails on
|
|
6
|
+
a locator (selector not found, strict-mode violation, a renamed button or label), when
|
|
7
|
+
tests must be updated after a UI change, when asked which pages a suite covers, or
|
|
8
|
+
whether a suite still names elements that exist. Requires @ia-qa/self-healing
|
|
9
|
+
(`ia-qa-heal`). Runs entirely on the user's machine.
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# ia-qa-heal — heal locators from the contract, not from a browser
|
|
13
|
+
|
|
14
|
+
## 1. Read the contract before you open anything
|
|
15
|
+
|
|
16
|
+
`.ia-qa/mapping/<page>.json` is a captured snapshot of every interactive element on a page:
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"page": "checkout", "url": "/checkout", "capturedAt": "2026-08-02T17:40:20.067Z",
|
|
21
|
+
"elements": [
|
|
22
|
+
{ "role": "button", "name": "Pay now", "selector": "#root form > button", "context": "main" },
|
|
23
|
+
{ "role": "link", "name": "Back to cart", "selector": "a[href=\"/cart\"]", "context": "nav", "href": "/cart" }
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
A failing locator is usually answered by **reading that file**: the element's current role, its
|
|
29
|
+
accessible name, a selector that works. A test asserting a `button` where the page now renders a
|
|
30
|
+
`link` is one `grep` away — no browser, no screenshot, no round-trip. Do this first.
|
|
31
|
+
|
|
32
|
+
Where things live:
|
|
33
|
+
|
|
34
|
+
| Path | What it is |
|
|
35
|
+
|---|---|
|
|
36
|
+
| `.ia-qa/mapping/` | the current capture |
|
|
37
|
+
| `.ia-qa/baseline/` | the committed reference `diff` compares against |
|
|
38
|
+
| `.ia-qa/mapping/_layouts/` | elements shared by every page (navbar, footer) — one fix, not N |
|
|
39
|
+
| `.ia-qa/usage.json` | the locators the suite actually uses (produced by `ingest`) |
|
|
40
|
+
| `.ia-qa/mapping/_overview.md`, `_navigation.md`/`.svg` | app index + navigation graph |
|
|
41
|
+
|
|
42
|
+
Open a browser only when the contract *cannot* answer: the page is not mapped, or the element
|
|
43
|
+
exists only in a state nothing captured (behind a tab, a modal, a mode toggle).
|
|
44
|
+
|
|
45
|
+
## 2. Which verb answers which question
|
|
46
|
+
|
|
47
|
+
| The user's question | Verb |
|
|
48
|
+
|---|---|
|
|
49
|
+
| "my tests broke — fix them" | `run` (capture during their suite → diff → confirm → fix → re-run to verify) |
|
|
50
|
+
| "did anything drift?" | `diff` → PASS/FIX/BLOCK (the CI gate) |
|
|
51
|
+
| "day one, no baseline — is my suite still valid?" | `audit` |
|
|
52
|
+
| "is the app I mapped even sound?" | `check` (dead links · unnamed elements · name collisions · orphan pages) |
|
|
53
|
+
| "which pages am I *not* covering?" | `discover` (`--sitemap` / `--crawl`; suggests only) |
|
|
54
|
+
| "give me the app's structure" | `graph --format mermaid\|svg\|json\|markdown` |
|
|
55
|
+
| "apply the rewrites" | `fix` — `--dry-run` first, always |
|
|
56
|
+
| "what do my tests actually use?" | `ingest` |
|
|
57
|
+
| first-time setup | write `.ia-qa/config.json` directly — `init` is a TTY wizard and **will refuse in your shell** |
|
|
58
|
+
|
|
59
|
+
Exact flags: `ia-qa-heal <verb> --help`. Do not guess them from this file.
|
|
60
|
+
|
|
61
|
+
## 3. Reading a verdict
|
|
62
|
+
|
|
63
|
+
- **PASS** — nothing moved.
|
|
64
|
+
- **FIX** — every drifted element was re-identified; `fix` rewrites them deterministically.
|
|
65
|
+
- **BLOCK** — a human decides.
|
|
66
|
+
|
|
67
|
+
Row statuses: `ok`, `renamed`, `healable`, `ambiguous`, `lost`, `added`. Any row may also carry
|
|
68
|
+
`rebound: true` + `reboundTo`.
|
|
69
|
+
|
|
70
|
+
BLOCK is raised by `lost` (element gone), `ambiguous` (several candidates — a coin flip), `rebound`
|
|
71
|
+
(the old selector still resolves, but onto a **different** element: the test stays green while
|
|
72
|
+
clicking the wrong thing), or a name-drift finding that is not attributable.
|
|
73
|
+
|
|
74
|
+
## 4. Never do this
|
|
75
|
+
|
|
76
|
+
1. **Never hand-rewrite a locator reported `unattributable`.** `getByText`, `cy.contains`,
|
|
77
|
+
`getByTitle`, `getByAltText` name a **string, not an element** — nothing proves the test meant
|
|
78
|
+
the renamed button rather than a heading that never moved. They are reported with `file:line`
|
|
79
|
+
and hold the verdict at BLOCK *on purpose*. Editing one breaks a test that was **passing** —
|
|
80
|
+
the only outcome worse than the drift. Surface it to the human instead.
|
|
81
|
+
2. **Never treat `audit` as a gate.** It is advisory (exit 0) unless `--strict`: a "missing"
|
|
82
|
+
locator may live on an unmapped page, or an unmapped *state*.
|
|
83
|
+
3. **Never call a green `run` a green app.** `run` only re-captures the pages the suite actually
|
|
84
|
+
exercised; the rest keep the baseline's `capturedAt`, are `stale`, and sit outside the verdict.
|
|
85
|
+
Read the coverage line it prints before concluding anything.
|
|
86
|
+
4. **Never diff a `map` baseline against a `run` capture.** The two read a page differently and
|
|
87
|
+
produce phantom drift. The tool warns — take the warning, don't explain it away.
|
|
88
|
+
5. **Never run `fix` blind.** `--dry-run` first, show the plan, then apply. It never commits;
|
|
89
|
+
neither should you without the human seeing the diff.
|
|
90
|
+
6. **There is no `--ai` flag on `ia-qa-heal`,** and adding one is not the fix — the gate stays
|
|
91
|
+
deterministic by design. The BYOK layer is the separate `ia-qa-heal-ai` binary: it *suggests*
|
|
92
|
+
matches for `lost`/`ambiguous` rows for a human to confirm, and never gates CI.
|
|
93
|
+
7. **Renames need an inventory.** `diff` can only gate on a changed *label* if `ingest` has
|
|
94
|
+
inventoried what the suite uses. No `usage.json` ⇒ no name escalation — so if their tests
|
|
95
|
+
locate by `getByRole(..., { name })`, run `ingest` before trusting a PASS.
|
|
96
|
+
|
|
97
|
+
## 5. What leaves the machine
|
|
98
|
+
|
|
99
|
+
Nothing, except: requests to the user's **own** `baseUrl` (`check`'s link half, `discover --crawl`
|
|
100
|
+
— GET only, same origin, never a `/logout` or `/delete` URL), and `ia-qa-heal-ai` calling the
|
|
101
|
+
user's own LLM if they opted in. Say that plainly rather than implying more or less.
|