@sudobility/testomniac_runner_service 0.1.84 → 0.1.86
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/hover-follow-up.d.ts.map +1 -1
- package/dist/analyzer/page-analyzer/generators/hover-follow-up.js +21 -0
- package/dist/analyzer/page-analyzer/generators/hover-follow-up.js.map +1 -1
- package/dist/analyzer/page-analyzer/index.d.ts +50 -0
- package/dist/analyzer/page-analyzer/index.d.ts.map +1 -1
- package/dist/analyzer/page-analyzer/index.js +97 -1
- package/dist/analyzer/page-analyzer/index.js.map +1 -1
- package/dist/browser/dom-snapshot.d.ts.map +1 -1
- package/dist/browser/dom-snapshot.js +37 -0
- package/dist/browser/dom-snapshot.js.map +1 -1
- package/dist/browser/page-utils.d.ts +6 -0
- package/dist/browser/page-utils.d.ts.map +1 -1
- package/dist/browser/page-utils.js +12 -4
- package/dist/browser/page-utils.js.map +1 -1
- package/dist/orchestrator/test-interaction-executor.d.ts.map +1 -1
- package/dist/orchestrator/test-interaction-executor.js +47 -9
- package/dist/orchestrator/test-interaction-executor.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hover-follow-up.d.ts","sourceRoot":"","sources":["../../../../src/analyzer/page-analyzer/generators/hover-follow-up.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"hover-follow-up.d.ts","sourceRoot":"","sources":["../../../../src/analyzer/page-analyzer/generators/hover-follow-up.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAGpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,GAAG,EACb,eAAe,EAAE,eAAe,EAChC,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,IAAI,CAAC,CAsLf"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { matchesActionableItemSelector } from "../../../browser/replay-selector";
|
|
2
|
+
import { computeActionableHash } from "../../../browser/page-utils";
|
|
2
3
|
export async function generateHoverFollowUpCases(analyzer, testInteraction, context) {
|
|
3
4
|
const selector = analyzer.getPrimarySelector(testInteraction);
|
|
4
5
|
if (!selector || !context.currentPageStateId) {
|
|
@@ -81,6 +82,26 @@ export async function generateHoverFollowUpCases(analyzer, testInteraction, cont
|
|
|
81
82
|
});
|
|
82
83
|
return;
|
|
83
84
|
}
|
|
85
|
+
// Skip if a different path already produced the same interactive elements.
|
|
86
|
+
// Note: we check the hash but don't register it — registration happens in
|
|
87
|
+
// the full generateTestInteractions pass. Registering here would
|
|
88
|
+
// incorrectly block full generation for a page reached via non-hover.
|
|
89
|
+
const actionableHash = await computeActionableHash(context.actionableItems);
|
|
90
|
+
if (analyzer.hasGeneratedForActionableHash(actionableHash)) {
|
|
91
|
+
console.info("[PageAnalyzer][hover-follow-up] actionable-items-already-covered", {
|
|
92
|
+
testInteractionId: context.currentTestInteractionId,
|
|
93
|
+
sourceTitle: testInteraction.title,
|
|
94
|
+
currentPath,
|
|
95
|
+
actionableHash,
|
|
96
|
+
});
|
|
97
|
+
await analyzer.reconcileGeneratedSurfaceElements(context, {
|
|
98
|
+
surfaceId: context.currentTestSurfaceId,
|
|
99
|
+
surfaceTitle: "",
|
|
100
|
+
desiredKeys: [],
|
|
101
|
+
dependencyTestInteractionId: context.currentTestInteractionId,
|
|
102
|
+
});
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
84
105
|
console.info("[PageAnalyzer][hover-follow-up] generating-hover-follow-ups", {
|
|
85
106
|
testInteractionId: context.currentTestInteractionId,
|
|
86
107
|
sourceTitle: testInteraction.title,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hover-follow-up.js","sourceRoot":"","sources":["../../../../src/analyzer/page-analyzer/generators/hover-follow-up.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,6BAA6B,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"hover-follow-up.js","sourceRoot":"","sources":["../../../../src/analyzer/page-analyzer/generators/hover-follow-up.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,8 +15,58 @@ type AppendActionResult = {
|
|
|
15
15
|
export declare class PageAnalyzer {
|
|
16
16
|
/** Paths for which full generation has already run in this test-run. */
|
|
17
17
|
private generatedPaths;
|
|
18
|
+
/**
|
|
19
|
+
* Actionable-item hashes for which full generation has already run.
|
|
20
|
+
* Different URL paths can produce the same set of interactive elements
|
|
21
|
+
* (e.g. `/store/` and `/store/all-items/`). Generating hover/click tests
|
|
22
|
+
* for the same elements twice is pure waste, so we deduplicate by the hash
|
|
23
|
+
* of visible actionable-item stable keys.
|
|
24
|
+
*/
|
|
25
|
+
private generatedActionableHashes;
|
|
26
|
+
/**
|
|
27
|
+
* Tracks page-scoped finding keys already recorded during this run.
|
|
28
|
+
* Page-level findings (page-health checks, page-load expectations) describe
|
|
29
|
+
* the page itself, not a specific interaction. Reporting them once per page
|
|
30
|
+
* path is sufficient — duplicating them for every hover/click on the same
|
|
31
|
+
* page just adds noise.
|
|
32
|
+
*/
|
|
33
|
+
private reportedPageFindingKeys;
|
|
34
|
+
/**
|
|
35
|
+
* Generic key-based dedup for findings where text-based matching is too
|
|
36
|
+
* fragile (e.g. page-health titles include variable counts).
|
|
37
|
+
*/
|
|
38
|
+
private reportedFindingKeys;
|
|
18
39
|
/** Check whether generation already happened for a given path in this run. */
|
|
19
40
|
hasGeneratedForPath(path: string): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Normalize finding text for dedup: strip leading count numbers that vary
|
|
43
|
+
* between evaluations. Preserves URLs, status codes, and other content.
|
|
44
|
+
*
|
|
45
|
+
* "[page-health] 5 broken image(s)" → "[page-health] broken image(s)"
|
|
46
|
+
* "3 significant console warning(s)" → "significant console warning(s)"
|
|
47
|
+
* "Page returned HTTP 404 for …" → unchanged
|
|
48
|
+
*/
|
|
49
|
+
private static normalizeFindingText;
|
|
50
|
+
/**
|
|
51
|
+
* Returns true if an equivalent page-scoped finding has already been
|
|
52
|
+
* recorded during this run. Both title and description are normalized
|
|
53
|
+
* to strip variable leading counts so that "3 console error(s): …" and
|
|
54
|
+
* "5 console error(s): …" are treated as the same finding.
|
|
55
|
+
*/
|
|
56
|
+
hasReportedPageFinding(_path: string, title: string, description: string): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Mark a page-scoped finding as recorded so it is not duplicated.
|
|
59
|
+
*/
|
|
60
|
+
markPageFindingReported(_path: string, title: string, description: string): void;
|
|
61
|
+
/** Check whether a finding with the given stable key has been reported. */
|
|
62
|
+
hasReportedFindingByKey(key: string): boolean;
|
|
63
|
+
/** Mark a stable finding key as reported. */
|
|
64
|
+
markReportedFindingByKey(key: string): void;
|
|
65
|
+
/**
|
|
66
|
+
* Check whether full test generation already ran for a page state with the
|
|
67
|
+
* same visible actionable items (by hash).
|
|
68
|
+
*/
|
|
69
|
+
hasGeneratedForActionableHash(hash: string): boolean;
|
|
20
70
|
/**
|
|
21
71
|
* Generate baseline expectations for a test element.
|
|
22
72
|
* Called BEFORE expertises evaluate.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analyzer/page-analyzer/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EAQZ,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analyzer/page-analyzer/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PlaywrightAction, ExpectationType, ExpectationSeverity, } from "@sudobility/testomniac_types";
|
|
2
2
|
import { buildReplaySelectorFromActionableItem, matchesActionableItemSelector, } from "../../browser/replay-selector";
|
|
3
|
-
import { computeHashes, sha256, normalizeHtml } from "../../browser/page-utils";
|
|
3
|
+
import { computeHashes, computeActionableHash, sha256, normalizeHtml, } from "../../browser/page-utils";
|
|
4
4
|
import { getBody, getContentBody } from "../../scanner/html-decomposer";
|
|
5
5
|
import { createHash } from "node:crypto";
|
|
6
6
|
import { fillValuePlanner } from "../../planners/fill-value-planner";
|
|
@@ -27,10 +27,74 @@ function logAnalyzer(step, details) {
|
|
|
27
27
|
export class PageAnalyzer {
|
|
28
28
|
/** Paths for which full generation has already run in this test-run. */
|
|
29
29
|
generatedPaths = new Set();
|
|
30
|
+
/**
|
|
31
|
+
* Actionable-item hashes for which full generation has already run.
|
|
32
|
+
* Different URL paths can produce the same set of interactive elements
|
|
33
|
+
* (e.g. `/store/` and `/store/all-items/`). Generating hover/click tests
|
|
34
|
+
* for the same elements twice is pure waste, so we deduplicate by the hash
|
|
35
|
+
* of visible actionable-item stable keys.
|
|
36
|
+
*/
|
|
37
|
+
generatedActionableHashes = new Set();
|
|
38
|
+
/**
|
|
39
|
+
* Tracks page-scoped finding keys already recorded during this run.
|
|
40
|
+
* Page-level findings (page-health checks, page-load expectations) describe
|
|
41
|
+
* the page itself, not a specific interaction. Reporting them once per page
|
|
42
|
+
* path is sufficient — duplicating them for every hover/click on the same
|
|
43
|
+
* page just adds noise.
|
|
44
|
+
*/
|
|
45
|
+
reportedPageFindingKeys = new Set();
|
|
46
|
+
/**
|
|
47
|
+
* Generic key-based dedup for findings where text-based matching is too
|
|
48
|
+
* fragile (e.g. page-health titles include variable counts).
|
|
49
|
+
*/
|
|
50
|
+
reportedFindingKeys = new Set();
|
|
30
51
|
/** Check whether generation already happened for a given path in this run. */
|
|
31
52
|
hasGeneratedForPath(path) {
|
|
32
53
|
return this.generatedPaths.has(path);
|
|
33
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Normalize finding text for dedup: strip leading count numbers that vary
|
|
57
|
+
* between evaluations. Preserves URLs, status codes, and other content.
|
|
58
|
+
*
|
|
59
|
+
* "[page-health] 5 broken image(s)" → "[page-health] broken image(s)"
|
|
60
|
+
* "3 significant console warning(s)" → "significant console warning(s)"
|
|
61
|
+
* "Page returned HTTP 404 for …" → unchanged
|
|
62
|
+
*/
|
|
63
|
+
static normalizeFindingText(text) {
|
|
64
|
+
return text.replace(/^(\[[^\]]+\]\s*)\d+\s+/, "$1").replace(/^\d+\s+/, "");
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Returns true if an equivalent page-scoped finding has already been
|
|
68
|
+
* recorded during this run. Both title and description are normalized
|
|
69
|
+
* to strip variable leading counts so that "3 console error(s): …" and
|
|
70
|
+
* "5 console error(s): …" are treated as the same finding.
|
|
71
|
+
*/
|
|
72
|
+
hasReportedPageFinding(_path, title, description) {
|
|
73
|
+
const key = `${PageAnalyzer.normalizeFindingText(title)}\0${PageAnalyzer.normalizeFindingText(description)}`;
|
|
74
|
+
return this.reportedPageFindingKeys.has(key);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Mark a page-scoped finding as recorded so it is not duplicated.
|
|
78
|
+
*/
|
|
79
|
+
markPageFindingReported(_path, title, description) {
|
|
80
|
+
const key = `${PageAnalyzer.normalizeFindingText(title)}\0${PageAnalyzer.normalizeFindingText(description)}`;
|
|
81
|
+
this.reportedPageFindingKeys.add(key);
|
|
82
|
+
}
|
|
83
|
+
/** Check whether a finding with the given stable key has been reported. */
|
|
84
|
+
hasReportedFindingByKey(key) {
|
|
85
|
+
return this.reportedFindingKeys.has(key);
|
|
86
|
+
}
|
|
87
|
+
/** Mark a stable finding key as reported. */
|
|
88
|
+
markReportedFindingByKey(key) {
|
|
89
|
+
this.reportedFindingKeys.add(key);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Check whether full test generation already ran for a page state with the
|
|
93
|
+
* same visible actionable items (by hash).
|
|
94
|
+
*/
|
|
95
|
+
hasGeneratedForActionableHash(hash) {
|
|
96
|
+
return this.generatedActionableHashes.has(hash);
|
|
97
|
+
}
|
|
34
98
|
/**
|
|
35
99
|
* Generate baseline expectations for a test element.
|
|
36
100
|
* Called BEFORE expertises evaluate.
|
|
@@ -192,6 +256,9 @@ export class PageAnalyzer {
|
|
|
192
256
|
currentPageStateId: resolvedContext.currentPageStateId,
|
|
193
257
|
currentPath: resolvedContext.currentPath,
|
|
194
258
|
});
|
|
259
|
+
// Hover-only interactions have their own same-page-state handling inside
|
|
260
|
+
// generateHoverFollowUpCases (including click-follow-up reconciliation),
|
|
261
|
+
// so let them through to that dedicated path.
|
|
195
262
|
if (this.isHoverOnly(testInteraction)) {
|
|
196
263
|
logAnalyzer("generate:hover-only", {
|
|
197
264
|
sourceTitle: testInteraction.title,
|
|
@@ -201,6 +268,19 @@ export class PageAnalyzer {
|
|
|
201
268
|
await generateHoverFollowUpCases(this, testInteraction, resolvedContext);
|
|
202
269
|
return;
|
|
203
270
|
}
|
|
271
|
+
// For non-hover interactions: skip generation when the end page state is
|
|
272
|
+
// the same as the starting page state — the interaction did not cause a
|
|
273
|
+
// meaningful change, so there is nothing new to discover or test.
|
|
274
|
+
if (resolvedContext.beginningPageStateId > 0 &&
|
|
275
|
+
currentPageStateId === resolvedContext.beginningPageStateId) {
|
|
276
|
+
logAnalyzer("generate:same-page-state", {
|
|
277
|
+
sourceTitle: testInteraction.title,
|
|
278
|
+
currentTestInteractionId: resolvedContext.currentTestInteractionId,
|
|
279
|
+
currentPageStateId,
|
|
280
|
+
beginningPageStateId: resolvedContext.beginningPageStateId,
|
|
281
|
+
});
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
204
284
|
// Skip generation if we already generated tests for this path during this
|
|
205
285
|
// run. The check is scoped to the PageAnalyzer instance (one per run) so
|
|
206
286
|
// previous runs on the same runner don't block re-discovery.
|
|
@@ -214,7 +294,23 @@ export class PageAnalyzer {
|
|
|
214
294
|
});
|
|
215
295
|
return;
|
|
216
296
|
}
|
|
297
|
+
// Skip generation if a different path already produced the same set of
|
|
298
|
+
// interactive elements. For example /store/ and /store/all-items/ may
|
|
299
|
+
// resolve to the same product grid — generating hover/click tests for
|
|
300
|
+
// both is redundant.
|
|
301
|
+
const actionableHash = await computeActionableHash(resolvedContext.actionableItems);
|
|
302
|
+
if (this.generatedActionableHashes.has(actionableHash)) {
|
|
303
|
+
logAnalyzer("generate:actionable-items-already-covered", {
|
|
304
|
+
sourceTitle: testInteraction.title,
|
|
305
|
+
currentTestInteractionId: resolvedContext.currentTestInteractionId,
|
|
306
|
+
currentPageStateId: resolvedContext.currentPageStateId,
|
|
307
|
+
currentPath,
|
|
308
|
+
actionableHash,
|
|
309
|
+
});
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
217
312
|
this.generatedPaths.add(currentPath);
|
|
313
|
+
this.generatedActionableHashes.add(actionableHash);
|
|
218
314
|
// If a hover+click navigated to a new page, create a direct navigation
|
|
219
315
|
// interaction and use it as the dependency instead of the hover chain
|
|
220
316
|
let contextForFullPass = resolvedContext;
|