@jevitate/cli 0.9.0 → 0.10.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/dist/anchor-baselines.d.ts +26 -0
- package/dist/anchor-baselines.js +25 -0
- package/dist/anchor-baselines.js.map +1 -0
- package/dist/approval-provenance.d.ts +32 -2
- package/dist/approval-provenance.js +92 -5
- package/dist/approval-provenance.js.map +1 -1
- package/dist/bin.js +10194 -6042
- package/dist/build-info.generated.js +2 -2
- package/dist/catalog-analysis.js +14 -0
- package/dist/catalog-analysis.js.map +1 -1
- package/dist/catalog-api.js +12 -4
- package/dist/catalog-api.js.map +1 -1
- package/dist/catalog-bundle-api.d.ts +73 -0
- package/dist/catalog-bundle-api.js +206 -0
- package/dist/catalog-bundle-api.js.map +1 -0
- package/dist/catalog-bundle-findings.d.ts +54 -0
- package/dist/catalog-bundle-findings.js +252 -0
- package/dist/catalog-bundle-findings.js.map +1 -0
- package/dist/catalog-bundle.d.ts +192 -0
- package/dist/catalog-bundle.js +578 -0
- package/dist/catalog-bundle.js.map +1 -0
- package/dist/catalog-cli.d.ts +6 -0
- package/dist/catalog-cli.js +180 -5
- package/dist/catalog-cli.js.map +1 -1
- package/dist/catalog-refs.d.ts +42 -0
- package/dist/catalog-refs.js +188 -0
- package/dist/catalog-refs.js.map +1 -0
- package/dist/catalog-review.d.ts +3 -1
- package/dist/catalog-review.js +61 -0
- package/dist/catalog-review.js.map +1 -1
- package/dist/catalog.d.ts +27 -3
- package/dist/catalog.js +46 -2
- package/dist/catalog.js.map +1 -1
- package/dist/check-api.js +162 -9
- package/dist/check-api.js.map +1 -1
- package/dist/check-cli.js +71 -2
- package/dist/check-cli.js.map +1 -1
- package/dist/check-execute.d.ts +12 -0
- package/dist/check-execute.js +55 -3
- package/dist/check-execute.js.map +1 -1
- package/dist/check-types.d.ts +98 -0
- package/dist/check-types.js.map +1 -1
- package/dist/cli-output.d.ts +6 -0
- package/dist/cli-output.js +23 -0
- package/dist/cli-output.js.map +1 -1
- package/dist/cli-shared.d.ts +10 -0
- package/dist/cli-shared.js +0 -4
- package/dist/cli-shared.js.map +1 -1
- package/dist/exit-codes.js +15 -0
- package/dist/exit-codes.js.map +1 -1
- package/dist/forge-verify.d.ts +224 -0
- package/dist/forge-verify.js +649 -0
- package/dist/forge-verify.js.map +1 -0
- package/dist/init-codeowners.d.ts +19 -0
- package/dist/init-codeowners.js +66 -0
- package/dist/init-codeowners.js.map +1 -1
- package/dist/job-draft-api.d.ts +52 -0
- package/dist/job-draft-api.js +110 -0
- package/dist/job-draft-api.js.map +1 -0
- package/dist/journeeze-api.d.ts +71 -0
- package/dist/journeeze-api.js +285 -0
- package/dist/journeeze-api.js.map +1 -0
- package/dist/journeeze-connect.d.ts +156 -0
- package/dist/journeeze-connect.js +357 -0
- package/dist/journeeze-connect.js.map +1 -0
- package/dist/journey-anchor-gate.d.ts +52 -0
- package/dist/journey-anchor-gate.js +101 -0
- package/dist/journey-anchor-gate.js.map +1 -0
- package/dist/journey-api.d.ts +1 -0
- package/dist/journey-api.js +37 -10
- package/dist/journey-api.js.map +1 -1
- package/dist/journey-cli.js +57 -5
- package/dist/journey-cli.js.map +1 -1
- package/dist/journey-heal.js +1 -1
- package/dist/journey-heal.js.map +1 -1
- package/dist/journey-lint-sarif.d.ts +3 -2
- package/dist/journey-lint-sarif.js +9 -2
- package/dist/journey-lint-sarif.js.map +1 -1
- package/dist/journey-migrate-api.d.ts +54 -0
- package/dist/journey-migrate-api.js +64 -0
- package/dist/journey-migrate-api.js.map +1 -0
- package/dist/journey-proposal-store.d.ts +9 -0
- package/dist/journey-proposal-store.js +23 -0
- package/dist/journey-proposal-store.js.map +1 -1
- package/dist/journey-result-record.d.ts +2 -0
- package/dist/journey-result-record.js +5 -0
- package/dist/journey-result-record.js.map +1 -1
- package/dist/journey-review-api.js +9 -1
- package/dist/journey-review-api.js.map +1 -1
- package/dist/journey-review.d.ts +11 -1
- package/dist/journey-review.js +77 -5
- package/dist/journey-review.js.map +1 -1
- package/dist/journey-stale-api.d.ts +40 -0
- package/dist/journey-stale-api.js +57 -0
- package/dist/journey-stale-api.js.map +1 -0
- package/dist/locator-health-api.d.ts +101 -0
- package/dist/locator-health-api.js +203 -0
- package/dist/locator-health-api.js.map +1 -0
- package/dist/locator-health.d.ts +195 -0
- package/dist/locator-health.js +419 -0
- package/dist/locator-health.js.map +1 -0
- package/dist/mcp-cli-tools.d.ts +3 -1
- package/dist/mcp-cli-tools.js +55 -5
- package/dist/mcp-cli-tools.js.map +1 -1
- package/dist/project-config.d.ts +29 -0
- package/dist/project-config.js +76 -0
- package/dist/project-config.js.map +1 -0
- package/package.json +18 -16
- package/skills/jevitate-ci-check/SKILL.md +16 -0
- package/skills/jevitate-getting-started/SKILL.md +7 -2
- package/skills/jevitate-run-journey/SKILL.md +11 -0
- package/skills/jevitate-test-campaign/SKILL.md +13 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import type { Recording, Step, TargetDescriptor } from "@jevitate/recording";
|
|
2
|
+
import type { LocatorHealth, LocatorHealthStep, LocatorRung } from "./check-types.js";
|
|
3
|
+
/**
|
|
4
|
+
* #470 — locator health, the pure core: for every step that acts on a target, the selector rung it
|
|
5
|
+
* resolves by, how robust that rung is, WHY it is brittle, and the fix for the app under test. A step
|
|
6
|
+
* is `stable` only when it resolves by a test id from the team's convention (`testIdAttributes`;
|
|
7
|
+
* `data-tflow-id` never counts, #468) that does not look generated; anything else is `brittle` and
|
|
8
|
+
* gets a suggestion — a work list for the codebase, de-duplicated by element.
|
|
9
|
+
*
|
|
10
|
+
* Static (a Journey's recorded descriptors) or dynamic (a run's `resolved` — the rung that actually
|
|
11
|
+
* matched at replay, `@jevitate/interpreter` `StepResolution`). No I/O: `locator-health-api.ts` loads
|
|
12
|
+
* Journeys, results and config; check/report/the review sheet call these helpers.
|
|
13
|
+
*/
|
|
14
|
+
/** The ladder's own grade for a rung (the recorder's `Stability`): how likely it is to survive change. */
|
|
15
|
+
export type LocatorLevel = "high" | "medium" | "low";
|
|
16
|
+
/** Why a step's locator is brittle — the stable vocabulary (machine-readable `code`, human `text`). */
|
|
17
|
+
export type BrittleReasonCode = "no-test-id" | "test-id-not-in-convention" | "tflow-id-not-a-test-id" | "generated-value" | "no-accessible-name" | "duplicate-name" | "positional-css" | "text-copy";
|
|
18
|
+
/** A run's resolution of one step (structurally `@jevitate/interpreter` `StepResolution`). */
|
|
19
|
+
export interface ResolvedStepInput {
|
|
20
|
+
readonly index: number;
|
|
21
|
+
readonly stepId?: string;
|
|
22
|
+
readonly rung: string;
|
|
23
|
+
readonly testIdAttr?: string;
|
|
24
|
+
readonly ordinal?: number;
|
|
25
|
+
readonly candidates?: number;
|
|
26
|
+
}
|
|
27
|
+
/** One step's verdict, in detail (a `LocatorHealthStep`, plus what the reports and the review sheet show). */
|
|
28
|
+
export interface LocatorHealthStepDetail extends LocatorHealthStep {
|
|
29
|
+
readonly kind: Step["kind"];
|
|
30
|
+
/** The ladder grade of the rung used. */
|
|
31
|
+
readonly level: LocatorLevel;
|
|
32
|
+
/** `recorded`: from the Journey's descriptor; `resolved`: the rung that matched at replay. */
|
|
33
|
+
readonly source: "recorded" | "resolved";
|
|
34
|
+
/** The route (path) of the page the step acts on, when known. */
|
|
35
|
+
readonly route?: string;
|
|
36
|
+
/** How the step finds its target, e.g. `role=button name="Save"`, `css=main > div:nth-of-type(2)`. */
|
|
37
|
+
readonly locator: string;
|
|
38
|
+
readonly reasonCodes: readonly BrittleReasonCode[];
|
|
39
|
+
/** The key of this step's suggestion (`LocatorSuggestion.key`); absent when stable. */
|
|
40
|
+
readonly suggestion?: string;
|
|
41
|
+
}
|
|
42
|
+
/** Where a brittle element is used. */
|
|
43
|
+
export interface LocatorOccurrence {
|
|
44
|
+
readonly journeyId?: string;
|
|
45
|
+
readonly index: number;
|
|
46
|
+
readonly stepId?: string;
|
|
47
|
+
}
|
|
48
|
+
/** One actionable fix for the app, per element (route + role + name), however many steps use it. */
|
|
49
|
+
export interface LocatorSuggestion {
|
|
50
|
+
/** The de-duplication key: `route|role|name` (or `route|css|selector` for an unnamed element). */
|
|
51
|
+
readonly key: string;
|
|
52
|
+
readonly route?: string;
|
|
53
|
+
readonly role?: string;
|
|
54
|
+
readonly name?: string;
|
|
55
|
+
/** The element in words, e.g. `the "Save" button`. */
|
|
56
|
+
readonly element: string;
|
|
57
|
+
/** A short outerHTML excerpt, when the caller had one (a live page); never a field's value. */
|
|
58
|
+
readonly html?: string;
|
|
59
|
+
/** The attribute the fix adds (the convention's first). */
|
|
60
|
+
readonly attribute: string;
|
|
61
|
+
/** The suggested test id (kebab-case, from the name and route). */
|
|
62
|
+
readonly testId: string;
|
|
63
|
+
/** The fix, e.g. `add data-testid="save-contact" to the "Save" button on /contacts/new`. */
|
|
64
|
+
readonly fix: string;
|
|
65
|
+
readonly reasons: readonly string[];
|
|
66
|
+
readonly occurrences: readonly LocatorOccurrence[];
|
|
67
|
+
}
|
|
68
|
+
export interface LocatorLevels {
|
|
69
|
+
readonly high: number;
|
|
70
|
+
readonly medium: number;
|
|
71
|
+
readonly low: number;
|
|
72
|
+
}
|
|
73
|
+
/** A Journey's (or a run's) locator health in detail — a `LocatorHealth` with the levels, line and fixes. */
|
|
74
|
+
export interface LocatorHealthDetail extends LocatorHealth {
|
|
75
|
+
readonly steps: readonly LocatorHealthStepDetail[];
|
|
76
|
+
readonly levels: LocatorLevels;
|
|
77
|
+
/** e.g. `7/9 steps on stable locators; 2 brittle (high 7 · medium 1 · low 1)`. */
|
|
78
|
+
readonly line: string;
|
|
79
|
+
readonly suggestions: readonly LocatorSuggestion[];
|
|
80
|
+
}
|
|
81
|
+
export interface AnalyzeOptions {
|
|
82
|
+
/** The team's test-id convention (project config `testIdAttributes`). */
|
|
83
|
+
readonly testIdAttributes: readonly string[];
|
|
84
|
+
/** Tags each suggestion's occurrences (a multi-Journey report). */
|
|
85
|
+
readonly journeyId?: string;
|
|
86
|
+
/** A run's resolutions: the rung that actually matched, per step (overrides the recorded rung). */
|
|
87
|
+
readonly resolved?: readonly ResolvedStepInput[];
|
|
88
|
+
/** Short outerHTML excerpts by flat step index, when the caller had a live page. */
|
|
89
|
+
readonly html?: ReadonlyMap<number, string>;
|
|
90
|
+
}
|
|
91
|
+
/** The target a step acts on, or null (navigate, press, assert, a forEach's items are its own). */
|
|
92
|
+
export declare function stepTarget(step: Step): TargetDescriptor | null;
|
|
93
|
+
interface Verdict {
|
|
94
|
+
readonly rung: LocatorRung;
|
|
95
|
+
readonly level: LocatorLevel;
|
|
96
|
+
readonly codes: BrittleReasonCode[];
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* One target's verdict against the convention. `via` (a run's resolution) replaces the recorded rung
|
|
100
|
+
* when present; everything else is read from the descriptor.
|
|
101
|
+
*/
|
|
102
|
+
export declare function classifyTarget(d: TargetDescriptor, testIdAttributes: readonly string[], via?: ResolvedStepInput): Verdict;
|
|
103
|
+
/** `"Save contact"` → `save-contact` (ASCII letters and digits, at most 40 chars). */
|
|
104
|
+
export declare function kebabCase(s: string): string;
|
|
105
|
+
/** The path of a page URL (`https://x/contacts/new?a=1` → `/contacts/new`); a path is kept as is. */
|
|
106
|
+
export declare function routeOf(url: string | undefined): string | undefined;
|
|
107
|
+
/**
|
|
108
|
+
* The suggested test id: the element's name in kebab-case, with the route's noun when the name is a
|
|
109
|
+
* single word (`Save` on /contacts/new → `save-contact`); an unnamed element is named by its route
|
|
110
|
+
* and tag (`contacts-div`).
|
|
111
|
+
*/
|
|
112
|
+
export declare function suggestTestId(name: string | undefined, route: string | undefined, fallbackTag: string): string;
|
|
113
|
+
/** The element's identity across steps and runs: route + role + name (else its css). */
|
|
114
|
+
export declare function suggestionKey(d: TargetDescriptor, route: string | undefined): string;
|
|
115
|
+
/** Merges suggestions for the same element (route + role + name): occurrences and reasons combined. */
|
|
116
|
+
export declare function dedupeSuggestions(lists: ReadonlyArray<readonly LocatorSuggestion[]>): LocatorSuggestion[];
|
|
117
|
+
export declare function emptyLevels(): LocatorLevels;
|
|
118
|
+
/** `7/9 steps on stable locators; 2 brittle (high 7 · medium 1 · low 1)`. */
|
|
119
|
+
export declare function healthLine(h: {
|
|
120
|
+
readonly stable: number;
|
|
121
|
+
readonly brittle: number;
|
|
122
|
+
readonly levels: LocatorLevels;
|
|
123
|
+
}): string;
|
|
124
|
+
/**
|
|
125
|
+
* A recording's locator health: every step with a target (flat index, as the interpreter numbers
|
|
126
|
+
* them), against the convention; with `resolved`, the rung each step actually matched at replay.
|
|
127
|
+
*/
|
|
128
|
+
export declare function analyzeRecording(rec: Recording, opts: AnalyzeOptions): LocatorHealthDetail;
|
|
129
|
+
/** Totals over several healths (a report, a check): counts, levels and the de-duplicated work list. */
|
|
130
|
+
export declare function combineHealth(healths: readonly LocatorHealthDetail[]): {
|
|
131
|
+
stable: number;
|
|
132
|
+
brittle: number;
|
|
133
|
+
levels: LocatorLevels;
|
|
134
|
+
line: string;
|
|
135
|
+
suggestions: LocatorSuggestion[];
|
|
136
|
+
};
|
|
137
|
+
/** `check --max-brittle-steps <n>`: true when a Journey item's brittle steps exceed the opt-in threshold. */
|
|
138
|
+
export declare function exceedsBrittleSteps(health: Pick<LocatorHealth, "brittle">, maxBrittleSteps: number | undefined): boolean;
|
|
139
|
+
export interface LocatorTrendStep {
|
|
140
|
+
/** `stepId`, else `#<index>`. */
|
|
141
|
+
readonly key: string;
|
|
142
|
+
readonly from: {
|
|
143
|
+
readonly rung: LocatorRung;
|
|
144
|
+
readonly level: LocatorLevel;
|
|
145
|
+
readonly stability: "stable" | "brittle";
|
|
146
|
+
};
|
|
147
|
+
readonly to: {
|
|
148
|
+
readonly rung: LocatorRung;
|
|
149
|
+
readonly level: LocatorLevel;
|
|
150
|
+
readonly stability: "stable" | "brittle";
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/** Against a baseline: steps whose locator improved / regressed (stability first, then level). */
|
|
154
|
+
export interface LocatorHealthTrend {
|
|
155
|
+
readonly improved: number;
|
|
156
|
+
readonly regressed: number;
|
|
157
|
+
readonly unchanged: number;
|
|
158
|
+
/** Steps only in the current (added) or only in the baseline (removed). */
|
|
159
|
+
readonly added: number;
|
|
160
|
+
readonly removed: number;
|
|
161
|
+
readonly brittleDelta: number;
|
|
162
|
+
readonly changes: readonly (LocatorTrendStep & {
|
|
163
|
+
readonly direction: "improved" | "regressed";
|
|
164
|
+
})[];
|
|
165
|
+
}
|
|
166
|
+
type TrendInputStep = Pick<LocatorHealthStep, "stepId" | "index" | "rung" | "stability"> & {
|
|
167
|
+
readonly level?: LocatorLevel;
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* The trend of `current` against `baseline` (a previous report or run of the same Journey), keyed by
|
|
171
|
+
* step id (else index): a Journey re-recorded or healed after the app added test ids shows its
|
|
172
|
+
* improvement; a step that fell back to a brittle rung shows as a regression.
|
|
173
|
+
*/
|
|
174
|
+
export declare function compareLocatorHealth(current: {
|
|
175
|
+
readonly brittle: number;
|
|
176
|
+
readonly steps: readonly TrendInputStep[];
|
|
177
|
+
}, baseline: {
|
|
178
|
+
readonly brittle: number;
|
|
179
|
+
readonly steps: readonly TrendInputStep[];
|
|
180
|
+
}): LocatorHealthTrend;
|
|
181
|
+
/** `trend vs baseline: 2 improved, 1 regressed (brittle -1)`. */
|
|
182
|
+
export declare function trendLine(t: LocatorHealthTrend): string;
|
|
183
|
+
/** What a run's result.json / a check item carries: counts, the line, levels, per-step verdicts, top fixes. */
|
|
184
|
+
export interface CompactLocatorHealth extends LocatorHealth {
|
|
185
|
+
readonly levels: LocatorLevels;
|
|
186
|
+
readonly line: string;
|
|
187
|
+
readonly steps: readonly LocatorHealthStep[];
|
|
188
|
+
readonly suggestions: ReadonlyArray<Pick<LocatorSuggestion, "key" | "element" | "fix" | "reasons"> & {
|
|
189
|
+
readonly route?: string;
|
|
190
|
+
readonly steps: number;
|
|
191
|
+
}>;
|
|
192
|
+
}
|
|
193
|
+
/** The compact form of a detail: per-step rung/stability/reasons, and the top `top` fixes. */
|
|
194
|
+
export declare function compactHealth(h: Pick<LocatorHealthDetail, "stable" | "brittle" | "steps" | "levels" | "line" | "suggestions">, top?: number): CompactLocatorHealth;
|
|
195
|
+
export {};
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
import { looksGenerated } from "@jevitate/recorder";
|
|
2
|
+
// === Classification ===
|
|
3
|
+
const LEVEL_RANK = { low: 0, medium: 1, high: 2 };
|
|
4
|
+
/** One notch down: a rung that only resolves with an ordinal (the recorder's `CAPPED_STABILITY`). */
|
|
5
|
+
const CAPPED = { high: "medium", medium: "low", low: "low" };
|
|
6
|
+
const REASON_TEXT = {
|
|
7
|
+
"no-test-id": "no test id",
|
|
8
|
+
"test-id-not-in-convention": "test id attribute is not in the convention",
|
|
9
|
+
"tflow-id-not-a-test-id": "data-tflow-id is tracking metadata, not a test id",
|
|
10
|
+
"generated-value": "generated-looking id or name",
|
|
11
|
+
"no-accessible-name": "no accessible name",
|
|
12
|
+
"duplicate-name": "duplicate name needs disambiguation (nth)",
|
|
13
|
+
"positional-css": "deep or positional css path",
|
|
14
|
+
"text-copy": "text locator on copy likely to change",
|
|
15
|
+
};
|
|
16
|
+
/** The target a step acts on, or null (navigate, press, assert, a forEach's items are its own). */
|
|
17
|
+
export function stepTarget(step) {
|
|
18
|
+
switch (step.kind) {
|
|
19
|
+
case "click":
|
|
20
|
+
case "fill":
|
|
21
|
+
case "waitFor":
|
|
22
|
+
case "extract":
|
|
23
|
+
case "select":
|
|
24
|
+
case "upload":
|
|
25
|
+
case "editText":
|
|
26
|
+
return step.target;
|
|
27
|
+
default:
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** The recorded rung replay tries (an anchor first, as `resolveTarget` does). */
|
|
32
|
+
function recordedRung(d) {
|
|
33
|
+
if (d.anchor !== undefined && d.testId === undefined && (d.anchor.id !== undefined || d.anchor.name !== undefined))
|
|
34
|
+
return "anchor";
|
|
35
|
+
return ownRung(d);
|
|
36
|
+
}
|
|
37
|
+
function ownRung(d) {
|
|
38
|
+
if (d.testId)
|
|
39
|
+
return "testId";
|
|
40
|
+
if (d.role && d.name)
|
|
41
|
+
return "role+name";
|
|
42
|
+
if (d.label)
|
|
43
|
+
return "label";
|
|
44
|
+
if (d.text)
|
|
45
|
+
return "text";
|
|
46
|
+
if (d.css)
|
|
47
|
+
return "css";
|
|
48
|
+
return d.role ? "role" : "css";
|
|
49
|
+
}
|
|
50
|
+
function asRung(r) {
|
|
51
|
+
return ["testId", "anchor", "role+name", "role", "label", "text", "css"].find((x) => x === r) ?? "css";
|
|
52
|
+
}
|
|
53
|
+
/** How deep a css path is, and whether it is positional. */
|
|
54
|
+
function cssShape(css) {
|
|
55
|
+
return { depth: css.split(">").length, positional: /:nth-(of-type|child)\(|:first-|:last-/.test(css) };
|
|
56
|
+
}
|
|
57
|
+
function describeLocator(d, rung) {
|
|
58
|
+
const nth = d.ordinal === undefined ? "" : ` nth=${d.ordinal}`;
|
|
59
|
+
switch (rung) {
|
|
60
|
+
case "testId":
|
|
61
|
+
return `testId[${d.testIdAttr ?? "data-testid"}]=${d.testId ?? "?"}`;
|
|
62
|
+
case "anchor":
|
|
63
|
+
return d.anchor?.id !== undefined ? `[id=${JSON.stringify(d.anchor.id)}]` : `[name=${JSON.stringify(d.anchor?.name ?? "")}]`;
|
|
64
|
+
case "role+name":
|
|
65
|
+
return `role=${d.role ?? "?"} name=${JSON.stringify(d.name ?? "")}${nth}`;
|
|
66
|
+
case "label":
|
|
67
|
+
return `label=${JSON.stringify(d.label ?? "")}${nth}`;
|
|
68
|
+
case "text":
|
|
69
|
+
return `text=${JSON.stringify(d.text ?? "")}${nth}`;
|
|
70
|
+
default:
|
|
71
|
+
return `css=${d.css ?? "?"}`;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* One target's verdict against the convention. `via` (a run's resolution) replaces the recorded rung
|
|
76
|
+
* when present; everything else is read from the descriptor.
|
|
77
|
+
*/
|
|
78
|
+
export function classifyTarget(d, testIdAttributes, via) {
|
|
79
|
+
const rung = via === undefined ? recordedRung(d) : asRung(via.rung);
|
|
80
|
+
const ordinal = via === undefined ? d.ordinal : via.ordinal;
|
|
81
|
+
const codes = [];
|
|
82
|
+
let level;
|
|
83
|
+
switch (rung) {
|
|
84
|
+
case "testId": {
|
|
85
|
+
const attr = (via?.testIdAttr ?? d.testIdAttr ?? "data-testid").toLowerCase();
|
|
86
|
+
const generated = looksGenerated(d.testId ?? "");
|
|
87
|
+
level = generated ? "low" : "high";
|
|
88
|
+
if (attr === "data-tflow-id")
|
|
89
|
+
codes.push("tflow-id-not-a-test-id");
|
|
90
|
+
else if (!testIdAttributes.includes(attr))
|
|
91
|
+
codes.push("test-id-not-in-convention");
|
|
92
|
+
if (generated)
|
|
93
|
+
codes.push("generated-value");
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
case "anchor":
|
|
97
|
+
// A non-generated id/name attribute (the recorder refuses generated ones): sturdy, but not the convention.
|
|
98
|
+
level = "medium";
|
|
99
|
+
codes.push("no-test-id");
|
|
100
|
+
break;
|
|
101
|
+
case "role+name":
|
|
102
|
+
level = looksGenerated(d.name ?? "") ? "low" : "high";
|
|
103
|
+
codes.push("no-test-id");
|
|
104
|
+
if (level === "low")
|
|
105
|
+
codes.push("generated-value");
|
|
106
|
+
break;
|
|
107
|
+
case "label":
|
|
108
|
+
level = "medium";
|
|
109
|
+
codes.push("no-test-id");
|
|
110
|
+
break;
|
|
111
|
+
case "text":
|
|
112
|
+
level = "medium";
|
|
113
|
+
codes.push("no-test-id", "text-copy");
|
|
114
|
+
break;
|
|
115
|
+
default: {
|
|
116
|
+
level = "low";
|
|
117
|
+
codes.push("no-test-id");
|
|
118
|
+
const shape = cssShape(d.css ?? "");
|
|
119
|
+
if (shape.positional || shape.depth > 3)
|
|
120
|
+
codes.push("positional-css");
|
|
121
|
+
if (/#[A-Za-z0-9_-]*\d{4}|[0-9a-fA-F]{8}/.test(d.css ?? ""))
|
|
122
|
+
codes.push("generated-value");
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (ordinal !== undefined && rung !== "testId" && rung !== "anchor" && rung !== "css") {
|
|
126
|
+
level = CAPPED[level];
|
|
127
|
+
codes.push("duplicate-name");
|
|
128
|
+
}
|
|
129
|
+
if (rung !== "testId" && !(d.name || d.label))
|
|
130
|
+
codes.push("no-accessible-name");
|
|
131
|
+
if (d.tflowId !== undefined && rung !== "testId" && !codes.includes("tflow-id-not-a-test-id"))
|
|
132
|
+
codes.push("tflow-id-not-a-test-id");
|
|
133
|
+
return { rung, level, codes };
|
|
134
|
+
}
|
|
135
|
+
// === Suggestions ===
|
|
136
|
+
/** `"Save contact"` → `save-contact` (ASCII letters and digits, at most 40 chars). */
|
|
137
|
+
export function kebabCase(s) {
|
|
138
|
+
return s
|
|
139
|
+
.normalize("NFKD")
|
|
140
|
+
.replace(/[̀-ͯ]/g, "")
|
|
141
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
|
|
142
|
+
.toLowerCase()
|
|
143
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
144
|
+
.replace(/^-+|-+$/g, "")
|
|
145
|
+
.slice(0, 40)
|
|
146
|
+
.replace(/-+$/g, "");
|
|
147
|
+
}
|
|
148
|
+
/** The path of a page URL (`https://x/contacts/new?a=1` → `/contacts/new`); a path is kept as is. */
|
|
149
|
+
export function routeOf(url) {
|
|
150
|
+
if (url === undefined || url === "")
|
|
151
|
+
return undefined;
|
|
152
|
+
try {
|
|
153
|
+
return new URL(url).pathname;
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
const path = url.split(/[?#]/)[0] ?? url;
|
|
157
|
+
return path.startsWith("/") ? path : `/${path}`;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function singular(word) {
|
|
161
|
+
if (/ies$/.test(word))
|
|
162
|
+
return word.replace(/ies$/, "y");
|
|
163
|
+
if (/(ss|us)$/.test(word))
|
|
164
|
+
return word;
|
|
165
|
+
return word.replace(/s$/, "");
|
|
166
|
+
}
|
|
167
|
+
/** The route's first meaningful segment (not an id or a verb like `new`/`edit`), singular. */
|
|
168
|
+
function routeWords(route) {
|
|
169
|
+
return (route ?? "").split("/").filter((s) => s !== "" && !/^\d+$/.test(s) && !looksGenerated(s) && !/^(new|edit|create|index|view)$/i.test(s));
|
|
170
|
+
}
|
|
171
|
+
function routeNoun(route) {
|
|
172
|
+
const first = routeWords(route)[0];
|
|
173
|
+
return first === undefined ? undefined : singular(kebabCase(first));
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* The suggested test id: the element's name in kebab-case, with the route's noun when the name is a
|
|
177
|
+
* single word (`Save` on /contacts/new → `save-contact`); an unnamed element is named by its route
|
|
178
|
+
* and tag (`contacts-div`).
|
|
179
|
+
*/
|
|
180
|
+
export function suggestTestId(name, route, fallbackTag) {
|
|
181
|
+
const base = name === undefined ? "" : kebabCase(name);
|
|
182
|
+
const noun = routeNoun(route);
|
|
183
|
+
if (base !== "")
|
|
184
|
+
return !base.includes("-") && noun !== undefined && !base.includes(noun) ? `${base}-${noun}` : base;
|
|
185
|
+
const where = kebabCase(routeWords(route).join("-"));
|
|
186
|
+
return `${where === "" ? "page" : where}-${fallbackTag}`;
|
|
187
|
+
}
|
|
188
|
+
function lastCssTag(css) {
|
|
189
|
+
const last = (css ?? "").split(">").pop()?.trim() ?? "";
|
|
190
|
+
return /^([a-z][a-z0-9-]*)/i.exec(last)?.[1]?.toLowerCase() ?? "element";
|
|
191
|
+
}
|
|
192
|
+
function describeElement(d) {
|
|
193
|
+
const name = d.name ?? d.label;
|
|
194
|
+
if (d.role && name)
|
|
195
|
+
return `the ${JSON.stringify(name)} ${d.role}`;
|
|
196
|
+
if (d.label)
|
|
197
|
+
return `the ${JSON.stringify(d.label)} field`;
|
|
198
|
+
if (d.role)
|
|
199
|
+
return `the ${d.role}`;
|
|
200
|
+
if (d.text)
|
|
201
|
+
return `the element with text ${JSON.stringify(d.text.length > 40 ? `${d.text.slice(0, 40)}…` : d.text)}`;
|
|
202
|
+
if (d.testId)
|
|
203
|
+
return `the element with ${d.testIdAttr ?? "data-testid"}=${JSON.stringify(d.testId)}`;
|
|
204
|
+
return `the element at css ${JSON.stringify(d.css ?? "?")}`;
|
|
205
|
+
}
|
|
206
|
+
/** The element's identity across steps and runs: route + role + name (else its css). */
|
|
207
|
+
export function suggestionKey(d, route) {
|
|
208
|
+
const name = d.name ?? d.label ?? d.text;
|
|
209
|
+
if (name !== undefined)
|
|
210
|
+
return `${route ?? ""}|${d.role ?? ""}|${name}`;
|
|
211
|
+
if (d.testId !== undefined)
|
|
212
|
+
return `${route ?? ""}|testid|${d.testId}`;
|
|
213
|
+
return `${route ?? ""}|css|${d.css ?? ""}`;
|
|
214
|
+
}
|
|
215
|
+
function fixFor(d, codes, attribute, testId, element, route) {
|
|
216
|
+
const on = route === undefined ? "" : ` on ${route}`;
|
|
217
|
+
const named = codes.includes("no-accessible-name") ? " and give it an accessible name (visible text or aria-label)" : "";
|
|
218
|
+
if (codes.includes("test-id-not-in-convention") && d.testId !== undefined && !looksGenerated(d.testId)) {
|
|
219
|
+
return `use ${attribute}=${JSON.stringify(d.testId)} instead of ${d.testIdAttr ?? "?"} on ${element}${on} (or add ${d.testIdAttr ?? "?"} to testIdAttributes in .jevitate/project.json)`;
|
|
220
|
+
}
|
|
221
|
+
if (d.testId !== undefined && looksGenerated(d.testId)) {
|
|
222
|
+
return `replace the generated ${d.testIdAttr ?? attribute}=${JSON.stringify(d.testId)} on ${element}${on} with a stable ${attribute}=${JSON.stringify(testId)}`;
|
|
223
|
+
}
|
|
224
|
+
return `add ${attribute}=${JSON.stringify(testId)} to ${element}${on}${named}`;
|
|
225
|
+
}
|
|
226
|
+
function buildSuggestion(d, codes, route, attribute, html, occurrence) {
|
|
227
|
+
const name = d.name ?? d.label ?? d.text;
|
|
228
|
+
const testId = suggestTestId(d.testId !== undefined && !looksGenerated(d.testId) ? d.testId : name, route, lastCssTag(d.css));
|
|
229
|
+
const element = describeElement(d);
|
|
230
|
+
return {
|
|
231
|
+
key: suggestionKey(d, route),
|
|
232
|
+
...(route === undefined ? {} : { route }),
|
|
233
|
+
...(d.role === undefined ? {} : { role: d.role }),
|
|
234
|
+
...(name === undefined ? {} : { name }),
|
|
235
|
+
element,
|
|
236
|
+
...(html === undefined ? {} : { html: html.length > 160 ? `${html.slice(0, 160)}…` : html }),
|
|
237
|
+
attribute,
|
|
238
|
+
testId,
|
|
239
|
+
fix: fixFor(d, codes, attribute, testId, element, route),
|
|
240
|
+
reasons: codes.map((c) => REASON_TEXT[c]),
|
|
241
|
+
occurrences: [occurrence],
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
/** Merges suggestions for the same element (route + role + name): occurrences and reasons combined. */
|
|
245
|
+
export function dedupeSuggestions(lists) {
|
|
246
|
+
const byKey = new Map();
|
|
247
|
+
for (const s of lists.flat()) {
|
|
248
|
+
const prev = byKey.get(s.key);
|
|
249
|
+
if (prev === undefined) {
|
|
250
|
+
byKey.set(s.key, s);
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
const occ = [...prev.occurrences];
|
|
254
|
+
for (const o of s.occurrences) {
|
|
255
|
+
if (!occ.some((p) => p.journeyId === o.journeyId && p.index === o.index && p.stepId === o.stepId))
|
|
256
|
+
occ.push(o);
|
|
257
|
+
}
|
|
258
|
+
byKey.set(s.key, {
|
|
259
|
+
...prev,
|
|
260
|
+
...(prev.html === undefined && s.html !== undefined ? { html: s.html } : {}),
|
|
261
|
+
reasons: [...new Set([...prev.reasons, ...s.reasons])],
|
|
262
|
+
occurrences: occ,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
// The elements most steps depend on first: the highest-value fixes lead the work list.
|
|
266
|
+
return [...byKey.values()].sort((a, b) => b.occurrences.length - a.occurrences.length || a.key.localeCompare(b.key));
|
|
267
|
+
}
|
|
268
|
+
// === Analysis ===
|
|
269
|
+
function flatWithRoute(rec) {
|
|
270
|
+
return rec.pages.flatMap((p) => p.steps.map((recorded) => ({ recorded, route: routeOf(p.url) })));
|
|
271
|
+
}
|
|
272
|
+
export function emptyLevels() {
|
|
273
|
+
return { high: 0, medium: 0, low: 0 };
|
|
274
|
+
}
|
|
275
|
+
/** `7/9 steps on stable locators; 2 brittle (high 7 · medium 1 · low 1)`. */
|
|
276
|
+
export function healthLine(h) {
|
|
277
|
+
const total = h.stable + h.brittle;
|
|
278
|
+
if (total === 0)
|
|
279
|
+
return "no steps act on a target";
|
|
280
|
+
return `${h.stable}/${total} steps on stable locators; ${h.brittle} brittle (high ${h.levels.high} · medium ${h.levels.medium} · low ${h.levels.low})`;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* A recording's locator health: every step with a target (flat index, as the interpreter numbers
|
|
284
|
+
* them), against the convention; with `resolved`, the rung each step actually matched at replay.
|
|
285
|
+
*/
|
|
286
|
+
export function analyzeRecording(rec, opts) {
|
|
287
|
+
const attribute = opts.testIdAttributes[0] ?? "data-testid";
|
|
288
|
+
const resolvedBy = new Map((opts.resolved ?? []).map((r) => [r.index, r]));
|
|
289
|
+
const steps = [];
|
|
290
|
+
const suggestions = [];
|
|
291
|
+
const levels = { high: 0, medium: 0, low: 0 };
|
|
292
|
+
flatWithRoute(rec).forEach(({ recorded, route }, index) => {
|
|
293
|
+
const d = stepTarget(recorded.step);
|
|
294
|
+
if (d === null)
|
|
295
|
+
return;
|
|
296
|
+
const via = resolvedBy.get(index);
|
|
297
|
+
const v = classifyTarget(d, opts.testIdAttributes, via);
|
|
298
|
+
const brittle = v.codes.length > 0;
|
|
299
|
+
levels[v.level] += 1;
|
|
300
|
+
const stepId = recorded.stepId ?? via?.stepId;
|
|
301
|
+
let key;
|
|
302
|
+
if (brittle) {
|
|
303
|
+
const occurrence = { ...(opts.journeyId === undefined ? {} : { journeyId: opts.journeyId }), index, ...(stepId === undefined ? {} : { stepId }) };
|
|
304
|
+
const s = buildSuggestion(d, v.codes, route, attribute, opts.html?.get(index), occurrence);
|
|
305
|
+
suggestions.push(s);
|
|
306
|
+
key = s.key;
|
|
307
|
+
}
|
|
308
|
+
steps.push({
|
|
309
|
+
...(stepId === undefined ? {} : { stepId }),
|
|
310
|
+
index,
|
|
311
|
+
kind: recorded.step.kind,
|
|
312
|
+
rung: v.rung,
|
|
313
|
+
level: v.level,
|
|
314
|
+
stability: brittle ? "brittle" : "stable",
|
|
315
|
+
source: via === undefined ? "recorded" : "resolved",
|
|
316
|
+
...(route === undefined ? {} : { route }),
|
|
317
|
+
locator: describeLocator(d, v.rung),
|
|
318
|
+
reasons: v.codes.map((c) => REASON_TEXT[c]),
|
|
319
|
+
reasonCodes: v.codes,
|
|
320
|
+
...(key === undefined ? {} : { suggestion: key }),
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
const stable = steps.filter((s) => s.stability === "stable").length;
|
|
324
|
+
const brittle = steps.length - stable;
|
|
325
|
+
return { stable, brittle, steps, levels, line: healthLine({ stable, brittle, levels }), suggestions: dedupeSuggestions([suggestions]) };
|
|
326
|
+
}
|
|
327
|
+
/** Totals over several healths (a report, a check): counts, levels and the de-duplicated work list. */
|
|
328
|
+
export function combineHealth(healths) {
|
|
329
|
+
const levels = { high: 0, medium: 0, low: 0 };
|
|
330
|
+
let stable = 0;
|
|
331
|
+
let brittle = 0;
|
|
332
|
+
for (const h of healths) {
|
|
333
|
+
stable += h.stable;
|
|
334
|
+
brittle += h.brittle;
|
|
335
|
+
levels.high += h.levels.high;
|
|
336
|
+
levels.medium += h.levels.medium;
|
|
337
|
+
levels.low += h.levels.low;
|
|
338
|
+
}
|
|
339
|
+
return { stable, brittle, levels, line: healthLine({ stable, brittle, levels }), suggestions: dedupeSuggestions(healths.map((h) => h.suggestions)) };
|
|
340
|
+
}
|
|
341
|
+
// === Gate ===
|
|
342
|
+
/** `check --max-brittle-steps <n>`: true when a Journey item's brittle steps exceed the opt-in threshold. */
|
|
343
|
+
export function exceedsBrittleSteps(health, maxBrittleSteps) {
|
|
344
|
+
return maxBrittleSteps !== undefined && health.brittle > maxBrittleSteps;
|
|
345
|
+
}
|
|
346
|
+
function stepKey(s) {
|
|
347
|
+
return s.stepId ?? `#${s.index}`;
|
|
348
|
+
}
|
|
349
|
+
function score(s) {
|
|
350
|
+
return (s.stability === "stable" ? 10 : 0) + LEVEL_RANK[s.level ?? (s.stability === "stable" ? "high" : "low")];
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* The trend of `current` against `baseline` (a previous report or run of the same Journey), keyed by
|
|
354
|
+
* step id (else index): a Journey re-recorded or healed after the app added test ids shows its
|
|
355
|
+
* improvement; a step that fell back to a brittle rung shows as a regression.
|
|
356
|
+
*/
|
|
357
|
+
export function compareLocatorHealth(current, baseline) {
|
|
358
|
+
const before = new Map(baseline.steps.map((s) => [stepKey(s), s]));
|
|
359
|
+
const seen = new Set();
|
|
360
|
+
const changes = [];
|
|
361
|
+
let unchanged = 0;
|
|
362
|
+
let added = 0;
|
|
363
|
+
const shape = (s) => ({ rung: s.rung, level: s.level ?? (s.stability === "stable" ? "high" : "low"), stability: s.stability });
|
|
364
|
+
for (const s of current.steps) {
|
|
365
|
+
const key = stepKey(s);
|
|
366
|
+
seen.add(key);
|
|
367
|
+
const b = before.get(key);
|
|
368
|
+
if (b === undefined) {
|
|
369
|
+
added++;
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
const delta = score(s) - score(b);
|
|
373
|
+
if (delta === 0)
|
|
374
|
+
unchanged++;
|
|
375
|
+
else
|
|
376
|
+
changes.push({ key, from: shape(b), to: shape(s), direction: delta > 0 ? "improved" : "regressed" });
|
|
377
|
+
}
|
|
378
|
+
const removed = [...before.keys()].filter((k) => !seen.has(k)).length;
|
|
379
|
+
return {
|
|
380
|
+
improved: changes.filter((c) => c.direction === "improved").length,
|
|
381
|
+
regressed: changes.filter((c) => c.direction === "regressed").length,
|
|
382
|
+
unchanged,
|
|
383
|
+
added,
|
|
384
|
+
removed,
|
|
385
|
+
brittleDelta: current.brittle - baseline.brittle,
|
|
386
|
+
changes,
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
/** `trend vs baseline: 2 improved, 1 regressed (brittle -1)`. */
|
|
390
|
+
export function trendLine(t) {
|
|
391
|
+
const sign = t.brittleDelta > 0 ? `+${t.brittleDelta}` : String(t.brittleDelta);
|
|
392
|
+
return `trend vs baseline: ${t.improved} improved, ${t.regressed} regressed (brittle ${sign})`;
|
|
393
|
+
}
|
|
394
|
+
/** The compact form of a detail: per-step rung/stability/reasons, and the top `top` fixes. */
|
|
395
|
+
export function compactHealth(h, top = 5) {
|
|
396
|
+
return {
|
|
397
|
+
stable: h.stable,
|
|
398
|
+
brittle: h.brittle,
|
|
399
|
+
levels: h.levels,
|
|
400
|
+
line: h.line,
|
|
401
|
+
steps: h.steps.map((s) => ({
|
|
402
|
+
...(s.stepId === undefined ? {} : { stepId: s.stepId }),
|
|
403
|
+
index: s.index,
|
|
404
|
+
rung: s.rung,
|
|
405
|
+
stability: s.stability,
|
|
406
|
+
reasons: s.reasons,
|
|
407
|
+
...("level" in s ? { level: s.level } : {}),
|
|
408
|
+
})),
|
|
409
|
+
suggestions: h.suggestions.slice(0, top).map((s) => ({
|
|
410
|
+
key: s.key,
|
|
411
|
+
element: s.element,
|
|
412
|
+
fix: s.fix,
|
|
413
|
+
reasons: s.reasons,
|
|
414
|
+
...(s.route === undefined ? {} : { route: s.route }),
|
|
415
|
+
steps: s.occurrences.length,
|
|
416
|
+
})),
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
//# sourceMappingURL=locator-health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locator-health.js","sourceRoot":"","sources":["../src/locator-health.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp-cli-tools.d.ts
CHANGED
|
@@ -60,7 +60,9 @@ export type CliParamKind =
|
|
|
60
60
|
/** `name=<storageState>` entries (`--persona`/`--actor`): each path confined as a session. */
|
|
61
61
|
| "named-sessions"
|
|
62
62
|
/** `<descriptor>=<file>` entries (`--type-fixture`): the file (after the LAST `=`) confined as a read path. */
|
|
63
|
-
| "bound-paths"
|
|
63
|
+
| "bound-paths"
|
|
64
|
+
/** #464: a path the command WRITES project output to — confined to the project roots only (never `~/.jevitate/`). */
|
|
65
|
+
| "project-path";
|
|
64
66
|
export interface CliParam {
|
|
65
67
|
readonly kind: CliParamKind;
|
|
66
68
|
/** The long flag (`--env`); absent for a positional. */
|