@ia-qa/qa-discovery 0.3.0 → 0.5.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 +109 -3
- package/ROADMAP.md +37 -4
- package/TUTORIAL.md +85 -2
- package/dist/ai/classify.d.ts +13 -36
- package/dist/ai/classify.js +23 -166
- package/dist/ai/classify.js.map +1 -1
- package/dist/ai/model.d.ts +93 -0
- package/dist/ai/model.js +192 -0
- package/dist/ai/model.js.map +1 -0
- package/dist/ai/plan.d.ts +224 -0
- package/dist/ai/plan.js +0 -0
- package/dist/ai/plan.js.map +1 -0
- package/dist/cli/args.js +2 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/generate.d.ts +56 -0
- package/dist/cli/generate.js +293 -0
- package/dist/cli/generate.js.map +1 -0
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +32 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/skill.d.ts +20 -0
- package/dist/cli/skill.js +63 -0
- package/dist/cli/skill.js.map +1 -0
- package/dist/cli-ai/index.d.ts +3 -2
- package/dist/cli-ai/index.js +268 -4
- package/dist/cli-ai/index.js.map +1 -1
- package/dist/coverage.d.ts +52 -2
- package/dist/coverage.js +67 -7
- package/dist/coverage.js.map +1 -1
- package/dist/coverageView.js +17 -1
- package/dist/coverageView.js.map +1 -1
- package/dist/generate.d.ts +62 -0
- package/dist/generate.js +163 -0
- package/dist/generate.js.map +1 -0
- package/dist/htmlReport.js +20 -4
- package/dist/htmlReport.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +32 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +49 -0
- package/dist/mcp/server.js +143 -20
- package/dist/mcp/server.js.map +1 -1
- package/dist/overview.d.ts +9 -0
- package/dist/overview.js +9 -4
- package/dist/overview.js.map +1 -1
- package/dist/overviewFile.js +5 -0
- package/dist/overviewFile.js.map +1 -1
- package/dist/planView.d.ts +141 -0
- package/dist/planView.js +345 -0
- package/dist/planView.js.map +1 -0
- package/package.json +3 -2
- package/skills/ia-qa-discover/SKILL.md +166 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { type AiProvider } from '@ia-qa/self-healing';
|
|
2
|
+
import type { PageCapture, Heading } from '../capture/page';
|
|
3
|
+
import { type CaptureIndex, type Citation, type CitationVerdict } from '../citations';
|
|
4
|
+
import { type ModelOptions } from './model';
|
|
5
|
+
/**
|
|
6
|
+
* The BYOK reading of a page: **what someone comes here to do**, and what they cannot do if
|
|
7
|
+
* it breaks.
|
|
8
|
+
*
|
|
9
|
+
* **Why this is not `classify` with a different prompt.** The deterministic half of this
|
|
10
|
+
* package answers what the app *accepts* — fields, types, required, what moved. `classify`
|
|
11
|
+
* answers what an entry point *is*, against a closed taxonomy. Neither can answer what a
|
|
12
|
+
* human is *trying to do*, and no amount of DOM says it: nothing in a capture states that a
|
|
13
|
+
* declined payment must show a message, or that this form is how a locked-out customer gets
|
|
14
|
+
* back in. That is the axis this file plays, and it is why the two layers are not ranked
|
|
15
|
+
* against each other — neither is a subset of the other.
|
|
16
|
+
*
|
|
17
|
+
* **It sends strictly less than `classify`, and that is a design decision, not an
|
|
18
|
+
* optimisation.** No selectors and no API calls leave for this question: they are the most
|
|
19
|
+
* sensitive half of the payload and they are technical noise for a question that is not
|
|
20
|
+
* technical. `planPayload` below IS what goes, `planEgressNotice` is derived from it, and a
|
|
21
|
+
* field added to one owes a line in the other.
|
|
22
|
+
*
|
|
23
|
+
* **It produces prose, never code.** Test code stays the deterministic generator's job, so
|
|
24
|
+
* that locators come from the contract and healing can repair them. A model sentence that
|
|
25
|
+
* became a locator would be a selector nobody can repair.
|
|
26
|
+
*
|
|
27
|
+
* **It gates nothing, and it ranks nothing.** `coverage` decides the order from what it
|
|
28
|
+
* measured; this adds a labelled line beside each page. A model reading that reordered a
|
|
29
|
+
* measured list would be exactly the confident-and-unfalsifiable number this package spends
|
|
30
|
+
* its design refusing.
|
|
31
|
+
*/
|
|
32
|
+
export declare const PLAN_SCHEMA = "qa-discovery-plan@1";
|
|
33
|
+
export declare const PLAN_FILENAME = "plan.json";
|
|
34
|
+
export interface PlanReading {
|
|
35
|
+
page: string;
|
|
36
|
+
/** What someone comes to this page to do, in the words of whoever uses the app. */
|
|
37
|
+
purpose: string;
|
|
38
|
+
/** What that person cannot do if this page breaks. */
|
|
39
|
+
impact: string;
|
|
40
|
+
/** The model's own number, kept and shown. Nothing is discarded on it. */
|
|
41
|
+
confidence: number;
|
|
42
|
+
evidence: Citation[];
|
|
43
|
+
/**
|
|
44
|
+
* The model looked and could not tell what the page is for.
|
|
45
|
+
*
|
|
46
|
+
* A result, never a gap — and never silently dropped. The capture may genuinely not say
|
|
47
|
+
* (a bare dashboard shell, a page whose whole content arrives after a click), and a
|
|
48
|
+
* proposal nobody can anchor is worth reading as long as it is labelled as one.
|
|
49
|
+
*/
|
|
50
|
+
unclear?: boolean;
|
|
51
|
+
}
|
|
52
|
+
export interface DroppedReading {
|
|
53
|
+
reading: Partial<PlanReading>;
|
|
54
|
+
reason: string;
|
|
55
|
+
rejected: Array<Extract<CitationVerdict, {
|
|
56
|
+
ok: false;
|
|
57
|
+
}>>;
|
|
58
|
+
}
|
|
59
|
+
export type PageReadingOutcome = {
|
|
60
|
+
status: 'read';
|
|
61
|
+
reading: PlanReading;
|
|
62
|
+
} | {
|
|
63
|
+
status: 'unclear';
|
|
64
|
+
reading: PlanReading;
|
|
65
|
+
} | {
|
|
66
|
+
status: 'dropped';
|
|
67
|
+
dropped: DroppedReading;
|
|
68
|
+
}
|
|
69
|
+
/** The call did not succeed. A fact about the request, never about the app. */
|
|
70
|
+
| {
|
|
71
|
+
status: 'failed';
|
|
72
|
+
reason: string;
|
|
73
|
+
};
|
|
74
|
+
/** Every heading sent. The same cap `classify` uses, for the same reason: a prompt is not a page. */
|
|
75
|
+
export declare const HEADING_LIMIT = 25;
|
|
76
|
+
/**
|
|
77
|
+
* Share of pages a heading must appear on to count as the app's shell rather than this page's
|
|
78
|
+
* content. The same 0.6 `autoLayout` uses, through the same `minPagesForLayout` — including
|
|
79
|
+
* its floor of 2, so on a two-page capture a heading cannot become "shared" by appearing
|
|
80
|
+
* once.
|
|
81
|
+
*/
|
|
82
|
+
export declare const SHELL_THRESHOLD = 0.6;
|
|
83
|
+
/**
|
|
84
|
+
* Headings that belong to the shell, not to any page.
|
|
85
|
+
*
|
|
86
|
+
* Measured on a real run: a page whose whole interest was `🗂️ Environment Manager` had its
|
|
87
|
+
* reading cited against `Legal`, `Contact` and `Tools` — the footer. Those citations resolve,
|
|
88
|
+
* so nothing rejected them, and the check that is supposed to anchor the reading was anchoring
|
|
89
|
+
* it to furniture. Removing them from the payload removes the temptation rather than judging
|
|
90
|
+
* it afterwards, which is the same move `offeredPlanPaths` makes for invented paths.
|
|
91
|
+
*
|
|
92
|
+
* This is the heading analogue of `promoteSharedCalls`, and deliberately not a new rule: a
|
|
93
|
+
* third threshold convention in one repo is a third thing to drift.
|
|
94
|
+
*/
|
|
95
|
+
export declare function shellHeadings(pages: PageCapture[]): Set<string>;
|
|
96
|
+
/**
|
|
97
|
+
* This page's own headings, with the shell dropped — and never all of them.
|
|
98
|
+
*
|
|
99
|
+
* A page whose every heading is shared keeps them: a payload with no heading at all would be
|
|
100
|
+
* a page the model cannot read, which is a worse outcome than a noisy one. The exclusion is a
|
|
101
|
+
* narrowing of the evidence, not a way to make a page unreadable.
|
|
102
|
+
*
|
|
103
|
+
* **The index is the one in the capture file, not a position in this list.** A citation
|
|
104
|
+
* resolves `pages/x.json#headings[3]` against the real array, so renumbering a filtered list
|
|
105
|
+
* would silently point every citation at a different heading — the kind of error that
|
|
106
|
+
* produces a verified-looking claim about something else entirely.
|
|
107
|
+
*/
|
|
108
|
+
export declare function ownHeadings(page: PageCapture, shell: Set<string>): Array<{
|
|
109
|
+
index: number;
|
|
110
|
+
heading: Heading;
|
|
111
|
+
}>;
|
|
112
|
+
export interface PlanPayload {
|
|
113
|
+
page: string;
|
|
114
|
+
url: string;
|
|
115
|
+
/**
|
|
116
|
+
* Carried with their `at` paths, like everything else citable.
|
|
117
|
+
*
|
|
118
|
+
* They were flat strings here, and a real run caught it within minutes: offered as citable
|
|
119
|
+
* but shown pathless, so the model cited `#description` — the shape of the *prompt*, not
|
|
120
|
+
* the shape of the capture, where it lives at `#meta.description`. The reading was dropped
|
|
121
|
+
* as an invented path, which is the right refusal for the wrong reason: the prompt was
|
|
122
|
+
* lying about the data and the model was right to trust it. `classify.ts` documents this
|
|
123
|
+
* exact failure, and this file repeated it. **If a field can be cited, it is shown with the
|
|
124
|
+
* path that addresses it.**
|
|
125
|
+
*/
|
|
126
|
+
title: {
|
|
127
|
+
at: string;
|
|
128
|
+
value: string;
|
|
129
|
+
};
|
|
130
|
+
description: {
|
|
131
|
+
at: string;
|
|
132
|
+
value: string;
|
|
133
|
+
};
|
|
134
|
+
headings: Array<{
|
|
135
|
+
at: string;
|
|
136
|
+
level: number;
|
|
137
|
+
text: string;
|
|
138
|
+
}>;
|
|
139
|
+
forms: Array<{
|
|
140
|
+
at: string;
|
|
141
|
+
submits: boolean;
|
|
142
|
+
fields: Record<string, unknown>[];
|
|
143
|
+
}>;
|
|
144
|
+
fields: Record<string, unknown>[];
|
|
145
|
+
/**
|
|
146
|
+
* The names of the other pages in this capture — no URLs, no titles, no content.
|
|
147
|
+
*
|
|
148
|
+
* A page cannot be placed in an app it cannot see: "reset" reads very differently in a
|
|
149
|
+
* capture that also holds `login` and `account` than in one that holds `admin-users`. The
|
|
150
|
+
* cheapest context that answers that, and it is a list of slugs the person already sees in
|
|
151
|
+
* their own capture directory.
|
|
152
|
+
*/
|
|
153
|
+
otherPages: string[];
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Exactly what is sent for one page. The egress notice is written from this function's
|
|
157
|
+
* output, so what it promises cannot drift from what goes.
|
|
158
|
+
*/
|
|
159
|
+
export declare function planPayload(page: PageCapture, otherPages?: string[], shell?: Set<string>): PlanPayload;
|
|
160
|
+
/**
|
|
161
|
+
* Every path the prompt offers, and therefore the only paths a citation may use.
|
|
162
|
+
*
|
|
163
|
+
* The same guardrail `classify` learned the hard way: a model given a shape invents paths
|
|
164
|
+
* that exist in the prompt and nowhere in the capture. Refusing a constructed path removes
|
|
165
|
+
* the class of error instead of catching it afterwards. Note what is NOT here — `apiCalls`,
|
|
166
|
+
* which this verb does not send and therefore may not be cited.
|
|
167
|
+
*/
|
|
168
|
+
export declare function offeredPlanPaths(page: PageCapture, shell?: Set<string>): Set<string>;
|
|
169
|
+
/**
|
|
170
|
+
* A page with nothing citable cannot produce a falsifiable reading, so it is never sent.
|
|
171
|
+
*
|
|
172
|
+
* Not a failure and never counted as one: a page that says nothing about itself is a finding
|
|
173
|
+
* about the app, and inventing a purpose for it is the one thing this layer must not do.
|
|
174
|
+
*/
|
|
175
|
+
export declare function isReadable(page: PageCapture): boolean;
|
|
176
|
+
/**
|
|
177
|
+
* The citations that actually carry the page's subject: a top-level heading, a form, or a
|
|
178
|
+
* field.
|
|
179
|
+
*
|
|
180
|
+
* `classify` learned that a citation pointing at the thing being classified proves nothing.
|
|
181
|
+
* The sibling failure here is a citation that resolves and supports nothing — a footer link,
|
|
182
|
+
* a `meta.description` shared by the whole site. Measured on a real run: every citation on
|
|
183
|
+
* one page was a heading, and half of them were the footer.
|
|
184
|
+
*
|
|
185
|
+
* So at least one citation must land here. The rule is **conditional on the page having
|
|
186
|
+
* one**: a page whose only headings are level 3 and which takes no input cannot satisfy it,
|
|
187
|
+
* and dropping its reading would punish the page for its own markup. Same shape as the
|
|
188
|
+
* offered-paths check — a rule that cannot be met is not applied.
|
|
189
|
+
*/
|
|
190
|
+
export declare function anchorPaths(page: PageCapture, shell?: Set<string>): Set<string>;
|
|
191
|
+
export declare function buildPlanPrompt(page: PageCapture, otherPages?: string[], shell?: Set<string>): string;
|
|
192
|
+
/**
|
|
193
|
+
* What leaves this machine for this verb, said before it leaves.
|
|
194
|
+
*
|
|
195
|
+
* Derived from `planPayload`: every line below is a field that function actually puts in the
|
|
196
|
+
* request, and the two "does NOT leave" lines name what `classify` sends and this does not.
|
|
197
|
+
* That difference is the reason this verb exists as its own notice rather than reusing the
|
|
198
|
+
* other — announcing more than goes is the mirror image of announcing less, and both make
|
|
199
|
+
* the announcement worthless.
|
|
200
|
+
*
|
|
201
|
+
* stderr in every mode, `--json` included: a security announcement, not decoration.
|
|
202
|
+
*/
|
|
203
|
+
export declare function planEgressNotice(provider: AiProvider, model: string, pages: number, planned?: boolean, baseUrl?: string): string;
|
|
204
|
+
/**
|
|
205
|
+
* Validate one reading against the capture.
|
|
206
|
+
*
|
|
207
|
+
* The order is the same as `classify`'s and for the same reason: shape first, then the
|
|
208
|
+
* citations. A reply that is not the requested shape is not a reply whose evidence is worth
|
|
209
|
+
* resolving.
|
|
210
|
+
*/
|
|
211
|
+
export declare function validateReading(raw: Partial<PlanReading> & Record<string, unknown>, page: PageCapture, index: CaptureIndex, offered?: Set<string>, anchors?: Set<string>): {
|
|
212
|
+
ok: true;
|
|
213
|
+
value: PlanReading;
|
|
214
|
+
} | {
|
|
215
|
+
ok: false;
|
|
216
|
+
dropped: DroppedReading;
|
|
217
|
+
};
|
|
218
|
+
/**
|
|
219
|
+
* One page in, one outcome out. Never throws: this layer is optional by construction, and a
|
|
220
|
+
* bad key must not take down a deterministic capture that already succeeded.
|
|
221
|
+
*/
|
|
222
|
+
export declare function readPage(page: PageCapture, index: CaptureIndex, opts: ModelOptions, otherPages?: string[],
|
|
223
|
+
/** Headings the whole app shares. The caller computes it once, over every captured page. */
|
|
224
|
+
shell?: Set<string>): Promise<PageReadingOutcome>;
|
package/dist/ai/plan.js
ADDED
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/ai/plan.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/args.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.KNOWN_FLAGS = void 0;
|
|
|
4
4
|
exports.rejectUnknownFlags = rejectUnknownFlags;
|
|
5
5
|
/** Flag validation for the hand-rolled CLI parser — mirrors `@ia-qa/self-healing`'s `cli/args.ts`. */
|
|
6
6
|
exports.KNOWN_FLAGS = {
|
|
7
|
+
skill: ["--install", "--user", "--dir", "--print", "--force"],
|
|
7
8
|
scan: [
|
|
8
9
|
'--depth',
|
|
9
10
|
'--max',
|
|
@@ -23,6 +24,7 @@ exports.KNOWN_FLAGS = {
|
|
|
23
24
|
login: ['--url', '--session'],
|
|
24
25
|
history: ['--json', '--limit'],
|
|
25
26
|
coverage: ['--json', '--report', '--open'],
|
|
27
|
+
generate: ['--json', '--out', '--force'],
|
|
26
28
|
};
|
|
27
29
|
function rejectUnknownFlags(command, args) {
|
|
28
30
|
const known = exports.KNOWN_FLAGS[command];
|
package/dist/cli/args.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":";;;AAyBA,gDAQC;AAjCD,sGAAsG;AACzF,QAAA,WAAW,GAAsC;IAC5D,KAAK,EAAE,CAAC,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC;IAC7D,IAAI,EAAE;QACJ,SAAS;QACT,OAAO;QACP,aAAa;QACb,eAAe;QACf,WAAW;QACX,cAAc;QACd,cAAc;QACd,QAAQ;QACR,eAAe;QACf,qBAAqB;QACrB,QAAQ;QACR,QAAQ;QACR,UAAU;QACV,QAAQ;KACT;IACD,KAAK,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC;IAC7B,OAAO,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC9B,QAAQ,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC;IAC1C,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC;CACzC,CAAC;AAEF,SAAgB,kBAAkB,CAAC,OAAe,EAAE,IAAc;IAChE,MAAM,KAAK,GAAG,mBAAW,CAAC,OAAO,CAAC,CAAC;IACnC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO;IAChC,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QACjC,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,SAAS;QAChC,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,yBAAyB,OAAO,kDAAkD,CAAC,CAAC;IACxH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { PageMapping } from '@ia-qa/self-healing';
|
|
2
|
+
/**
|
|
3
|
+
* `ia-qa-discover generate` — a starting suite for the pages nothing tests.
|
|
4
|
+
*
|
|
5
|
+
* **Why it lives here and not in `@ia-qa/self-healing`.** It needs both halves: the contract,
|
|
6
|
+
* to name elements the way healing will repair them, and the capture, to know which fields a
|
|
7
|
+
* page takes and which of them carry a durable identity. Discovery already depends on
|
|
8
|
+
* healing; the reverse would invert a publish order that exists to be enforced. So the
|
|
9
|
+
* package that already holds both is the one that gets the verb.
|
|
10
|
+
*
|
|
11
|
+
* **What it proposes, never applies.** Files land in their own directory and an existing one
|
|
12
|
+
* is never overwritten without `--force` — the same restraint as `discover --apply` and
|
|
13
|
+
* `heal skill`. A generated test is a proposal a human reads, and nothing here adds it to
|
|
14
|
+
* anyone's suite.
|
|
15
|
+
*
|
|
16
|
+
* **Default target is the gap, not the app.** With no arguments it generates for the pages
|
|
17
|
+
* the coverage map says nothing tests, because generating over pages already covered is how
|
|
18
|
+
* a suite doubles in size without covering one more thing. Named pages override that.
|
|
19
|
+
*/
|
|
20
|
+
export declare const GENERATED_DIRNAME = "generated";
|
|
21
|
+
export declare function generatedDir(cwd?: string): string;
|
|
22
|
+
export declare function runGenerate(args: string[]): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Whether healing would ever read what was just written.
|
|
25
|
+
*
|
|
26
|
+
* This fires on the default, and that is the point. Measured on a real project: the specs
|
|
27
|
+
* landed in `.ia-qa-discovery/generated/` while healing's `testPaths` was `["tests/"]`, so
|
|
28
|
+
* `ingest` inventoried nothing from them — no name drift would escalate, `fix` would never
|
|
29
|
+
* rewrite them, and "born already maintained" was simply false. The first check of it looked
|
|
30
|
+
* green for the wrong reason: the placeholders were in `usage.json` because the project's own
|
|
31
|
+
* suite already used them, and every recorded site was in `tests/`.
|
|
32
|
+
*
|
|
33
|
+
* Writing into someone's suite by default would be the other error — this verb produces
|
|
34
|
+
* proposals, and a proposal does not install itself. So the default stays out of the way and
|
|
35
|
+
* says so, with both remedies, only when it is actually out of reach.
|
|
36
|
+
*/
|
|
37
|
+
export declare function healingReach(outDir: string, cwd?: string): {
|
|
38
|
+
covered: boolean;
|
|
39
|
+
why: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* The contract for a captured page, by name and then by URL.
|
|
43
|
+
*
|
|
44
|
+
* The URL fallback is not belt-and-braces, it is the ordinary case on a configured project.
|
|
45
|
+
* Both packages resolve a page name through the same `pageNameFromUrl`, but healing's
|
|
46
|
+
* `config.pages` may *declare* a name, and that declaration wins there and is invisible here:
|
|
47
|
+
* measured on a real app, discovery captured `/` as `home` while the contract for the very
|
|
48
|
+
* same URL was filed as `login`. Matching on the name alone found nothing, so the generator
|
|
49
|
+
* fell back to the page's own placeholder text — a locator that works, but not the one the
|
|
50
|
+
* contract holds and therefore not one healing will rewrite. Silently producing the weaker
|
|
51
|
+
* form is exactly the failure this whole feature is built to avoid.
|
|
52
|
+
*
|
|
53
|
+
* A page with no contract at all is still generated, from its capture alone — thinner, and
|
|
54
|
+
* never fatal.
|
|
55
|
+
*/
|
|
56
|
+
export declare function contractOf(name: string, url: string, mappingPath: string): PageMapping | null;
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.GENERATED_DIRNAME = void 0;
|
|
37
|
+
exports.generatedDir = generatedDir;
|
|
38
|
+
exports.runGenerate = runGenerate;
|
|
39
|
+
exports.healingReach = healingReach;
|
|
40
|
+
exports.contractOf = contractOf;
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const self_healing_1 = require("@ia-qa/self-healing");
|
|
44
|
+
const config_1 = require("../config");
|
|
45
|
+
const coverage_1 = require("../coverage");
|
|
46
|
+
const generate_1 = require("../generate");
|
|
47
|
+
/** `--out <dir>`, and the remaining arguments with it removed. */
|
|
48
|
+
function takeValueFlag(args, flag, fallback) {
|
|
49
|
+
const at = args.indexOf(flag);
|
|
50
|
+
if (at === -1)
|
|
51
|
+
return { value: fallback, rest: args };
|
|
52
|
+
const value = args[at + 1];
|
|
53
|
+
if (value === undefined || value.startsWith('-')) {
|
|
54
|
+
throw new Error(`${flag} needs a directory, e.g. \`${flag} tests/generated\`.`);
|
|
55
|
+
}
|
|
56
|
+
return { value: path.resolve(process.cwd(), value), rest: [...args.slice(0, at), ...args.slice(at + 2)] };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* `ia-qa-discover generate` — a starting suite for the pages nothing tests.
|
|
60
|
+
*
|
|
61
|
+
* **Why it lives here and not in `@ia-qa/self-healing`.** It needs both halves: the contract,
|
|
62
|
+
* to name elements the way healing will repair them, and the capture, to know which fields a
|
|
63
|
+
* page takes and which of them carry a durable identity. Discovery already depends on
|
|
64
|
+
* healing; the reverse would invert a publish order that exists to be enforced. So the
|
|
65
|
+
* package that already holds both is the one that gets the verb.
|
|
66
|
+
*
|
|
67
|
+
* **What it proposes, never applies.** Files land in their own directory and an existing one
|
|
68
|
+
* is never overwritten without `--force` — the same restraint as `discover --apply` and
|
|
69
|
+
* `heal skill`. A generated test is a proposal a human reads, and nothing here adds it to
|
|
70
|
+
* anyone's suite.
|
|
71
|
+
*
|
|
72
|
+
* **Default target is the gap, not the app.** With no arguments it generates for the pages
|
|
73
|
+
* the coverage map says nothing tests, because generating over pages already covered is how
|
|
74
|
+
* a suite doubles in size without covering one more thing. Named pages override that.
|
|
75
|
+
*/
|
|
76
|
+
exports.GENERATED_DIRNAME = 'generated';
|
|
77
|
+
function generatedDir(cwd = (0, config_1.baseDir)()) {
|
|
78
|
+
return path.join(cwd, '.ia-qa-discovery', exports.GENERATED_DIRNAME);
|
|
79
|
+
}
|
|
80
|
+
async function runGenerate(args) {
|
|
81
|
+
const json = args.includes('--json');
|
|
82
|
+
const force = args.includes('--force');
|
|
83
|
+
const { value: outDir, rest } = takeValueFlag(args, '--out', generatedDir());
|
|
84
|
+
const named = rest.filter((a) => !a.startsWith('-'));
|
|
85
|
+
const surface = (0, coverage_1.loadSurface)((0, config_1.captureDir)());
|
|
86
|
+
if (!surface) {
|
|
87
|
+
return refuse(json, 'No capture to generate from.', ['Run `ia-qa-discover scan` first — a test cannot be written for a page nobody has looked at.']);
|
|
88
|
+
}
|
|
89
|
+
const byName = new Map(surface.pages.map((p) => [p.page, p]));
|
|
90
|
+
let targets;
|
|
91
|
+
if (named.length > 0) {
|
|
92
|
+
const unknown = named.filter((n) => !byName.has(n));
|
|
93
|
+
if (unknown.length > 0) {
|
|
94
|
+
return refuse(json, `Not in this capture: ${unknown.join(', ')}.`, [
|
|
95
|
+
`Pages captured: ${[...byName.keys()].join(', ')}`,
|
|
96
|
+
]);
|
|
97
|
+
}
|
|
98
|
+
targets = named;
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
const config = (() => {
|
|
102
|
+
try {
|
|
103
|
+
return (0, config_1.loadConfig)();
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
})();
|
|
109
|
+
const coverage = (0, coverage_1.computeCoverage)({
|
|
110
|
+
captureDirPath: (0, config_1.captureDir)(),
|
|
111
|
+
healingDirPath: path.join((0, config_1.baseDir)(), coverage_1.HEALING_DIR),
|
|
112
|
+
scope: config?.outOfScope,
|
|
113
|
+
});
|
|
114
|
+
if (!coverage.ok) {
|
|
115
|
+
// Generating for every captured page instead would bury the pages that need a test
|
|
116
|
+
// under the ones already covered — a bigger suite, not a better one. The refusal names
|
|
117
|
+
// the measurement that is missing, and the pages remain reachable by name.
|
|
118
|
+
return refuse(json, `Cannot tell which pages are untested: ${coverage.refusal.message}`, [
|
|
119
|
+
...coverage.refusal.available,
|
|
120
|
+
`Or name the pages yourself: ia-qa-discover generate <page…>`,
|
|
121
|
+
]);
|
|
122
|
+
}
|
|
123
|
+
targets = coverage.map.uncovered.map((u) => u.page);
|
|
124
|
+
if (targets.length === 0) {
|
|
125
|
+
return refuse(json, 'Every page this scan reached is already visited by your suite.', [
|
|
126
|
+
`Name a page to generate for it anyway: ia-qa-discover generate <page…>`,
|
|
127
|
+
]);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const mappingPath = path.join((0, config_1.baseDir)(), coverage_1.HEALING_DIR, 'mapping');
|
|
131
|
+
const specs = targets.map((name) => {
|
|
132
|
+
const captured = byName.get(name);
|
|
133
|
+
return (0, generate_1.buildSpec)({ page: captured, contract: contractOf(name, captured.url, mappingPath) });
|
|
134
|
+
});
|
|
135
|
+
const written = [];
|
|
136
|
+
const kept = [];
|
|
137
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
138
|
+
for (const spec of specs) {
|
|
139
|
+
const file = path.join(outDir, `${spec.page}.spec.js`);
|
|
140
|
+
if (fs.existsSync(file) && !force) {
|
|
141
|
+
kept.push(path.relative(process.cwd(), file) || file);
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
fs.writeFileSync(file, spec.code, 'utf8');
|
|
145
|
+
written.push({
|
|
146
|
+
page: spec.page,
|
|
147
|
+
file: path.relative(process.cwd(), file) || file,
|
|
148
|
+
locators: spec.locators.length,
|
|
149
|
+
skipped: spec.skipped.length,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
if (json) {
|
|
153
|
+
console.log(JSON.stringify({ written, kept, specs: specs.map(({ code, ...rest }) => rest) }, null, 2));
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
console.log(`\n✍️ Generated ${written.length} spec${written.length === 1 ? '' : 's'} → ${path.relative(process.cwd(), outDir) || outDir}`);
|
|
157
|
+
for (const w of written) {
|
|
158
|
+
const skipped = w.skipped > 0 ? ` · ${w.skipped} field${w.skipped === 1 ? '' : 's'} left out` : '';
|
|
159
|
+
console.log(` · ${w.page} — ${w.locators} locator${w.locators === 1 ? '' : 's'}${skipped}`);
|
|
160
|
+
}
|
|
161
|
+
if (kept.length > 0) {
|
|
162
|
+
console.log(`\n Left untouched (already there, --force to replace):`);
|
|
163
|
+
for (const k of kept)
|
|
164
|
+
console.log(` · ${k}`);
|
|
165
|
+
}
|
|
166
|
+
const totalSkipped = specs.reduce((n, s) => n + s.skipped.length, 0);
|
|
167
|
+
if (totalSkipped > 0) {
|
|
168
|
+
console.log(`\n ${totalSkipped} field(s) were not generated — each says why at the top of its file.\n` +
|
|
169
|
+
` Most often: no test id, id or name, so the only selector is positional. That is a\n` +
|
|
170
|
+
` finding about the app, not about this tool: such a field cannot be tested reliably\n` +
|
|
171
|
+
` by anyone, and healing could not repair it either.`);
|
|
172
|
+
}
|
|
173
|
+
const reach = healingReach(outDir);
|
|
174
|
+
if (written.length > 0 && !reach.covered) {
|
|
175
|
+
console.log(`\n ⚠ Healing cannot see these files, so it will never repair them.\n` +
|
|
176
|
+
` ${reach.why}\n` +
|
|
177
|
+
` The whole point of generating them this way is that a label change is REWRITTEN\n` +
|
|
178
|
+
` instead of turning the suite red — and that only happens for files \`ingest\`\n` +
|
|
179
|
+
` inventories. Either write them where your suite lives:\n` +
|
|
180
|
+
` ia-qa-discover generate --out <a path under your testPaths>\n` +
|
|
181
|
+
` or add this directory to "testPaths" in .ia-qa/config.json, then run:\n` +
|
|
182
|
+
` ia-qa-heal ingest`);
|
|
183
|
+
}
|
|
184
|
+
console.log(`\n These are proposals. Nothing was added to your suite, and the assertions are yours:\n` +
|
|
185
|
+
` the navigation and the actions are generated, what the app should DO is a TODO in\n` +
|
|
186
|
+
` each file. An app declares what it accepts, never what it promises.`);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Whether healing would ever read what was just written.
|
|
190
|
+
*
|
|
191
|
+
* This fires on the default, and that is the point. Measured on a real project: the specs
|
|
192
|
+
* landed in `.ia-qa-discovery/generated/` while healing's `testPaths` was `["tests/"]`, so
|
|
193
|
+
* `ingest` inventoried nothing from them — no name drift would escalate, `fix` would never
|
|
194
|
+
* rewrite them, and "born already maintained" was simply false. The first check of it looked
|
|
195
|
+
* green for the wrong reason: the placeholders were in `usage.json` because the project's own
|
|
196
|
+
* suite already used them, and every recorded site was in `tests/`.
|
|
197
|
+
*
|
|
198
|
+
* Writing into someone's suite by default would be the other error — this verb produces
|
|
199
|
+
* proposals, and a proposal does not install itself. So the default stays out of the way and
|
|
200
|
+
* says so, with both remedies, only when it is actually out of reach.
|
|
201
|
+
*/
|
|
202
|
+
function healingReach(outDir, cwd = (0, config_1.baseDir)()) {
|
|
203
|
+
let testPaths;
|
|
204
|
+
try {
|
|
205
|
+
// Healing's own resolver, never a copy of its rule: it resolves against the project root
|
|
206
|
+
// rather than the config directory, and getting that wrong points the check at a
|
|
207
|
+
// directory nobody has.
|
|
208
|
+
testPaths = (0, self_healing_1.configuredTestPaths)(cwd);
|
|
209
|
+
}
|
|
210
|
+
catch (err) {
|
|
211
|
+
return { covered: false, why: `Healing's config could not be read (${err.message}).` };
|
|
212
|
+
}
|
|
213
|
+
if (testPaths.length === 0) {
|
|
214
|
+
return { covered: false, why: `Healing declares no "testPaths", so \`ingest\` reads nothing.` };
|
|
215
|
+
}
|
|
216
|
+
const target = path.resolve(outDir);
|
|
217
|
+
const covered = testPaths.some((abs) => {
|
|
218
|
+
const rel = path.relative(abs, target);
|
|
219
|
+
return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));
|
|
220
|
+
});
|
|
221
|
+
return {
|
|
222
|
+
covered,
|
|
223
|
+
why: covered
|
|
224
|
+
? ''
|
|
225
|
+
: `They are outside "testPaths" (${testPaths.map((p) => path.relative(cwd, p) || p).join(', ')}), which is all \`ingest\` reads.`,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* The contract for a captured page, by name and then by URL.
|
|
230
|
+
*
|
|
231
|
+
* The URL fallback is not belt-and-braces, it is the ordinary case on a configured project.
|
|
232
|
+
* Both packages resolve a page name through the same `pageNameFromUrl`, but healing's
|
|
233
|
+
* `config.pages` may *declare* a name, and that declaration wins there and is invisible here:
|
|
234
|
+
* measured on a real app, discovery captured `/` as `home` while the contract for the very
|
|
235
|
+
* same URL was filed as `login`. Matching on the name alone found nothing, so the generator
|
|
236
|
+
* fell back to the page's own placeholder text — a locator that works, but not the one the
|
|
237
|
+
* contract holds and therefore not one healing will rewrite. Silently producing the weaker
|
|
238
|
+
* form is exactly the failure this whole feature is built to avoid.
|
|
239
|
+
*
|
|
240
|
+
* A page with no contract at all is still generated, from its capture alone — thinner, and
|
|
241
|
+
* never fatal.
|
|
242
|
+
*/
|
|
243
|
+
function contractOf(name, url, mappingPath) {
|
|
244
|
+
try {
|
|
245
|
+
return (0, self_healing_1.loadMapping)(name, mappingPath);
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
/* not filed under this name — try the URL */
|
|
249
|
+
}
|
|
250
|
+
const target = normalizeUrl(url);
|
|
251
|
+
if (!target)
|
|
252
|
+
return null;
|
|
253
|
+
let files;
|
|
254
|
+
try {
|
|
255
|
+
files = fs.readdirSync(mappingPath).filter((f) => f.endsWith('.json') && !f.startsWith('_'));
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
for (const file of files) {
|
|
261
|
+
try {
|
|
262
|
+
const mapping = JSON.parse(fs.readFileSync(path.join(mappingPath, file), 'utf8'));
|
|
263
|
+
if (normalizeUrl(mapping.url) === target)
|
|
264
|
+
return mapping;
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
// One unreadable contract costs one candidate, never the generation.
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
/** Host and path only: a trailing slash or a query string does not make it another page. */
|
|
273
|
+
function normalizeUrl(raw) {
|
|
274
|
+
if (!raw)
|
|
275
|
+
return null;
|
|
276
|
+
try {
|
|
277
|
+
const u = new URL(raw);
|
|
278
|
+
return `${u.host.replace(/^www\./, '')}${u.pathname.replace(/\/$/, '')}`;
|
|
279
|
+
}
|
|
280
|
+
catch {
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
function refuse(json, message, available) {
|
|
285
|
+
if (json) {
|
|
286
|
+
console.log(JSON.stringify({ generated: false, reason: message, available }, null, 2));
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
console.log(`\nℹ️ ${message}`);
|
|
290
|
+
for (const a of available)
|
|
291
|
+
console.log(`\n ${a}`);
|
|
292
|
+
}
|
|
293
|
+
//# sourceMappingURL=generate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/cli/generate.ts"],"names":[],"mappings":"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"}
|