@sudobility/testomniac_runner_service 0.1.53 → 0.1.55
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 +3 -0
- package/dist/analyzer/page-analyzer/generators/content.d.ts.map +1 -0
- package/dist/analyzer/page-analyzer/generators/content.js +34 -0
- package/dist/analyzer/page-analyzer/generators/content.js.map +1 -0
- package/dist/analyzer/page-analyzer/generators/dialogs.d.ts +3 -0
- package/dist/analyzer/page-analyzer/generators/dialogs.d.ts.map +1 -0
- package/dist/analyzer/page-analyzer/generators/dialogs.js +38 -0
- package/dist/analyzer/page-analyzer/generators/dialogs.js.map +1 -0
- package/dist/analyzer/page-analyzer/generators/e2e.d.ts +3 -0
- package/dist/analyzer/page-analyzer/generators/e2e.d.ts.map +1 -0
- package/dist/analyzer/page-analyzer/generators/e2e.js +28 -0
- package/dist/analyzer/page-analyzer/generators/e2e.js.map +1 -0
- package/dist/analyzer/page-analyzer/generators/forms.d.ts +3 -0
- package/dist/analyzer/page-analyzer/generators/forms.d.ts.map +1 -0
- package/dist/analyzer/page-analyzer/generators/forms.js +69 -0
- package/dist/analyzer/page-analyzer/generators/forms.js.map +1 -0
- package/dist/analyzer/page-analyzer/generators/hover-follow-up.d.ts +4 -0
- package/dist/analyzer/page-analyzer/generators/hover-follow-up.d.ts.map +1 -0
- package/dist/analyzer/page-analyzer/generators/hover-follow-up.js +34 -0
- package/dist/analyzer/page-analyzer/generators/hover-follow-up.js.map +1 -0
- package/dist/analyzer/page-analyzer/generators/keyboard-disclosure.d.ts +3 -0
- package/dist/analyzer/page-analyzer/generators/keyboard-disclosure.d.ts.map +1 -0
- package/dist/analyzer/page-analyzer/generators/keyboard-disclosure.js +30 -0
- package/dist/analyzer/page-analyzer/generators/keyboard-disclosure.js.map +1 -0
- package/dist/analyzer/page-analyzer/generators/navigation.d.ts +3 -0
- package/dist/analyzer/page-analyzer/generators/navigation.d.ts.map +1 -0
- package/dist/analyzer/page-analyzer/generators/navigation.js +22 -0
- package/dist/analyzer/page-analyzer/generators/navigation.js.map +1 -0
- package/dist/analyzer/page-analyzer/generators/render.d.ts +3 -0
- package/dist/analyzer/page-analyzer/generators/render.d.ts.map +1 -0
- package/dist/analyzer/page-analyzer/generators/render.js +26 -0
- package/dist/analyzer/page-analyzer/generators/render.js.map +1 -0
- package/dist/analyzer/page-analyzer/generators/scaffolds.d.ts +3 -0
- package/dist/analyzer/page-analyzer/generators/scaffolds.d.ts.map +1 -0
- package/dist/analyzer/page-analyzer/generators/scaffolds.js +36 -0
- package/dist/analyzer/page-analyzer/generators/scaffolds.js.map +1 -0
- package/dist/analyzer/page-analyzer/generators/semantic-journeys.d.ts +3 -0
- package/dist/analyzer/page-analyzer/generators/semantic-journeys.d.ts.map +1 -0
- package/dist/analyzer/page-analyzer/generators/semantic-journeys.js +30 -0
- package/dist/analyzer/page-analyzer/generators/semantic-journeys.js.map +1 -0
- package/dist/analyzer/page-analyzer/generators/variants.d.ts +3 -0
- package/dist/analyzer/page-analyzer/generators/variants.d.ts.map +1 -0
- package/dist/analyzer/page-analyzer/generators/variants.js +30 -0
- package/dist/analyzer/page-analyzer/generators/variants.js.map +1 -0
- package/dist/analyzer/{page-analyzer.d.ts → page-analyzer/index.d.ts} +7 -39
- package/dist/analyzer/page-analyzer/index.d.ts.map +1 -0
- package/dist/analyzer/{page-analyzer.js → page-analyzer/index.js} +63 -405
- package/dist/analyzer/page-analyzer/index.js.map +1 -0
- package/dist/analyzer/page-analyzer/types.d.ts +28 -0
- package/dist/analyzer/page-analyzer/types.d.ts.map +1 -0
- package/dist/analyzer/page-analyzer/types.js +1 -0
- package/dist/analyzer/page-analyzer/types.js.map +1 -0
- package/dist/expertise/tester/core-checks.d.ts.map +1 -1
- package/dist/expertise/tester/core-checks.js +2 -1
- package/dist/expertise/tester/core-checks.js.map +1 -1
- package/dist/orchestrator/runner.d.ts.map +1 -1
- package/dist/orchestrator/runner.js +19 -5
- package/dist/orchestrator/runner.js.map +1 -1
- package/dist/orchestrator/test-element-executor.d.ts.map +1 -1
- package/dist/orchestrator/test-element-executor.js +102 -25
- package/dist/orchestrator/test-element-executor.js.map +1 -1
- package/dist/orchestrator/types.d.ts +2 -0
- package/dist/orchestrator/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/analyzer/page-analyzer.d.ts.map +0 -1
- package/dist/analyzer/page-analyzer.js.map +0 -1
|
@@ -1,30 +1,6 @@
|
|
|
1
|
-
import type { TestElement, Expectation
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
import type { ScanEventHandler } from "../orchestrator/types";
|
|
5
|
-
export interface AnalyzerContext {
|
|
6
|
-
runnerId: number;
|
|
7
|
-
sizeClass: SizeClass;
|
|
8
|
-
uid?: string;
|
|
9
|
-
currentTestElementId: number;
|
|
10
|
-
currentTestSurfaceId: number;
|
|
11
|
-
currentSurfaceRunId: number | null;
|
|
12
|
-
html: string;
|
|
13
|
-
currentPageStateId: number;
|
|
14
|
-
beginningPageStateId: number;
|
|
15
|
-
currentPath: string;
|
|
16
|
-
pageId: number;
|
|
17
|
-
pageRequiresLogin: boolean;
|
|
18
|
-
scaffolds: DetectedScaffoldRegion[];
|
|
19
|
-
scaffoldSelectorByItemSelector: Record<string, string>;
|
|
20
|
-
actionableItems: ActionableItem[];
|
|
21
|
-
forms: FormInfo[];
|
|
22
|
-
journeySteps: TestStep[];
|
|
23
|
-
navigationSurface: TestSurfaceResponse;
|
|
24
|
-
bundleRun: TestSurfaceBundleRunResponse;
|
|
25
|
-
api: ApiClient;
|
|
26
|
-
events: ScanEventHandler;
|
|
27
|
-
}
|
|
1
|
+
import type { TestElement, Expectation } from "@sudobility/testomniac_types";
|
|
2
|
+
import type { AnalyzerContext } from "./types";
|
|
3
|
+
export type { AnalyzerContext } from "./types";
|
|
28
4
|
/**
|
|
29
5
|
* PageAnalyzer generates expectations and discovers new test elements
|
|
30
6
|
* during discovery mode.
|
|
@@ -40,18 +16,7 @@ export declare class PageAnalyzer {
|
|
|
40
16
|
* Called AFTER expertises evaluate and the target page state is established.
|
|
41
17
|
*/
|
|
42
18
|
generateTestElements(testElement: TestElement, context: AnalyzerContext): Promise<void>;
|
|
43
|
-
private generateHoverFollowUpCases;
|
|
44
|
-
private generateNavigationTestElements;
|
|
45
|
-
private generateScaffoldTestElements;
|
|
46
19
|
private getScaffoldSurfaceItems;
|
|
47
|
-
private generateRenderTestElements;
|
|
48
|
-
private generateFormTestElements;
|
|
49
|
-
private generateE2ETestElements;
|
|
50
|
-
private generateSemanticJourneyTestElements;
|
|
51
|
-
private generateDialogLifecycleTestElements;
|
|
52
|
-
private generateKeyboardAndDisclosureTestElements;
|
|
53
|
-
private generateVariantTestElements;
|
|
54
|
-
private generateContentTestElements;
|
|
55
20
|
private ensureSurfaceRun;
|
|
56
21
|
private isMouseActionable;
|
|
57
22
|
private isSurfaceCandidate;
|
|
@@ -65,6 +30,9 @@ export declare class PageAnalyzer {
|
|
|
65
30
|
private ensureTargetPageState;
|
|
66
31
|
private ensureScaffolds;
|
|
67
32
|
private ensureStoredForms;
|
|
33
|
+
private normalizeContext;
|
|
34
|
+
private normalizeActionableItems;
|
|
35
|
+
private normalizeForms;
|
|
68
36
|
private buildRenderTestElement;
|
|
69
37
|
private buildFormTestElement;
|
|
70
38
|
private buildNegativeFormTestElement;
|
|
@@ -153,4 +121,4 @@ export declare class PageAnalyzer {
|
|
|
153
121
|
private detectPasswordRequirements;
|
|
154
122
|
private generatePasswordVariants;
|
|
155
123
|
}
|
|
156
|
-
//# sourceMappingURL=
|
|
124
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analyzer/page-analyzer/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import { PlaywrightAction, ExpectationType, ExpectationSeverity, } from "@sudobility/testomniac_types";
|
|
2
|
-
import { computeHashes } from "
|
|
2
|
+
import { computeHashes } from "../../browser/page-utils";
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
|
-
import { fillValuePlanner } from "
|
|
5
|
-
import { AUTH_URL_PATTERNS, SIGNUP_URL_PATTERNS } from "
|
|
4
|
+
import { fillValuePlanner } from "../../planners/fill-value-planner";
|
|
5
|
+
import { AUTH_URL_PATTERNS, SIGNUP_URL_PATTERNS } from "../../config/constants";
|
|
6
|
+
import { generateHoverFollowUpCases } from "./generators/hover-follow-up";
|
|
7
|
+
import { generateNavigationTestElements } from "./generators/navigation";
|
|
8
|
+
import { generateScaffoldTestElements } from "./generators/scaffolds";
|
|
9
|
+
import { generateRenderTestElements } from "./generators/render";
|
|
10
|
+
import { generateFormTestElements } from "./generators/forms";
|
|
11
|
+
import { generateE2ETestElements } from "./generators/e2e";
|
|
12
|
+
import { generateSemanticJourneyTestElements } from "./generators/semantic-journeys";
|
|
13
|
+
import { generateDialogLifecycleTestElements } from "./generators/dialogs";
|
|
14
|
+
import { generateKeyboardAndDisclosureTestElements } from "./generators/keyboard-disclosure";
|
|
15
|
+
import { generateVariantTestElements } from "./generators/variants";
|
|
16
|
+
import { generateContentTestElements } from "./generators/content";
|
|
6
17
|
/**
|
|
7
18
|
* PageAnalyzer generates expectations and discovers new test elements
|
|
8
19
|
* during discovery mode.
|
|
@@ -13,6 +24,7 @@ export class PageAnalyzer {
|
|
|
13
24
|
* Called BEFORE expertises evaluate.
|
|
14
25
|
*/
|
|
15
26
|
generateExpectations(testElement) {
|
|
27
|
+
const steps = Array.isArray(testElement.steps) ? testElement.steps : [];
|
|
16
28
|
const expectations = [
|
|
17
29
|
{
|
|
18
30
|
expectationType: ExpectationType.PageLoaded,
|
|
@@ -28,8 +40,8 @@ export class PageAnalyzer {
|
|
|
28
40
|
},
|
|
29
41
|
];
|
|
30
42
|
// If test element has only a navigation action, no more expectations
|
|
31
|
-
const isNavigationOnly =
|
|
32
|
-
|
|
43
|
+
const isNavigationOnly = steps.length === 1 &&
|
|
44
|
+
steps[0]?.action?.actionType === PlaywrightAction.Goto;
|
|
33
45
|
if (!isNavigationOnly) {
|
|
34
46
|
expectations.push({
|
|
35
47
|
expectationType: ExpectationType.NoConsoleErrors,
|
|
@@ -45,414 +57,35 @@ export class PageAnalyzer {
|
|
|
45
57
|
* Called AFTER expertises evaluate and the target page state is established.
|
|
46
58
|
*/
|
|
47
59
|
async generateTestElements(testElement, context) {
|
|
48
|
-
const
|
|
60
|
+
const normalizedContext = this.normalizeContext(context);
|
|
61
|
+
const currentPageStateId = await this.ensureTargetPageState(normalizedContext);
|
|
49
62
|
const resolvedContext = {
|
|
50
|
-
...
|
|
63
|
+
...normalizedContext,
|
|
51
64
|
currentPageStateId,
|
|
52
65
|
};
|
|
53
66
|
if (this.isHoverOnly(testElement)) {
|
|
54
|
-
await
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
// a. Navigation test elements — for every link on the page
|
|
58
|
-
await this.generateNavigationTestElements(resolvedContext);
|
|
59
|
-
// b. Render test elements — capture render coverage for the page
|
|
60
|
-
await this.generateRenderTestElements(resolvedContext);
|
|
61
|
-
// c. Form and password test elements — build form workflows from extracted forms
|
|
62
|
-
await this.generateFormTestElements(resolvedContext);
|
|
63
|
-
// d. Synthetic journey test elements — build generic business flows from common UI verbs
|
|
64
|
-
await this.generateSemanticJourneyTestElements(resolvedContext);
|
|
65
|
-
// e. Journey test elements — preserve discovered multi-step flows as standalone e2e tests
|
|
66
|
-
await this.generateE2ETestElements(resolvedContext);
|
|
67
|
-
// f. Dialog lifecycle cases — only when a dialog is already open in the analyzed state
|
|
68
|
-
await this.generateDialogLifecycleTestElements(resolvedContext);
|
|
69
|
-
// g. Scaffold test elements — for each scaffold's actionable elements
|
|
70
|
-
await this.generateScaffoldTestElements(resolvedContext);
|
|
71
|
-
// h. Content test elements — for non-scaffold actionable elements
|
|
72
|
-
await this.generateContentTestElements(resolvedContext);
|
|
73
|
-
// i. Keyboard/disclosure cases
|
|
74
|
-
await this.generateKeyboardAndDisclosureTestElements(resolvedContext);
|
|
75
|
-
// j. Variant/option cases
|
|
76
|
-
await this.generateVariantTestElements(resolvedContext);
|
|
77
|
-
}
|
|
78
|
-
async generateHoverFollowUpCases(testElement, context) {
|
|
79
|
-
const selector = this.getPrimarySelector(testElement);
|
|
80
|
-
if (!selector || !context.currentPageStateId)
|
|
81
|
-
return;
|
|
82
|
-
const beginningItems = context.beginningPageStateId > 0
|
|
83
|
-
? await context.api.getItemsByPageState(context.beginningPageStateId)
|
|
84
|
-
: [];
|
|
85
|
-
const beginningKeys = new Set(beginningItems.map(item => this.getItemKey(item)).filter(Boolean));
|
|
86
|
-
const revealedItems = this.selectRepresentativeItems(context.actionableItems.filter(item => {
|
|
87
|
-
if (!this.isMouseActionable(item))
|
|
88
|
-
return false;
|
|
89
|
-
const key = this.getItemKey(item);
|
|
90
|
-
return Boolean(key) && !beginningKeys.has(key);
|
|
91
|
-
}));
|
|
92
|
-
const hoveredItem = context.actionableItems.find(item => item.selector === selector) ?? null;
|
|
93
|
-
if (revealedItems.length === 0 && hoveredItem) {
|
|
94
|
-
const clickCase = this.buildClickTestElement(hoveredItem, context.currentPath, context.sizeClass, context.uid, context.currentPageStateId, context.currentTestElementId);
|
|
95
|
-
const tc = await context.api.ensureTestElement(context.runnerId, context.currentTestSurfaceId, clickCase);
|
|
96
|
-
await context.api.createTestElementRun({
|
|
97
|
-
testElementId: tc.id,
|
|
98
|
-
testSurfaceRunId: context.currentSurfaceRunId ?? undefined,
|
|
99
|
-
});
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
for (const item of revealedItems) {
|
|
103
|
-
const nextHover = this.buildHoverTestElement(item, context.currentPath, context.sizeClass, context.uid, context.currentPageStateId, context.currentTestElementId);
|
|
104
|
-
const tc = await context.api.ensureTestElement(context.runnerId, context.currentTestSurfaceId, nextHover);
|
|
105
|
-
await context.api.createTestElementRun({
|
|
106
|
-
testElementId: tc.id,
|
|
107
|
-
testSurfaceRunId: context.currentSurfaceRunId ?? undefined,
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
async generateNavigationTestElements(context) {
|
|
112
|
-
if (context.pageRequiresLogin)
|
|
67
|
+
await generateHoverFollowUpCases(this, testElement, resolvedContext);
|
|
113
68
|
return;
|
|
114
|
-
const { api, runnerId, sizeClass, uid, navigationSurface, bundleRun } = context;
|
|
115
|
-
const links = this.selectRepresentativeItems(context.actionableItems.filter(item => item.actionKind === "navigate" && item.href && item.visible));
|
|
116
|
-
// Ensure navigation surface is in the bundle
|
|
117
|
-
await api.ensureBundleSurfaceLink(bundleRun.testSurfaceBundleId, navigationSurface.id);
|
|
118
|
-
// Ensure a surface run exists for the navigation surface under this bundle run
|
|
119
|
-
const surfaceRun = await this.ensureSurfaceRun(api, navigationSurface.id, bundleRun.id);
|
|
120
|
-
for (const link of links) {
|
|
121
|
-
if (!link.href)
|
|
122
|
-
continue;
|
|
123
|
-
const path = this.extractRelativePath(link.href);
|
|
124
|
-
if (!path)
|
|
125
|
-
continue;
|
|
126
|
-
const testElement = this.buildNavigationTestElement(path, sizeClass, uid, context.currentPageStateId);
|
|
127
|
-
const tc = await api.ensureTestElement(runnerId, navigationSurface.id, testElement);
|
|
128
|
-
await api.createTestElementRun({
|
|
129
|
-
testElementId: tc.id,
|
|
130
|
-
testSurfaceRunId: surfaceRun.id,
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
async generateScaffoldTestElements(context) {
|
|
135
|
-
const { api, runnerId, sizeClass, uid, bundleRun } = context;
|
|
136
|
-
for (const scaffold of context.scaffolds) {
|
|
137
|
-
const scaffoldItems = this.selectRepresentativeItems(this.getScaffoldSurfaceItems(context, scaffold));
|
|
138
|
-
if (scaffoldItems.length === 0)
|
|
139
|
-
continue;
|
|
140
|
-
// Ensure a test surface for this scaffold
|
|
141
|
-
const surfaceTitle = `Scaffold: ${scaffold.type}`;
|
|
142
|
-
const surface = await api.ensureTestSurface(runnerId, {
|
|
143
|
-
title: surfaceTitle,
|
|
144
|
-
description: `Tests for ${scaffold.type} scaffold`,
|
|
145
|
-
startingPageStateId: context.currentPageStateId,
|
|
146
|
-
startingPath: context.currentPath,
|
|
147
|
-
sizeClass,
|
|
148
|
-
priority: 3,
|
|
149
|
-
surface_tags: ["scaffold", scaffold.type],
|
|
150
|
-
uid,
|
|
151
|
-
});
|
|
152
|
-
context.events.onTestSurfaceCreated({
|
|
153
|
-
surfaceId: surface.id,
|
|
154
|
-
title: surface.title,
|
|
155
|
-
});
|
|
156
|
-
await api.ensureBundleSurfaceLink(bundleRun.testSurfaceBundleId, surface.id);
|
|
157
|
-
const surfaceRun = await this.ensureSurfaceRun(api, surface.id, bundleRun.id);
|
|
158
|
-
for (const item of scaffoldItems) {
|
|
159
|
-
const testElement = this.shouldUseDirectControlInteraction(item)
|
|
160
|
-
? this.buildControlInteractionTestElement(item, context.currentPath, sizeClass, uid, context.currentPageStateId)
|
|
161
|
-
: this.buildHoverTestElement(item, context.currentPath, sizeClass, uid, context.currentPageStateId);
|
|
162
|
-
const tc = await api.ensureTestElement(runnerId, surface.id, testElement);
|
|
163
|
-
await api.createTestElementRun({
|
|
164
|
-
testElementId: tc.id,
|
|
165
|
-
testSurfaceRunId: surfaceRun.id,
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
69
|
}
|
|
70
|
+
await generateNavigationTestElements(this, resolvedContext);
|
|
71
|
+
await generateRenderTestElements(this, resolvedContext);
|
|
72
|
+
await generateFormTestElements(this, resolvedContext);
|
|
73
|
+
await generateSemanticJourneyTestElements(this, resolvedContext);
|
|
74
|
+
await generateE2ETestElements(this, resolvedContext);
|
|
75
|
+
await generateDialogLifecycleTestElements(this, resolvedContext);
|
|
76
|
+
await generateScaffoldTestElements(this, resolvedContext);
|
|
77
|
+
await generateContentTestElements(this, resolvedContext);
|
|
78
|
+
await generateKeyboardAndDisclosureTestElements(this, resolvedContext);
|
|
79
|
+
await generateVariantTestElements(this, resolvedContext);
|
|
169
80
|
}
|
|
170
81
|
getScaffoldSurfaceItems(context, scaffold) {
|
|
171
|
-
return context.actionableItems.filter(item => {
|
|
82
|
+
return this.normalizeActionableItems(context.actionableItems).filter(item => {
|
|
172
83
|
if (!this.isSurfaceCandidate(item) || !item.selector)
|
|
173
84
|
return false;
|
|
174
85
|
return (context.scaffoldSelectorByItemSelector[item.selector] ===
|
|
175
86
|
scaffold.selector);
|
|
176
87
|
});
|
|
177
88
|
}
|
|
178
|
-
async generateRenderTestElements(context) {
|
|
179
|
-
const { api, runnerId, sizeClass, uid, bundleRun } = context;
|
|
180
|
-
const surface = await api.ensureTestSurface(runnerId, {
|
|
181
|
-
title: `Render: ${context.currentPath}`,
|
|
182
|
-
description: `Render validation for ${context.currentPath}`,
|
|
183
|
-
startingPageStateId: context.currentPageStateId,
|
|
184
|
-
startingPath: context.currentPath,
|
|
185
|
-
sizeClass,
|
|
186
|
-
priority: 2,
|
|
187
|
-
surface_tags: ["render"],
|
|
188
|
-
uid,
|
|
189
|
-
});
|
|
190
|
-
context.events.onTestSurfaceCreated({
|
|
191
|
-
surfaceId: surface.id,
|
|
192
|
-
title: surface.title,
|
|
193
|
-
});
|
|
194
|
-
await api.ensureBundleSurfaceLink(bundleRun.testSurfaceBundleId, surface.id);
|
|
195
|
-
const surfaceRun = await this.ensureSurfaceRun(api, surface.id, bundleRun.id);
|
|
196
|
-
const testElement = this.buildRenderTestElement(context.currentPath, sizeClass, uid, context.currentPageStateId, context.pageId);
|
|
197
|
-
const tc = await api.ensureTestElement(runnerId, surface.id, testElement);
|
|
198
|
-
await api.createTestElementRun({
|
|
199
|
-
testElementId: tc.id,
|
|
200
|
-
testSurfaceRunId: surfaceRun.id,
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
async generateFormTestElements(context) {
|
|
204
|
-
if (context.forms.length === 0)
|
|
205
|
-
return;
|
|
206
|
-
const { api, runnerId, sizeClass, uid, bundleRun } = context;
|
|
207
|
-
const surface = await api.ensureTestSurface(runnerId, {
|
|
208
|
-
title: `Forms: ${context.currentPath}`,
|
|
209
|
-
description: `Form workflows for ${context.currentPath}`,
|
|
210
|
-
startingPageStateId: context.currentPageStateId,
|
|
211
|
-
startingPath: context.currentPath,
|
|
212
|
-
sizeClass,
|
|
213
|
-
priority: 2,
|
|
214
|
-
surface_tags: ["form"],
|
|
215
|
-
uid,
|
|
216
|
-
});
|
|
217
|
-
context.events.onTestSurfaceCreated({
|
|
218
|
-
surfaceId: surface.id,
|
|
219
|
-
title: surface.title,
|
|
220
|
-
});
|
|
221
|
-
await api.ensureBundleSurfaceLink(bundleRun.testSurfaceBundleId, surface.id);
|
|
222
|
-
const surfaceRun = await this.ensureSurfaceRun(api, surface.id, bundleRun.id);
|
|
223
|
-
for (let index = 0; index < context.forms.length; index++) {
|
|
224
|
-
const form = context.forms[index];
|
|
225
|
-
const formType = this.identifyFormType(form, context.currentPath);
|
|
226
|
-
const formLabel = this.describeForm(form, index);
|
|
227
|
-
const validValues = this.planFormValues(form, context.actionableItems);
|
|
228
|
-
if (this.isSearchForm(form)) {
|
|
229
|
-
const searchTests = this.buildSearchTestElements(form, formLabel, context.currentPath, sizeClass, uid, context.currentPageStateId, validValues, context.actionableItems);
|
|
230
|
-
for (const searchTest of searchTests) {
|
|
231
|
-
const searchElement = await api.ensureTestElement(runnerId, surface.id, searchTest);
|
|
232
|
-
await api.createTestElementRun({
|
|
233
|
-
testElementId: searchElement.id,
|
|
234
|
-
testSurfaceRunId: surfaceRun.id,
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
continue;
|
|
238
|
-
}
|
|
239
|
-
const positive = this.buildFormTestElement(form, formLabel, formType, context.currentPath, sizeClass, uid, context.currentPageStateId, validValues);
|
|
240
|
-
const positiveElement = await api.ensureTestElement(runnerId, surface.id, positive);
|
|
241
|
-
await api.createTestElementRun({
|
|
242
|
-
testElementId: positiveElement.id,
|
|
243
|
-
testSurfaceRunId: surfaceRun.id,
|
|
244
|
-
});
|
|
245
|
-
for (const field of form.fields.filter(field => this.isNegativeCandidateField(field))) {
|
|
246
|
-
const negative = this.buildNegativeFormTestElement(form, formLabel, formType, field, context.currentPath, sizeClass, uid, context.currentPageStateId, validValues);
|
|
247
|
-
const negativeElement = await api.ensureTestElement(runnerId, surface.id, negative);
|
|
248
|
-
await api.createTestElementRun({
|
|
249
|
-
testElementId: negativeElement.id,
|
|
250
|
-
testSurfaceRunId: surfaceRun.id,
|
|
251
|
-
});
|
|
252
|
-
const correction = this.buildFormCorrectionTestElement(form, formLabel, formType, field, context.currentPath, sizeClass, uid, context.currentPageStateId, validValues);
|
|
253
|
-
const correctionElement = await api.ensureTestElement(runnerId, surface.id, correction);
|
|
254
|
-
await api.createTestElementRun({
|
|
255
|
-
testElementId: correctionElement.id,
|
|
256
|
-
testSurfaceRunId: surfaceRun.id,
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
if (this.isPasswordScenario(formType, form)) {
|
|
260
|
-
const passwordTests = this.buildPasswordTestElements(form, formLabel, formType, context.currentPath, sizeClass, uid, context.currentPageStateId, validValues, this.detectPasswordRequirements(this.extractVisibleText(context.html)));
|
|
261
|
-
for (const passwordTest of passwordTests) {
|
|
262
|
-
const passwordElement = await api.ensureTestElement(runnerId, surface.id, passwordTest);
|
|
263
|
-
await api.createTestElementRun({
|
|
264
|
-
testElementId: passwordElement.id,
|
|
265
|
-
testSurfaceRunId: surfaceRun.id,
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
async generateE2ETestElements(context) {
|
|
272
|
-
if (context.journeySteps.length < 2)
|
|
273
|
-
return;
|
|
274
|
-
const { api, runnerId, sizeClass, uid, bundleRun } = context;
|
|
275
|
-
const surface = await api.ensureTestSurface(runnerId, {
|
|
276
|
-
title: `Journeys: ${context.currentPath}`,
|
|
277
|
-
description: `End-to-end journeys reaching ${context.currentPath}`,
|
|
278
|
-
startingPageStateId: context.currentPageStateId,
|
|
279
|
-
startingPath: context.currentPath,
|
|
280
|
-
sizeClass,
|
|
281
|
-
priority: 2,
|
|
282
|
-
surface_tags: ["e2e"],
|
|
283
|
-
uid,
|
|
284
|
-
});
|
|
285
|
-
context.events.onTestSurfaceCreated({
|
|
286
|
-
surfaceId: surface.id,
|
|
287
|
-
title: surface.title,
|
|
288
|
-
});
|
|
289
|
-
await api.ensureBundleSurfaceLink(bundleRun.testSurfaceBundleId, surface.id);
|
|
290
|
-
const surfaceRun = await this.ensureSurfaceRun(api, surface.id, bundleRun.id);
|
|
291
|
-
const e2e = this.buildE2ETestElement(context.currentPath, sizeClass, uid, context.currentPageStateId, context.journeySteps);
|
|
292
|
-
const tc = await api.ensureTestElement(runnerId, surface.id, e2e);
|
|
293
|
-
await api.createTestElementRun({
|
|
294
|
-
testElementId: tc.id,
|
|
295
|
-
testSurfaceRunId: surfaceRun.id,
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
async generateSemanticJourneyTestElements(context) {
|
|
299
|
-
const journeys = this.buildSemanticJourneyTestElements(context);
|
|
300
|
-
if (journeys.length === 0)
|
|
301
|
-
return;
|
|
302
|
-
const { api, runnerId, bundleRun } = context;
|
|
303
|
-
const surface = await api.ensureTestSurface(runnerId, {
|
|
304
|
-
title: `Journeys: ${context.currentPath}`,
|
|
305
|
-
description: `Semantic multi-step journeys from ${context.currentPath}`,
|
|
306
|
-
startingPageStateId: context.currentPageStateId,
|
|
307
|
-
startingPath: context.currentPath,
|
|
308
|
-
sizeClass: context.sizeClass,
|
|
309
|
-
priority: 2,
|
|
310
|
-
surface_tags: ["e2e", "semantic-journey"],
|
|
311
|
-
uid: context.uid,
|
|
312
|
-
});
|
|
313
|
-
context.events.onTestSurfaceCreated({
|
|
314
|
-
surfaceId: surface.id,
|
|
315
|
-
title: surface.title,
|
|
316
|
-
});
|
|
317
|
-
await api.ensureBundleSurfaceLink(bundleRun.testSurfaceBundleId, surface.id);
|
|
318
|
-
const surfaceRun = await this.ensureSurfaceRun(api, surface.id, bundleRun.id);
|
|
319
|
-
for (const journey of journeys) {
|
|
320
|
-
const tc = await api.ensureTestElement(runnerId, surface.id, journey);
|
|
321
|
-
await api.createTestElementRun({
|
|
322
|
-
testElementId: tc.id,
|
|
323
|
-
testSurfaceRunId: surfaceRun.id,
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
async generateDialogLifecycleTestElements(context) {
|
|
328
|
-
if (!this.pageHasOpenDialog(context.html))
|
|
329
|
-
return;
|
|
330
|
-
const closeCandidates = this.selectRepresentativeItems(context.actionableItems.filter(item => item.visible &&
|
|
331
|
-
!item.disabled &&
|
|
332
|
-
item.selector &&
|
|
333
|
-
this.isDialogCloseItem(item)));
|
|
334
|
-
const tests = [];
|
|
335
|
-
for (const item of closeCandidates) {
|
|
336
|
-
tests.push(this.buildDialogCloseTestElement(item, context.currentPath, context.sizeClass, context.uid, context.currentPageStateId));
|
|
337
|
-
}
|
|
338
|
-
tests.push(this.buildEscapeDialogTestElement(context.currentPath, context.sizeClass, context.uid, context.currentPageStateId));
|
|
339
|
-
const { api, runnerId, bundleRun } = context;
|
|
340
|
-
const surface = await api.ensureTestSurface(runnerId, {
|
|
341
|
-
title: `Dialogs: ${context.currentPath}`,
|
|
342
|
-
description: `Dialog lifecycle checks for ${context.currentPath}`,
|
|
343
|
-
startingPageStateId: context.currentPageStateId,
|
|
344
|
-
startingPath: context.currentPath,
|
|
345
|
-
sizeClass: context.sizeClass,
|
|
346
|
-
priority: 2,
|
|
347
|
-
surface_tags: ["dialog"],
|
|
348
|
-
uid: context.uid,
|
|
349
|
-
});
|
|
350
|
-
context.events.onTestSurfaceCreated({
|
|
351
|
-
surfaceId: surface.id,
|
|
352
|
-
title: surface.title,
|
|
353
|
-
});
|
|
354
|
-
await api.ensureBundleSurfaceLink(bundleRun.testSurfaceBundleId, surface.id);
|
|
355
|
-
const surfaceRun = await this.ensureSurfaceRun(api, surface.id, bundleRun.id);
|
|
356
|
-
for (const test of tests) {
|
|
357
|
-
const tc = await api.ensureTestElement(runnerId, surface.id, test);
|
|
358
|
-
await api.createTestElementRun({
|
|
359
|
-
testElementId: tc.id,
|
|
360
|
-
testSurfaceRunId: surfaceRun.id,
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
async generateKeyboardAndDisclosureTestElements(context) {
|
|
365
|
-
const tests = this.buildKeyboardAndDisclosureTestElements(context);
|
|
366
|
-
if (tests.length === 0)
|
|
367
|
-
return;
|
|
368
|
-
const { api, runnerId, bundleRun } = context;
|
|
369
|
-
const surface = await api.ensureTestSurface(runnerId, {
|
|
370
|
-
title: `Keyboard: ${context.currentPath}`,
|
|
371
|
-
description: `Keyboard parity and disclosure checks for ${context.currentPath}`,
|
|
372
|
-
startingPageStateId: context.currentPageStateId,
|
|
373
|
-
startingPath: context.currentPath,
|
|
374
|
-
sizeClass: context.sizeClass,
|
|
375
|
-
priority: 3,
|
|
376
|
-
surface_tags: ["keyboard", "disclosure"],
|
|
377
|
-
uid: context.uid,
|
|
378
|
-
});
|
|
379
|
-
context.events.onTestSurfaceCreated({
|
|
380
|
-
surfaceId: surface.id,
|
|
381
|
-
title: surface.title,
|
|
382
|
-
});
|
|
383
|
-
await api.ensureBundleSurfaceLink(bundleRun.testSurfaceBundleId, surface.id);
|
|
384
|
-
const surfaceRun = await this.ensureSurfaceRun(api, surface.id, bundleRun.id);
|
|
385
|
-
for (const test of tests) {
|
|
386
|
-
const tc = await api.ensureTestElement(runnerId, surface.id, test);
|
|
387
|
-
await api.createTestElementRun({
|
|
388
|
-
testElementId: tc.id,
|
|
389
|
-
testSurfaceRunId: surfaceRun.id,
|
|
390
|
-
});
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
async generateVariantTestElements(context) {
|
|
394
|
-
const tests = this.buildVariantTestElements(context);
|
|
395
|
-
if (tests.length === 0)
|
|
396
|
-
return;
|
|
397
|
-
const { api, runnerId, bundleRun } = context;
|
|
398
|
-
const surface = await api.ensureTestSurface(runnerId, {
|
|
399
|
-
title: `Variants: ${context.currentPath}`,
|
|
400
|
-
description: `Variant and option state checks for ${context.currentPath}`,
|
|
401
|
-
startingPageStateId: context.currentPageStateId,
|
|
402
|
-
startingPath: context.currentPath,
|
|
403
|
-
sizeClass: context.sizeClass,
|
|
404
|
-
priority: 2,
|
|
405
|
-
surface_tags: ["variant", "option"],
|
|
406
|
-
uid: context.uid,
|
|
407
|
-
});
|
|
408
|
-
context.events.onTestSurfaceCreated({
|
|
409
|
-
surfaceId: surface.id,
|
|
410
|
-
title: surface.title,
|
|
411
|
-
});
|
|
412
|
-
await api.ensureBundleSurfaceLink(bundleRun.testSurfaceBundleId, surface.id);
|
|
413
|
-
const surfaceRun = await this.ensureSurfaceRun(api, surface.id, bundleRun.id);
|
|
414
|
-
for (const test of tests) {
|
|
415
|
-
const tc = await api.ensureTestElement(runnerId, surface.id, test);
|
|
416
|
-
await api.createTestElementRun({
|
|
417
|
-
testElementId: tc.id,
|
|
418
|
-
testSurfaceRunId: surfaceRun.id,
|
|
419
|
-
});
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
async generateContentTestElements(context) {
|
|
423
|
-
const { api, runnerId, sizeClass, uid, bundleRun, pageId: _pageId, } = context;
|
|
424
|
-
// Content items are those NOT in a scaffold
|
|
425
|
-
const contentItems = this.selectRepresentativeItems(context.actionableItems.filter(item => item.scaffoldId == null && this.isSurfaceCandidate(item)));
|
|
426
|
-
if (contentItems.length === 0)
|
|
427
|
-
return;
|
|
428
|
-
const surfaceTitle = `Page: ${context.currentPath}`;
|
|
429
|
-
const surface = await api.ensureTestSurface(runnerId, {
|
|
430
|
-
title: surfaceTitle,
|
|
431
|
-
description: `Tests for page content at ${context.currentPath}`,
|
|
432
|
-
startingPageStateId: context.currentPageStateId,
|
|
433
|
-
startingPath: context.currentPath,
|
|
434
|
-
sizeClass,
|
|
435
|
-
priority: 3,
|
|
436
|
-
surface_tags: ["page-content"],
|
|
437
|
-
uid,
|
|
438
|
-
});
|
|
439
|
-
context.events.onTestSurfaceCreated({
|
|
440
|
-
surfaceId: surface.id,
|
|
441
|
-
title: surface.title,
|
|
442
|
-
});
|
|
443
|
-
await api.ensureBundleSurfaceLink(bundleRun.testSurfaceBundleId, surface.id);
|
|
444
|
-
const surfaceRun = await this.ensureSurfaceRun(api, surface.id, bundleRun.id);
|
|
445
|
-
for (const item of contentItems) {
|
|
446
|
-
const testElement = this.shouldUseDirectControlInteraction(item)
|
|
447
|
-
? this.buildControlInteractionTestElement(item, context.currentPath, sizeClass, uid, context.currentPageStateId)
|
|
448
|
-
: this.buildHoverTestElement(item, context.currentPath, sizeClass, uid, context.currentPageStateId);
|
|
449
|
-
const tc = await api.ensureTestElement(runnerId, surface.id, testElement);
|
|
450
|
-
await api.createTestElementRun({
|
|
451
|
-
testElementId: tc.id,
|
|
452
|
-
testSurfaceRunId: surfaceRun.id,
|
|
453
|
-
});
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
89
|
async ensureSurfaceRun(api, testSurfaceId, bundleRunId) {
|
|
457
90
|
const openSurfaceRuns = await api.getOpenTestSurfaceRuns(bundleRunId);
|
|
458
91
|
const existing = openSurfaceRuns.find(surfaceRun => surfaceRun.testSurfaceId === testSurfaceId);
|
|
@@ -566,11 +199,13 @@ export class PageAnalyzer {
|
|
|
566
199
|
};
|
|
567
200
|
}
|
|
568
201
|
isHoverOnly(testElement) {
|
|
569
|
-
|
|
570
|
-
|
|
202
|
+
const steps = Array.isArray(testElement.steps) ? testElement.steps : [];
|
|
203
|
+
return (steps.length === 1 &&
|
|
204
|
+
steps[0]?.action?.actionType === PlaywrightAction.Hover);
|
|
571
205
|
}
|
|
572
206
|
getPrimarySelector(testElement) {
|
|
573
|
-
const
|
|
207
|
+
const steps = Array.isArray(testElement.steps) ? testElement.steps : [];
|
|
208
|
+
const step = steps[0];
|
|
574
209
|
return step?.action.path ?? null;
|
|
575
210
|
}
|
|
576
211
|
getItemKey(item) {
|
|
@@ -649,16 +284,39 @@ export class PageAnalyzer {
|
|
|
649
284
|
return scaffoldIdsBySelector;
|
|
650
285
|
}
|
|
651
286
|
async ensureStoredForms(pageStateId, context) {
|
|
652
|
-
|
|
287
|
+
const forms = this.normalizeForms(context.forms);
|
|
288
|
+
if (forms.length === 0)
|
|
653
289
|
return;
|
|
654
290
|
const existing = await context.api.getFormsByPageState(pageStateId);
|
|
655
291
|
const existingSelectors = new Set(existing.map(form => form.selector));
|
|
656
|
-
for (const form of
|
|
292
|
+
for (const form of forms) {
|
|
657
293
|
if (existingSelectors.has(form.selector))
|
|
658
294
|
continue;
|
|
659
295
|
await context.api.insertForm(pageStateId, form, this.identifyFormType(form, context.currentPath));
|
|
660
296
|
}
|
|
661
297
|
}
|
|
298
|
+
normalizeContext(context) {
|
|
299
|
+
return {
|
|
300
|
+
...context,
|
|
301
|
+
html: typeof context.html === "string" ? context.html : "",
|
|
302
|
+
scaffolds: Array.isArray(context.scaffolds) ? context.scaffolds : [],
|
|
303
|
+
scaffoldSelectorByItemSelector: context.scaffoldSelectorByItemSelector &&
|
|
304
|
+
typeof context.scaffoldSelectorByItemSelector === "object"
|
|
305
|
+
? context.scaffoldSelectorByItemSelector
|
|
306
|
+
: {},
|
|
307
|
+
actionableItems: this.normalizeActionableItems(context.actionableItems),
|
|
308
|
+
forms: this.normalizeForms(context.forms),
|
|
309
|
+
journeySteps: Array.isArray(context.journeySteps)
|
|
310
|
+
? context.journeySteps
|
|
311
|
+
: [],
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
normalizeActionableItems(items) {
|
|
315
|
+
return Array.isArray(items) ? items : [];
|
|
316
|
+
}
|
|
317
|
+
normalizeForms(forms) {
|
|
318
|
+
return Array.isArray(forms) ? forms : [];
|
|
319
|
+
}
|
|
662
320
|
buildRenderTestElement(currentPath, sizeClass, uid, startingPageStateId, pageId) {
|
|
663
321
|
return {
|
|
664
322
|
title: `Render — ${currentPath}`,
|
|
@@ -2550,4 +2208,4 @@ export class PageAnalyzer {
|
|
|
2550
2208
|
return variants;
|
|
2551
2209
|
}
|
|
2552
2210
|
}
|
|
2553
|
-
//# sourceMappingURL=
|
|
2211
|
+
//# sourceMappingURL=index.js.map
|