@sudobility/testomniac_runner_service 0.1.57 → 0.1.59
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/analyzer/page-analyzer/generators/content.d.ts.map +1 -1
- package/dist/analyzer/page-analyzer/generators/content.js +14 -2
- package/dist/analyzer/page-analyzer/generators/content.js.map +1 -1
- package/dist/analyzer/page-analyzer/generators/dialogs.d.ts.map +1 -1
- package/dist/analyzer/page-analyzer/generators/dialogs.js +14 -2
- package/dist/analyzer/page-analyzer/generators/dialogs.js.map +1 -1
- package/dist/analyzer/page-analyzer/generators/e2e.d.ts.map +1 -1
- package/dist/analyzer/page-analyzer/generators/e2e.js +14 -3
- package/dist/analyzer/page-analyzer/generators/e2e.js.map +1 -1
- package/dist/analyzer/page-analyzer/generators/forms.d.ts.map +1 -1
- package/dist/analyzer/page-analyzer/generators/forms.js +19 -2
- package/dist/analyzer/page-analyzer/generators/forms.js.map +1 -1
- package/dist/analyzer/page-analyzer/generators/hover-follow-up.d.ts.map +1 -1
- package/dist/analyzer/page-analyzer/generators/hover-follow-up.js +13 -0
- package/dist/analyzer/page-analyzer/generators/hover-follow-up.js.map +1 -1
- package/dist/analyzer/page-analyzer/generators/keyboard-disclosure.d.ts.map +1 -1
- package/dist/analyzer/page-analyzer/generators/keyboard-disclosure.js +13 -2
- package/dist/analyzer/page-analyzer/generators/keyboard-disclosure.js.map +1 -1
- package/dist/analyzer/page-analyzer/generators/navigation.d.ts.map +1 -1
- package/dist/analyzer/page-analyzer/generators/navigation.js +14 -1
- package/dist/analyzer/page-analyzer/generators/navigation.js.map +1 -1
- package/dist/analyzer/page-analyzer/generators/render.d.ts.map +1 -1
- package/dist/analyzer/page-analyzer/generators/render.js +7 -1
- package/dist/analyzer/page-analyzer/generators/render.js.map +1 -1
- package/dist/analyzer/page-analyzer/generators/scaffolds.d.ts.map +1 -1
- package/dist/analyzer/page-analyzer/generators/scaffolds.js +33 -2
- package/dist/analyzer/page-analyzer/generators/scaffolds.js.map +1 -1
- package/dist/analyzer/page-analyzer/generators/semantic-journeys.d.ts.map +1 -1
- package/dist/analyzer/page-analyzer/generators/semantic-journeys.js +13 -2
- package/dist/analyzer/page-analyzer/generators/semantic-journeys.js.map +1 -1
- package/dist/analyzer/page-analyzer/generators/variants.d.ts.map +1 -1
- package/dist/analyzer/page-analyzer/generators/variants.js +13 -2
- package/dist/analyzer/page-analyzer/generators/variants.js.map +1 -1
- package/dist/analyzer/page-analyzer/index.d.ts +15 -0
- package/dist/analyzer/page-analyzer/index.d.ts.map +1 -1
- package/dist/analyzer/page-analyzer/index.js +98 -0
- package/dist/analyzer/page-analyzer/index.js.map +1 -1
- package/dist/api/client.d.ts +2 -1
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +6 -2
- package/dist/api/client.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"variants.js","sourceRoot":"","sources":["../../../../src/analyzer/page-analyzer/generators/variants.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,QAAa,EACb,OAAwB;IAExB,MAAM,KAAK,GAAG,QAAQ,CAAC,wBAAwB,CAAC,OAAO,CAAC,CAAC;IACzD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"variants.js","sourceRoot":"","sources":["../../../../src/analyzer/page-analyzer/generators/variants.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,QAAa,EACb,OAAwB;IAExB,MAAM,KAAK,GAAG,QAAQ,CAAC,wBAAwB,CAAC,OAAO,CAAC,CAAC;IACzD,MAAM,YAAY,GAAG,aAAa,OAAO,CAAC,WAAW,EAAE,CAAC;IACxD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,QAAQ,CAAC,iCAAiC,CAAC,OAAO,EAAE;YACxD,YAAY;YACZ,WAAW,EAAE,EAAE;SAChB,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAC7C,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,iBAAiB,CAAC,QAAQ,EAAE;QACpD,KAAK,EAAE,YAAY;QACnB,WAAW,EAAE,uCAAuC,OAAO,CAAC,WAAW,EAAE;QACzE,mBAAmB,EAAE,OAAO,CAAC,kBAAkB;QAC/C,YAAY,EAAE,OAAO,CAAC,WAAW;QACjC,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,QAAQ,EAAE,CAAC;QACX,YAAY,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC;QACnC,GAAG,EAAE,OAAO,CAAC,GAAG;KACjB,CAAC,CAAC;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAC;QAClC,SAAS,EAAE,OAAO,CAAC,EAAE;QACrB,KAAK,EAAE,OAAO,CAAC,KAAK;KACrB,CAAC,CAAC;IAEH,MAAM,GAAG,CAAC,uBAAuB,CAAC,SAAS,CAAC,mBAAmB,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7E,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,gBAAgB,CAChD,GAAG,EACH,OAAO,CAAC,EAAE,EACV,SAAS,CAAC,EAAE,CACb,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QACnE,MAAM,GAAG,CAAC,oBAAoB,CAAC;YAC7B,aAAa,EAAE,EAAE,CAAC,EAAE;YACpB,gBAAgB,EAAE,UAAU,CAAC,EAAE;SAChC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,CAAC,iCAAiC,CAAC,OAAO,EAAE;QACxD,SAAS,EAAE,OAAO,CAAC,EAAE;QACrB,YAAY;QACZ,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;KACtE,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { TestElement, Expectation } from "@sudobility/testomniac_types";
|
|
2
2
|
import type { AnalyzerContext } from "./types";
|
|
3
3
|
export type { AnalyzerContext } from "./types";
|
|
4
|
+
type GeneratedTestElement = TestElement & {
|
|
5
|
+
generatedKey?: string;
|
|
6
|
+
};
|
|
4
7
|
/**
|
|
5
8
|
* PageAnalyzer generates expectations and discovers new test elements
|
|
6
9
|
* during discovery mode.
|
|
@@ -16,6 +19,13 @@ export declare class PageAnalyzer {
|
|
|
16
19
|
* Called AFTER expertises evaluate and the target page state is established.
|
|
17
20
|
*/
|
|
18
21
|
generateTestElements(testElement: TestElement, context: AnalyzerContext): Promise<void>;
|
|
22
|
+
reconcileGeneratedSurfaceElements(context: AnalyzerContext, params: {
|
|
23
|
+
surfaceId?: number | null;
|
|
24
|
+
surfaceTitle: string;
|
|
25
|
+
desiredKeys: string[];
|
|
26
|
+
dependencyTestElementId?: number;
|
|
27
|
+
}): Promise<void>;
|
|
28
|
+
private findExistingSurfaceByTitle;
|
|
19
29
|
private getScaffoldSurfaceItems;
|
|
20
30
|
private ensureSurfaceRun;
|
|
21
31
|
private isMouseActionable;
|
|
@@ -27,6 +37,11 @@ export declare class PageAnalyzer {
|
|
|
27
37
|
private isHoverOnly;
|
|
28
38
|
private getPrimarySelector;
|
|
29
39
|
private getItemKey;
|
|
40
|
+
withGeneratedKey(testElement: GeneratedTestElement, ...parts: Array<string | number | null | undefined>): GeneratedTestElement;
|
|
41
|
+
getGeneratedKey(testElement: Pick<GeneratedTestElement, "generatedKey" | "title">): string;
|
|
42
|
+
private getPersistedGeneratedKey;
|
|
43
|
+
private buildGeneratedKey;
|
|
44
|
+
private buildStepSignature;
|
|
30
45
|
private ensureTargetPageState;
|
|
31
46
|
private ensureScaffolds;
|
|
32
47
|
private ensureStoredForms;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analyzer/page-analyzer/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EAQZ,MAAM,8BAA8B,CAAC;AAYtC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAa/C,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAQ/C;;;GAGG;AACH,qBAAa,YAAY;IACvB;;;OAGG;IACH,oBAAoB,CAAC,WAAW,EAAE,WAAW,GAAG,WAAW,EAAE;IAkC7D;;;OAGG;IACG,oBAAoB,CACxB,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analyzer/page-analyzer/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -78,6 +78,39 @@ export class PageAnalyzer {
|
|
|
78
78
|
await generateKeyboardAndDisclosureTestElements(this, resolvedContext);
|
|
79
79
|
await generateVariantTestElements(this, resolvedContext);
|
|
80
80
|
}
|
|
81
|
+
async reconcileGeneratedSurfaceElements(context, params) {
|
|
82
|
+
const surface = params.surfaceId != null
|
|
83
|
+
? { id: params.surfaceId, title: params.surfaceTitle }
|
|
84
|
+
: await this.findExistingSurfaceByTitle(context, params.surfaceTitle);
|
|
85
|
+
if (!surface)
|
|
86
|
+
return;
|
|
87
|
+
const existing = await context.api.getTestElementsByTestSurface(surface.id, true);
|
|
88
|
+
const desiredKeys = new Set(params.desiredKeys.map(key => key.trim()).filter(Boolean));
|
|
89
|
+
const obsoleteIds = existing
|
|
90
|
+
.filter(testElement => {
|
|
91
|
+
const isGenerated = Boolean(testElement.isGenerated);
|
|
92
|
+
const isActive = testElement.isActive !== false;
|
|
93
|
+
if (!isGenerated || !isActive)
|
|
94
|
+
return false;
|
|
95
|
+
if (testElement.startingPageStateId !== context.currentPageStateId)
|
|
96
|
+
return false;
|
|
97
|
+
if ((testElement.dependencyTestElementId ?? null) !==
|
|
98
|
+
(params.dependencyTestElementId ?? null)) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
const existingKey = this.getPersistedGeneratedKey(testElement);
|
|
102
|
+
return !existingKey || !desiredKeys.has(existingKey);
|
|
103
|
+
})
|
|
104
|
+
.map(testElement => testElement.id);
|
|
105
|
+
if (obsoleteIds.length === 0)
|
|
106
|
+
return;
|
|
107
|
+
await context.api.retireTestElements(obsoleteIds);
|
|
108
|
+
}
|
|
109
|
+
async findExistingSurfaceByTitle(context, title) {
|
|
110
|
+
const surfaces = await context.api.getTestSurfacesByRunner(context.runnerId);
|
|
111
|
+
const surface = surfaces.find(candidate => candidate.title === title);
|
|
112
|
+
return surface ? { id: surface.id, title: surface.title } : null;
|
|
113
|
+
}
|
|
81
114
|
getScaffoldSurfaceItems(context, scaffold) {
|
|
82
115
|
return this.normalizeActionableItems(context.actionableItems).filter(item => {
|
|
83
116
|
if (!this.isSurfaceCandidate(item) || !item.selector)
|
|
@@ -140,6 +173,7 @@ export class PageAnalyzer {
|
|
|
140
173
|
],
|
|
141
174
|
globalExpectations: [],
|
|
142
175
|
uid,
|
|
176
|
+
generatedKey: this.buildGeneratedKey("navigation", startingPageStateId, path),
|
|
143
177
|
};
|
|
144
178
|
}
|
|
145
179
|
buildHoverTestElement(item, startingPath, sizeClass, uid, startingPageStateId, dependencyTestElementId) {
|
|
@@ -168,6 +202,7 @@ export class PageAnalyzer {
|
|
|
168
202
|
],
|
|
169
203
|
globalExpectations: [],
|
|
170
204
|
uid,
|
|
205
|
+
generatedKey: this.buildGeneratedKey("hover", startingPageStateId, dependencyTestElementId, item.stableKey ?? item.selector ?? label),
|
|
171
206
|
};
|
|
172
207
|
}
|
|
173
208
|
buildClickTestElement(item, startingPath, sizeClass, uid, startingPageStateId, dependencyTestElementId) {
|
|
@@ -196,6 +231,7 @@ export class PageAnalyzer {
|
|
|
196
231
|
],
|
|
197
232
|
globalExpectations: [],
|
|
198
233
|
uid,
|
|
234
|
+
generatedKey: this.buildGeneratedKey("click", startingPageStateId, dependencyTestElementId, item.stableKey ?? item.selector ?? label),
|
|
199
235
|
};
|
|
200
236
|
}
|
|
201
237
|
isHoverOnly(testElement) {
|
|
@@ -213,6 +249,49 @@ export class PageAnalyzer {
|
|
|
213
249
|
const selector = item.selector;
|
|
214
250
|
return stableKey ?? selector ?? null;
|
|
215
251
|
}
|
|
252
|
+
withGeneratedKey(testElement, ...parts) {
|
|
253
|
+
return {
|
|
254
|
+
...testElement,
|
|
255
|
+
generatedKey: this.buildGeneratedKey(...parts),
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
getGeneratedKey(testElement) {
|
|
259
|
+
return (testElement.generatedKey?.trim() || testElement.title).trim();
|
|
260
|
+
}
|
|
261
|
+
getPersistedGeneratedKey(testElement) {
|
|
262
|
+
const generatedKey = testElement.generatedKey?.trim();
|
|
263
|
+
if (generatedKey)
|
|
264
|
+
return generatedKey;
|
|
265
|
+
const title = testElement.title?.trim();
|
|
266
|
+
return title || null;
|
|
267
|
+
}
|
|
268
|
+
buildGeneratedKey(...parts) {
|
|
269
|
+
const normalized = parts
|
|
270
|
+
.map(part => (part == null ? "" : String(part).trim()))
|
|
271
|
+
.filter(Boolean);
|
|
272
|
+
const raw = normalized.join("||");
|
|
273
|
+
const digest = createHash("sha1").update(raw).digest("hex").slice(0, 16);
|
|
274
|
+
const prefix = normalized
|
|
275
|
+
.slice(0, 3)
|
|
276
|
+
.map(part => part
|
|
277
|
+
.toLowerCase()
|
|
278
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
279
|
+
.replace(/^-+|-+$/g, ""))
|
|
280
|
+
.filter(Boolean)
|
|
281
|
+
.join(":")
|
|
282
|
+
.slice(0, 80);
|
|
283
|
+
return prefix ? `${prefix}:${digest}` : digest;
|
|
284
|
+
}
|
|
285
|
+
buildStepSignature(steps) {
|
|
286
|
+
return steps
|
|
287
|
+
.map(step => [
|
|
288
|
+
step.action?.actionType ?? "",
|
|
289
|
+
step.action?.path ?? "",
|
|
290
|
+
step.action?.value ?? "",
|
|
291
|
+
step.action?.description ?? "",
|
|
292
|
+
].join("|"))
|
|
293
|
+
.join("||");
|
|
294
|
+
}
|
|
216
295
|
async ensureTargetPageState(context) {
|
|
217
296
|
const scaffoldIdsBySelector = await this.ensureScaffolds(context);
|
|
218
297
|
for (const item of context.actionableItems) {
|
|
@@ -370,6 +449,7 @@ export class PageAnalyzer {
|
|
|
370
449
|
],
|
|
371
450
|
globalExpectations: this.defaultFlowExpectations("Render page without runtime errors"),
|
|
372
451
|
uid,
|
|
452
|
+
generatedKey: this.buildGeneratedKey("render", startingPageStateId, pageId, currentPath),
|
|
373
453
|
};
|
|
374
454
|
}
|
|
375
455
|
buildFormTestElement(form, formLabel, formType, currentPath, sizeClass, uid, startingPageStateId, validValues) {
|
|
@@ -414,6 +494,7 @@ export class PageAnalyzer {
|
|
|
414
494
|
this.makeExpectation("field_error_clears_after_fix", `Validation errors on ${formLabel} should clear once the fields are corrected`),
|
|
415
495
|
],
|
|
416
496
|
uid,
|
|
497
|
+
generatedKey: this.buildGeneratedKey("form-positive", startingPageStateId, form.selector, formType),
|
|
417
498
|
};
|
|
418
499
|
}
|
|
419
500
|
buildNegativeFormTestElement(form, formLabel, formType, omittedField, currentPath, sizeClass, uid, startingPageStateId, validValues) {
|
|
@@ -436,6 +517,7 @@ export class PageAnalyzer {
|
|
|
436
517
|
}),
|
|
437
518
|
],
|
|
438
519
|
uid,
|
|
520
|
+
generatedKey: this.buildGeneratedKey("form-negative", startingPageStateId, form.selector, formType, omittedField.selector),
|
|
439
521
|
};
|
|
440
522
|
}
|
|
441
523
|
buildFormCorrectionTestElement(form, formLabel, formType, correctedField, currentPath, sizeClass, uid, startingPageStateId, validValues) {
|
|
@@ -480,6 +562,7 @@ export class PageAnalyzer {
|
|
|
480
562
|
this.makeExpectation("feedback_not_duplicated", `Form ${formLabel} should not show duplicate feedback after correction`),
|
|
481
563
|
],
|
|
482
564
|
uid,
|
|
565
|
+
generatedKey: this.buildGeneratedKey("form-correction", startingPageStateId, form.selector, formType, correctedField.selector),
|
|
483
566
|
};
|
|
484
567
|
}
|
|
485
568
|
buildPasswordTestElements(form, formLabel, formType, currentPath, sizeClass, uid, startingPageStateId, validValues, passwordRequirements) {
|
|
@@ -515,6 +598,7 @@ export class PageAnalyzer {
|
|
|
515
598
|
},
|
|
516
599
|
],
|
|
517
600
|
uid,
|
|
601
|
+
generatedKey: this.buildGeneratedKey("password", startingPageStateId, form.selector, formType, variant.description, variant.password),
|
|
518
602
|
};
|
|
519
603
|
});
|
|
520
604
|
}
|
|
@@ -533,6 +617,7 @@ export class PageAnalyzer {
|
|
|
533
617
|
})),
|
|
534
618
|
globalExpectations: this.defaultFlowExpectations(`Journey to ${currentPath} should complete without runtime errors`),
|
|
535
619
|
uid,
|
|
620
|
+
generatedKey: this.buildGeneratedKey("dependency-journey", startingPageStateId, currentPath, this.buildStepSignature(journeySteps)),
|
|
536
621
|
};
|
|
537
622
|
}
|
|
538
623
|
buildFormSteps(form, valuesBySelector, omittedSelector, postSubmitExpectations = []) {
|
|
@@ -813,6 +898,7 @@ export class PageAnalyzer {
|
|
|
813
898
|
this.makeExpectation(ExpectationType.LoadingCompletes, `Search results for ${formLabel} should finish loading`),
|
|
814
899
|
],
|
|
815
900
|
uid,
|
|
901
|
+
generatedKey: this.buildGeneratedKey("search", startingPageStateId, form.selector, searchField.selector),
|
|
816
902
|
},
|
|
817
903
|
{
|
|
818
904
|
title: `Search Empty State — ${formLabel}`,
|
|
@@ -835,6 +921,7 @@ export class PageAnalyzer {
|
|
|
835
921
|
this.makeExpectation(ExpectationType.LoadingCompletes, `No-result search for ${formLabel} should finish loading`),
|
|
836
922
|
],
|
|
837
923
|
uid,
|
|
924
|
+
generatedKey: this.buildGeneratedKey("search-empty", startingPageStateId, form.selector, searchField.selector),
|
|
838
925
|
},
|
|
839
926
|
{
|
|
840
927
|
title: `Search Recovery — ${formLabel}`,
|
|
@@ -858,6 +945,7 @@ export class PageAnalyzer {
|
|
|
858
945
|
this.makeExpectation(ExpectationType.LoadingCompletes, `Search recovery for ${formLabel} should finish loading`),
|
|
859
946
|
],
|
|
860
947
|
uid,
|
|
948
|
+
generatedKey: this.buildGeneratedKey("search-recovery", startingPageStateId, form.selector, searchField.selector),
|
|
861
949
|
},
|
|
862
950
|
];
|
|
863
951
|
const clearAction = actionableItems.find(item => this.isSearchClearItem(item));
|
|
@@ -884,6 +972,7 @@ export class PageAnalyzer {
|
|
|
884
972
|
this.makeExpectation(ExpectationType.ResultsRestored, `Clearing ${formLabel} should restore the initial results baseline`),
|
|
885
973
|
],
|
|
886
974
|
uid,
|
|
975
|
+
generatedKey: this.buildGeneratedKey("search-clear", startingPageStateId, form.selector, searchField.selector, clearAction.selector),
|
|
887
976
|
});
|
|
888
977
|
}
|
|
889
978
|
return tests;
|
|
@@ -1220,6 +1309,7 @@ export class PageAnalyzer {
|
|
|
1220
1309
|
steps,
|
|
1221
1310
|
globalExpectations: this.defaultFlowExpectations(`${title} should complete without runtime errors`),
|
|
1222
1311
|
uid: context.uid,
|
|
1312
|
+
generatedKey: this.buildGeneratedKey("semantic-journey", context.currentPageStateId, context.currentPath, this.buildStepSignature(steps)),
|
|
1223
1313
|
};
|
|
1224
1314
|
}
|
|
1225
1315
|
buildJourneyAction(item, description, expectations) {
|
|
@@ -1418,6 +1508,7 @@ export class PageAnalyzer {
|
|
|
1418
1508
|
],
|
|
1419
1509
|
globalExpectations: this.defaultFlowExpectations("Variant selection should complete without runtime errors"),
|
|
1420
1510
|
uid: context.uid,
|
|
1511
|
+
generatedKey: this.buildGeneratedKey("variant-selection", context.currentPageStateId, item.selector, plannedValue),
|
|
1421
1512
|
};
|
|
1422
1513
|
}
|
|
1423
1514
|
buildVariantPurchaseJourney(item, purchaseAction, context) {
|
|
@@ -1489,6 +1580,7 @@ export class PageAnalyzer {
|
|
|
1489
1580
|
],
|
|
1490
1581
|
globalExpectations: this.defaultFlowExpectations(`Variant purchase journey for ${label} should execute cleanly`),
|
|
1491
1582
|
uid: context.uid,
|
|
1583
|
+
generatedKey: this.buildGeneratedKey("variant-purchase", context.currentPageStateId, item.selector, plannedValue, purchaseAction.selector),
|
|
1492
1584
|
};
|
|
1493
1585
|
}
|
|
1494
1586
|
buildRequiredVariantGuardTestElement(item, requiredField, purchaseAction, context) {
|
|
@@ -1512,6 +1604,7 @@ export class PageAnalyzer {
|
|
|
1512
1604
|
],
|
|
1513
1605
|
globalExpectations: this.defaultFlowExpectations(`${label} should be enforced before ${purchaseLabel}`),
|
|
1514
1606
|
uid: context.uid,
|
|
1607
|
+
generatedKey: this.buildGeneratedKey("variant-guard", context.currentPageStateId, item.selector, requiredField.selector, purchaseAction.selector),
|
|
1515
1608
|
};
|
|
1516
1609
|
}
|
|
1517
1610
|
findRequiredVariantField(item, forms) {
|
|
@@ -1553,6 +1646,7 @@ export class PageAnalyzer {
|
|
|
1553
1646
|
],
|
|
1554
1647
|
globalExpectations: this.defaultFlowExpectations("Disclosure interaction should complete without runtime errors"),
|
|
1555
1648
|
uid,
|
|
1649
|
+
generatedKey: this.buildGeneratedKey("disclosure-click", startingPageStateId, item.stableKey ?? item.selector ?? label),
|
|
1556
1650
|
};
|
|
1557
1651
|
}
|
|
1558
1652
|
buildKeyboardActivateTestElement(item, key, titlePrefix, expectations, startingPath, sizeClass, uid, startingPageStateId) {
|
|
@@ -1598,6 +1692,7 @@ export class PageAnalyzer {
|
|
|
1598
1692
|
],
|
|
1599
1693
|
globalExpectations: this.defaultFlowExpectations("Keyboard activation should complete without runtime errors"),
|
|
1600
1694
|
uid,
|
|
1695
|
+
generatedKey: this.buildGeneratedKey("keyboard", startingPageStateId, key === " " ? "space" : key, item.stableKey ?? item.selector ?? label),
|
|
1601
1696
|
};
|
|
1602
1697
|
}
|
|
1603
1698
|
buildDialogCloseTestElement(item, startingPath, sizeClass, uid, startingPageStateId) {
|
|
@@ -1628,6 +1723,7 @@ export class PageAnalyzer {
|
|
|
1628
1723
|
],
|
|
1629
1724
|
globalExpectations: this.defaultFlowExpectations("Dialog should close cleanly"),
|
|
1630
1725
|
uid,
|
|
1726
|
+
generatedKey: this.buildGeneratedKey("dialog-close", startingPageStateId, item.stableKey ?? item.selector ?? label),
|
|
1631
1727
|
};
|
|
1632
1728
|
}
|
|
1633
1729
|
buildEscapeDialogTestElement(startingPath, sizeClass, uid, startingPageStateId) {
|
|
@@ -1657,6 +1753,7 @@ export class PageAnalyzer {
|
|
|
1657
1753
|
],
|
|
1658
1754
|
globalExpectations: this.defaultFlowExpectations("Dialog should close on Escape without runtime errors"),
|
|
1659
1755
|
uid,
|
|
1756
|
+
generatedKey: this.buildGeneratedKey("dialog-escape", startingPageStateId, startingPath),
|
|
1660
1757
|
};
|
|
1661
1758
|
}
|
|
1662
1759
|
shouldUseDirectControlInteraction(item) {
|
|
@@ -1759,6 +1856,7 @@ export class PageAnalyzer {
|
|
|
1759
1856
|
? `${label} should remain non-interactive despite appearing disabled`
|
|
1760
1857
|
: `${label} should react without runtime errors`),
|
|
1761
1858
|
uid,
|
|
1859
|
+
generatedKey: this.buildGeneratedKey("control", startingPageStateId, isImmutable ? "immutable" : "enabled", role || inputType || item.actionKind || "control", item.stableKey ?? item.selector ?? label),
|
|
1762
1860
|
};
|
|
1763
1861
|
}
|
|
1764
1862
|
buildImmutableControlExpectations(item, label) {
|