@sudobility/testomniac_runner_service 0.1.36 → 0.1.37
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/api/client.d.ts +60 -1
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +21 -2
- package/dist/api/client.js.map +1 -1
- package/dist/crawler/link-extractor.d.ts +8 -0
- package/dist/crawler/link-extractor.d.ts.map +1 -0
- package/dist/crawler/link-extractor.js +37 -0
- package/dist/crawler/link-extractor.js.map +1 -0
- package/dist/crawler/url-normalizer.d.ts +4 -0
- package/dist/crawler/url-normalizer.d.ts.map +1 -0
- package/dist/crawler/url-normalizer.js +27 -0
- package/dist/crawler/url-normalizer.js.map +1 -0
- package/dist/expertise/accessibility-expertise.d.ts +11 -0
- package/dist/expertise/accessibility-expertise.d.ts.map +1 -0
- package/dist/expertise/accessibility-expertise.js +131 -0
- package/dist/expertise/accessibility-expertise.js.map +1 -0
- package/dist/expertise/content-expertise.d.ts +10 -0
- package/dist/expertise/content-expertise.d.ts.map +1 -0
- package/dist/expertise/content-expertise.js +102 -0
- package/dist/expertise/content-expertise.js.map +1 -0
- package/dist/expertise/index.d.ts +3 -0
- package/dist/expertise/index.d.ts.map +1 -1
- package/dist/expertise/index.js +9 -4
- package/dist/expertise/index.js.map +1 -1
- package/dist/expertise/ui-expertise.d.ts +10 -0
- package/dist/expertise/ui-expertise.d.ts.map +1 -0
- package/dist/expertise/ui-expertise.js +76 -0
- package/dist/expertise/ui-expertise.js.map +1 -0
- package/dist/orchestrator/decomposition.d.ts.map +1 -1
- package/dist/orchestrator/decomposition.js +300 -65
- package/dist/orchestrator/decomposition.js.map +1 -1
- package/dist/orchestrator/direct-navigation.d.ts +4 -0
- package/dist/orchestrator/direct-navigation.d.ts.map +1 -0
- package/dist/orchestrator/direct-navigation.js +47 -0
- package/dist/orchestrator/direct-navigation.js.map +1 -0
- package/dist/orchestrator/discovery.d.ts +10 -0
- package/dist/orchestrator/discovery.d.ts.map +1 -0
- package/dist/orchestrator/discovery.js +77 -0
- package/dist/orchestrator/discovery.js.map +1 -0
- package/dist/orchestrator/expertise.d.ts +5 -0
- package/dist/orchestrator/expertise.d.ts.map +1 -0
- package/dist/orchestrator/expertise.js +157 -0
- package/dist/orchestrator/expertise.js.map +1 -0
- package/dist/orchestrator/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator/orchestrator.js +63 -37
- package/dist/orchestrator/orchestrator.js.map +1 -1
- package/dist/orchestrator/page-capture.d.ts +22 -0
- package/dist/orchestrator/page-capture.d.ts.map +1 -0
- package/dist/orchestrator/page-capture.js +102 -0
- package/dist/orchestrator/page-capture.js.map +1 -0
- package/dist/orchestrator/test-execution.d.ts.map +1 -1
- package/dist/orchestrator/test-execution.js +17 -32
- package/dist/orchestrator/test-execution.js.map +1 -1
- package/dist/orchestrator/types.d.ts +10 -0
- package/dist/orchestrator/types.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"direct-navigation.js","sourceRoot":"","sources":["../../src/orchestrator/direct-navigation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,sBAAsB,GAAG,oBAAoB,CAAC;AAEpD,KAAK,UAAU,2BAA2B,CACxC,GAAc,EACd,MAAkB,EAClB,MAAwB;IAExB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,qBAAqB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,sBAAsB,CAAC,CAAC;IAC9E,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,QAAQ,CAAC,EAAE,CAAC;IACrB,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,EAAE;QACvD,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EAAE,gDAAgD;QAC7D,YAAY,EAAE,GAAG;QACjB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,QAAQ,EAAE,CAAC;QACX,UAAU,EAAE,CAAC,mBAAmB,CAAC;KAC3B,CAAC,CAAC;IACV,MAAM,CAAC,kBAAkB,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IACrE,OAAO,KAAK,CAAC,EAAE,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,GAAc,EACd,MAAkB,EAClB,MAAwB,EACxB,YAAoB;IAEpB,MAAM,OAAO,GAAG,MAAM,2BAA2B,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACvE,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,cAAc,CACvC,MAAM,CAAC,QAAQ,EACf;QACE,KAAK,EAAE,eAAe,YAAY,IAAI,GAAG,EAAE;QAC3C,IAAI,EAAE,YAAY;QAClB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,QAAQ,EAAE,CAAC;QACX,UAAU,EAAE,CAAC,mBAAmB,CAAC;QACjC,YAAY,EAAE,YAAY,IAAI,GAAG;QACjC,KAAK,EAAE,EAAE;QACT,kBAAkB,EAAE,EAAE;KAChB,EACR,OAAO,CACR,CAAC;IAEF,MAAM,eAAe,GAAG,MAAM,GAAG,CAAC,oBAAoB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACpE,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,OAAO;IACT,CAAC;IAED,MAAM,GAAG,CAAC,gBAAgB,CAAC;QACzB,UAAU,EAAE,QAAQ,CAAC,EAAE;QACvB,SAAS,EAAE,CAAC;QACZ,UAAU,EAAE,gBAAgB,CAAC,IAAI;QACjC,IAAI,EAAE,YAAY,IAAI,GAAG;QACzB,cAAc,EAAE,oBAAoB,YAAY,IAAI,GAAG,KAAK;QAC5D,WAAW,EAAE,eAAe,YAAY,IAAI,GAAG,EAAE;QACjD,YAAY,EAAE,EAAE;QAChB,iBAAiB,EAAE,KAAK;KACzB,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BrowserAdapter } from "../adapter";
|
|
2
|
+
import type { ApiClient } from "../api/client";
|
|
3
|
+
import type { ScanConfig, ScanEventHandler } from "./types";
|
|
4
|
+
export interface DiscoveryResult {
|
|
5
|
+
pageIdsByPath: Map<string, number>;
|
|
6
|
+
visitedPaths: Set<string>;
|
|
7
|
+
capturedPaths: Set<string>;
|
|
8
|
+
}
|
|
9
|
+
export declare function discoverPublicPages(adapter: BrowserAdapter, config: ScanConfig, api: ApiClient, events: ScanEventHandler): Promise<DiscoveryResult>;
|
|
10
|
+
//# sourceMappingURL=discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/orchestrator/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAc5D,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC5B;AAED,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,eAAe,CAAC,CAkF1B"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { ensureDirectNavigationCase } from "./direct-navigation";
|
|
2
|
+
import { extractSameOriginLinks } from "../crawler/link-extractor";
|
|
3
|
+
import { toRelativePath } from "../crawler/url-normalizer";
|
|
4
|
+
import { captureCurrentPage } from "./page-capture";
|
|
5
|
+
const LOG = (...args) => console.warn("[discovery]", ...args);
|
|
6
|
+
const MAX_DISCOVERY_PAGES = 25;
|
|
7
|
+
function checkAbort(signal) {
|
|
8
|
+
if (signal?.aborted)
|
|
9
|
+
throw new Error("Scan aborted");
|
|
10
|
+
}
|
|
11
|
+
export async function discoverPublicPages(adapter, config, api, events) {
|
|
12
|
+
const queue = [config.scanUrl];
|
|
13
|
+
const visitedPaths = new Set();
|
|
14
|
+
const pageIdsByPath = new Map();
|
|
15
|
+
const capturedPaths = new Set();
|
|
16
|
+
while (queue.length > 0 && visitedPaths.size < MAX_DISCOVERY_PAGES) {
|
|
17
|
+
checkAbort(config.signal);
|
|
18
|
+
const nextUrl = queue.shift();
|
|
19
|
+
if (!nextUrl)
|
|
20
|
+
break;
|
|
21
|
+
LOG(`Visiting ${nextUrl}`);
|
|
22
|
+
try {
|
|
23
|
+
await adapter.goto(nextUrl, { waitUntil: "networkidle0" });
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
const relativePath = toRelativePath(nextUrl);
|
|
27
|
+
if (config.testEnvironmentId) {
|
|
28
|
+
await api.createPageVisit({
|
|
29
|
+
testRunId: config.scanId,
|
|
30
|
+
testEnvironmentId: config.testEnvironmentId,
|
|
31
|
+
relativePath,
|
|
32
|
+
status: "failed",
|
|
33
|
+
errorMessage: error instanceof Error ? error.message : "Navigation failed",
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const currentUrl = await adapter.getUrl();
|
|
39
|
+
const relativePath = toRelativePath(currentUrl);
|
|
40
|
+
if (visitedPaths.has(relativePath)) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
visitedPaths.add(relativePath);
|
|
44
|
+
const page = await api.findOrCreatePage(config.runnerId, relativePath);
|
|
45
|
+
pageIdsByPath.set(relativePath, page.id);
|
|
46
|
+
await ensureDirectNavigationCase(api, config, events, relativePath);
|
|
47
|
+
const captureResult = await captureCurrentPage(adapter, config, api, events, {
|
|
48
|
+
testRunId: config.scanId,
|
|
49
|
+
markDiscovered: true,
|
|
50
|
+
captureState: relativePath !== toRelativePath(config.scanUrl),
|
|
51
|
+
createDecompositionJob: relativePath !== toRelativePath(config.scanUrl),
|
|
52
|
+
});
|
|
53
|
+
if (captureResult?.createdNewState) {
|
|
54
|
+
capturedPaths.add(relativePath);
|
|
55
|
+
}
|
|
56
|
+
const discoveredLinks = await extractSameOriginLinks(adapter, config.baseUrl);
|
|
57
|
+
LOG(`Discovered ${discoveredLinks.length} links on ${relativePath}`);
|
|
58
|
+
if (config.testEnvironmentId && discoveredLinks.length > 0) {
|
|
59
|
+
await api.createDiscoveredPages({
|
|
60
|
+
testEnvironmentId: config.testEnvironmentId,
|
|
61
|
+
pages: discoveredLinks.map(link => ({
|
|
62
|
+
relativePath: link.relativePath,
|
|
63
|
+
sourcePagePath: relativePath,
|
|
64
|
+
sourceLabel: link.label,
|
|
65
|
+
isPublic: true,
|
|
66
|
+
})),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
for (const link of discoveredLinks) {
|
|
70
|
+
if (!visitedPaths.has(link.relativePath)) {
|
|
71
|
+
queue.push(link.url);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return { pageIdsByPath, visitedPaths, capturedPaths };
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/orchestrator/discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { BrowserAdapter } from "../adapter";
|
|
2
|
+
import type { ApiClient } from "../api/client";
|
|
3
|
+
import type { ScanConfig, ScanEventHandler } from "./types";
|
|
4
|
+
export declare function executePageExpertises(adapter: BrowserAdapter, config: ScanConfig, api: ApiClient, events: ScanEventHandler, pageStateId: number, pageId: number, relativePath: string): Promise<void>;
|
|
5
|
+
//# sourceMappingURL=expertise.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expertise.d.ts","sourceRoot":"","sources":["../../src/orchestrator/expertise.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI/C,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAmG5D,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,gBAAgB,EACxB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CA4Gf"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { ExpectationType } from "../domain/types";
|
|
2
|
+
import { createDefaultExpertises } from "../expertise";
|
|
3
|
+
import { detectScaffoldRegions } from "../scanner/component-detector";
|
|
4
|
+
import { detectPatternsWithInstances } from "../scanner/pattern-detector";
|
|
5
|
+
const EXPERTISE_PREFIX = "Expertise:";
|
|
6
|
+
function buildDefaultExpectations() {
|
|
7
|
+
return [
|
|
8
|
+
{
|
|
9
|
+
expectationType: ExpectationType.PageLoaded,
|
|
10
|
+
description: "Page should load successfully",
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
expectationType: ExpectationType.NoConsoleErrors,
|
|
14
|
+
description: "Page should not produce console errors",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
expectationType: ExpectationType.NoNetworkErrors,
|
|
18
|
+
description: "Page should not produce network errors",
|
|
19
|
+
},
|
|
20
|
+
];
|
|
21
|
+
}
|
|
22
|
+
function normalizeOutcomes(outcomes) {
|
|
23
|
+
const expectedOutcome = outcomes.length > 0
|
|
24
|
+
? outcomes.map(item => item.expected).join("\n")
|
|
25
|
+
: undefined;
|
|
26
|
+
const observedOutcome = outcomes.length > 0
|
|
27
|
+
? outcomes.map(item => `[${item.result}] ${item.observed}`).join("\n")
|
|
28
|
+
: undefined;
|
|
29
|
+
const hasErrors = outcomes.some(item => item.result === "error");
|
|
30
|
+
return {
|
|
31
|
+
expectedOutcome,
|
|
32
|
+
observedOutcome,
|
|
33
|
+
status: hasErrors ? "failed" : "completed",
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
async function ensureExpertiseSuite(api, config, events, expertiseName) {
|
|
37
|
+
const title = `${EXPERTISE_PREFIX} ${expertiseName}`;
|
|
38
|
+
const suites = await api.getTestSuitesByRunner(config.runnerId);
|
|
39
|
+
const existing = suites.find(suite => suite.title === title);
|
|
40
|
+
if (existing) {
|
|
41
|
+
return existing.id;
|
|
42
|
+
}
|
|
43
|
+
const created = await api.insertTestSuite(config.runnerId, {
|
|
44
|
+
title,
|
|
45
|
+
description: `Auto-generated expertise suite for ${expertiseName} findings`,
|
|
46
|
+
startingPath: "/",
|
|
47
|
+
sizeClass: config.sizeClass,
|
|
48
|
+
priority: 2,
|
|
49
|
+
suite_tags: ["expertise", expertiseName],
|
|
50
|
+
});
|
|
51
|
+
events.onTestSuiteCreated({ suiteId: created.id, title: created.title });
|
|
52
|
+
return created.id;
|
|
53
|
+
}
|
|
54
|
+
async function ensureExpertiseCase(api, config, suiteId, expertiseName, pageStateId, pageId, relativePath) {
|
|
55
|
+
const testCase = await api.insertTestCase(config.runnerId, {
|
|
56
|
+
title: `${expertiseName}: ${relativePath || "/"}`,
|
|
57
|
+
type: "render",
|
|
58
|
+
sizeClass: config.sizeClass,
|
|
59
|
+
suite_tags: ["expertise", expertiseName],
|
|
60
|
+
page_id: pageId,
|
|
61
|
+
priority: 2,
|
|
62
|
+
startingPageStateId: pageStateId,
|
|
63
|
+
startingPath: relativePath || "/",
|
|
64
|
+
steps: [],
|
|
65
|
+
globalExpectations: [],
|
|
66
|
+
}, suiteId);
|
|
67
|
+
return testCase.id;
|
|
68
|
+
}
|
|
69
|
+
export async function executePageExpertises(adapter, config, api, events, pageStateId, pageId, relativePath) {
|
|
70
|
+
const html = await adapter.content();
|
|
71
|
+
const scaffolds = await detectScaffoldRegions(adapter);
|
|
72
|
+
const patterns = await detectPatternsWithInstances(adapter);
|
|
73
|
+
const context = {
|
|
74
|
+
html,
|
|
75
|
+
scaffolds,
|
|
76
|
+
patterns,
|
|
77
|
+
consoleLogs: [],
|
|
78
|
+
networkLogs: [],
|
|
79
|
+
expectations: buildDefaultExpectations(),
|
|
80
|
+
};
|
|
81
|
+
const expertises = createDefaultExpertises();
|
|
82
|
+
for (const expertise of expertises) {
|
|
83
|
+
const suiteId = await ensureExpertiseSuite(api, config, events, expertise.name);
|
|
84
|
+
const testCaseId = await ensureExpertiseCase(api, config, suiteId, expertise.name, pageStateId, pageId, relativePath);
|
|
85
|
+
const testCaseRun = await api.createTestCaseRun({ testCaseId });
|
|
86
|
+
const testRun = await api.createTestRun({
|
|
87
|
+
runnerId: config.runnerId,
|
|
88
|
+
testCaseRunId: testCaseRun.id,
|
|
89
|
+
testEnvironmentId: config.testEnvironmentId,
|
|
90
|
+
parentTestRunId: config.scanId,
|
|
91
|
+
rootTestRunId: config.scanId,
|
|
92
|
+
sizeClass: config.sizeClass,
|
|
93
|
+
runnerInstanceId: config.runnerInstanceId,
|
|
94
|
+
runnerInstanceName: config.runnerInstanceName,
|
|
95
|
+
});
|
|
96
|
+
const startedAt = Date.now();
|
|
97
|
+
try {
|
|
98
|
+
const outcomes = expertise.evaluate(context);
|
|
99
|
+
const { expectedOutcome, observedOutcome, status } = normalizeOutcomes(outcomes);
|
|
100
|
+
for (const outcome of outcomes) {
|
|
101
|
+
if (outcome.result === "warning" || outcome.result === "error") {
|
|
102
|
+
await api.createTestRunFinding({
|
|
103
|
+
testCaseRunId: testCaseRun.id,
|
|
104
|
+
type: outcome.result === "error" ? "error" : "warning",
|
|
105
|
+
title: `[${expertise.name}] ${outcome.expected}`,
|
|
106
|
+
description: outcome.observed,
|
|
107
|
+
});
|
|
108
|
+
events.onFindingCreated({
|
|
109
|
+
type: outcome.result,
|
|
110
|
+
title: `[${expertise.name}] ${outcome.expected}`,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
await api.completeTestCaseRun(testCaseRun.id, {
|
|
115
|
+
status,
|
|
116
|
+
durationMs: Date.now() - startedAt,
|
|
117
|
+
expectedOutcome,
|
|
118
|
+
observedOutcome,
|
|
119
|
+
});
|
|
120
|
+
await api.completeTestRun(testRun.id, {
|
|
121
|
+
status,
|
|
122
|
+
totalDurationMs: Date.now() - startedAt,
|
|
123
|
+
});
|
|
124
|
+
events.onTestRunCompleted({
|
|
125
|
+
testRunId: testRun.id,
|
|
126
|
+
passed: status !== "failed",
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
const message = error instanceof Error ? error.message : "Expertise evaluation failed";
|
|
131
|
+
await api.completeTestCaseRun(testCaseRun.id, {
|
|
132
|
+
status: "failed",
|
|
133
|
+
durationMs: Date.now() - startedAt,
|
|
134
|
+
errorMessage: message,
|
|
135
|
+
});
|
|
136
|
+
await api.completeTestRun(testRun.id, {
|
|
137
|
+
status: "failed",
|
|
138
|
+
totalDurationMs: Date.now() - startedAt,
|
|
139
|
+
});
|
|
140
|
+
await api.createTestRunFinding({
|
|
141
|
+
testCaseRunId: testCaseRun.id,
|
|
142
|
+
type: "error",
|
|
143
|
+
title: `[${expertise.name}] expertise execution failed`,
|
|
144
|
+
description: message,
|
|
145
|
+
});
|
|
146
|
+
events.onFindingCreated({
|
|
147
|
+
type: "error",
|
|
148
|
+
title: `[${expertise.name}] expertise execution failed`,
|
|
149
|
+
});
|
|
150
|
+
events.onTestRunCompleted({
|
|
151
|
+
testRunId: testRun.id,
|
|
152
|
+
passed: false,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=expertise.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expertise.js","sourceRoot":"","sources":["../../src/orchestrator/expertise.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/orchestrator/orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/orchestrator/orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AA6CxE,wBAAsB,OAAO,CAC3B,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,SAAS,EACd,YAAY,EAAE,gBAAgB,GAC7B,OAAO,CAAC,UAAU,CAAC,CA2LrB"}
|
|
@@ -1,14 +1,38 @@
|
|
|
1
|
+
import { discoverPublicPages } from "./discovery";
|
|
1
2
|
import { processDecompositionJob } from "./decomposition";
|
|
2
3
|
import { executeTestCases } from "./test-execution";
|
|
3
|
-
import {
|
|
4
|
-
import { extractActionableItems } from "../extractors";
|
|
4
|
+
import { captureCurrentPage, resetCapturedPagePaths } from "./page-capture";
|
|
5
5
|
const LOG = (...args) => console.warn("[orchestrator]", ...args);
|
|
6
|
+
function buildAiSummary(pagesFound, pageStatesFound, testRunsCompleted, findingsFound, expertiseSummary) {
|
|
7
|
+
const expertiseLines = Object.entries(expertiseSummary)
|
|
8
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
9
|
+
.map(([name, counts]) => {
|
|
10
|
+
const parts = [];
|
|
11
|
+
if (counts.errors > 0)
|
|
12
|
+
parts.push(`${counts.errors} error${counts.errors === 1 ? "" : "s"}`);
|
|
13
|
+
if (counts.warnings > 0) {
|
|
14
|
+
parts.push(`${counts.warnings} warning${counts.warnings === 1 ? "" : "s"}`);
|
|
15
|
+
}
|
|
16
|
+
return parts.length > 0
|
|
17
|
+
? `${name}: ${parts.join(", ")}`
|
|
18
|
+
: `${name}: no findings`;
|
|
19
|
+
});
|
|
20
|
+
const headline = findingsFound === 0
|
|
21
|
+
? `Scan completed with no findings across ${pagesFound} page${pagesFound === 1 ? "" : "s"}.`
|
|
22
|
+
: `Scan completed with ${findingsFound} finding${findingsFound === 1 ? "" : "s"} across ${pagesFound} page${pagesFound === 1 ? "" : "s"}.`;
|
|
23
|
+
const detail = `Captured ${pageStatesFound} page state${pageStatesFound === 1 ? "" : "s"} and completed ${testRunsCompleted} test run${testRunsCompleted === 1 ? "" : "s"}.`;
|
|
24
|
+
if (expertiseLines.length === 0) {
|
|
25
|
+
return `${headline} ${detail}`;
|
|
26
|
+
}
|
|
27
|
+
return `${headline} ${detail} Findings by expertise: ${expertiseLines.join("; ")}.`;
|
|
28
|
+
}
|
|
6
29
|
export async function runScan(adapter, config, api, eventHandler) {
|
|
7
30
|
const startTime = Date.now();
|
|
8
31
|
let pagesFound = 0;
|
|
9
32
|
let pageStatesFound = 0;
|
|
10
33
|
let testRunsCompleted = 0;
|
|
11
34
|
let findingsFound = 0;
|
|
35
|
+
const expertiseSummary = {};
|
|
12
36
|
const wrappedHandler = {
|
|
13
37
|
...eventHandler,
|
|
14
38
|
onPageFound(page) {
|
|
@@ -28,6 +52,21 @@ export async function runScan(adapter, config, api, eventHandler) {
|
|
|
28
52
|
},
|
|
29
53
|
onFindingCreated(finding) {
|
|
30
54
|
findingsFound++;
|
|
55
|
+
const match = /^\[([^\]]+)\]/.exec(finding.title);
|
|
56
|
+
if (match?.[1]) {
|
|
57
|
+
const expertiseName = match[1];
|
|
58
|
+
const counts = expertiseSummary[expertiseName] ?? {
|
|
59
|
+
warnings: 0,
|
|
60
|
+
errors: 0,
|
|
61
|
+
};
|
|
62
|
+
if (finding.type === "error") {
|
|
63
|
+
counts.errors += 1;
|
|
64
|
+
}
|
|
65
|
+
else if (finding.type === "warning") {
|
|
66
|
+
counts.warnings += 1;
|
|
67
|
+
}
|
|
68
|
+
expertiseSummary[expertiseName] = counts;
|
|
69
|
+
}
|
|
31
70
|
eventHandler.onFindingCreated(finding);
|
|
32
71
|
emitStats();
|
|
33
72
|
},
|
|
@@ -41,42 +80,23 @@ export async function runScan(adapter, config, api, eventHandler) {
|
|
|
41
80
|
});
|
|
42
81
|
}
|
|
43
82
|
try {
|
|
44
|
-
|
|
45
|
-
|
|
83
|
+
resetCapturedPagePaths();
|
|
84
|
+
// 1. Crawl the site from the scan URL to inventory public pages
|
|
85
|
+
LOG(`Step 1: Discovering pages from ${config.scanUrl}`);
|
|
86
|
+
await discoverPublicPages(adapter, config, api, wrappedHandler);
|
|
87
|
+
// 2. Navigate back to scan URL and capture initial page state
|
|
88
|
+
LOG(`Step 2: Navigating to ${config.scanUrl}`);
|
|
46
89
|
await adapter.goto(config.scanUrl, { waitUntil: "networkidle0" });
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const relativePath = scanUrlObj.pathname;
|
|
52
|
-
const page = await api.findOrCreatePage(config.runnerId, relativePath);
|
|
53
|
-
LOG(`Page created/found: id=${page.id}, path=${relativePath}`);
|
|
54
|
-
wrappedHandler.onPageFound({ relativePath, pageId: page.id });
|
|
55
|
-
// Extract actionable items and compute hashes
|
|
56
|
-
const items = await extractActionableItems(adapter);
|
|
57
|
-
LOG(`Extracted ${items.length} actionable items from page`);
|
|
58
|
-
const hashes = await computeHashes(initialHtml, items);
|
|
59
|
-
LOG(`Computed hashes:`, hashes);
|
|
60
|
-
const initialPageState = await api.createPageState({
|
|
61
|
-
pageId: page.id,
|
|
62
|
-
sizeClass: config.sizeClass,
|
|
63
|
-
hashes,
|
|
64
|
-
screenshotPath: undefined,
|
|
65
|
-
contentText: initialHtml.slice(0, 5000),
|
|
66
|
-
});
|
|
67
|
-
LOG(`Created page state: id=${initialPageState.id}`);
|
|
68
|
-
wrappedHandler.onPageStateCreated({
|
|
69
|
-
pageStateId: initialPageState.id,
|
|
70
|
-
pageId: page.id,
|
|
71
|
-
});
|
|
72
|
-
// 2. Create initial AI Decomposition Job
|
|
73
|
-
const initialJob = await api.createDecompositionJob(config.scanId, initialPageState.id);
|
|
74
|
-
LOG(`Created decomposition job: id=${initialJob.id}`);
|
|
75
|
-
wrappedHandler.onDecompositionJobCreated({
|
|
76
|
-
jobId: initialJob.id,
|
|
77
|
-
pageStateId: initialPageState.id,
|
|
90
|
+
const initialCapture = await captureCurrentPage(adapter, config, api, wrappedHandler, {
|
|
91
|
+
testRunId: config.scanId,
|
|
92
|
+
markDiscovered: false,
|
|
93
|
+
createDecompositionJob: true,
|
|
78
94
|
});
|
|
79
|
-
|
|
95
|
+
if (!initialCapture?.pageStateId) {
|
|
96
|
+
throw new Error("Failed to capture initial page state");
|
|
97
|
+
}
|
|
98
|
+
LOG(`Captured initial page state ${initialCapture.pageStateId} for ${initialCapture.relativePath}`);
|
|
99
|
+
// 4. Generate/Run loop
|
|
80
100
|
let iteration = 0;
|
|
81
101
|
const MAX_ITERATIONS = 50;
|
|
82
102
|
while (iteration < MAX_ITERATIONS) {
|
|
@@ -113,10 +133,12 @@ export async function runScan(adapter, config, api, eventHandler) {
|
|
|
113
133
|
}
|
|
114
134
|
LOG("New pages discovered — continuing to next iteration");
|
|
115
135
|
}
|
|
116
|
-
//
|
|
136
|
+
// 5. Complete test run
|
|
117
137
|
const durationMs = Date.now() - startTime;
|
|
138
|
+
const aiSummary = buildAiSummary(pagesFound, pageStatesFound, testRunsCompleted, findingsFound, expertiseSummary);
|
|
118
139
|
await api.completeTestRun(config.scanId, {
|
|
119
140
|
status: "completed",
|
|
141
|
+
aiSummary,
|
|
120
142
|
totalDurationMs: durationMs,
|
|
121
143
|
pagesFound,
|
|
122
144
|
pageStatesFound,
|
|
@@ -129,11 +151,15 @@ export async function runScan(adapter, config, api, eventHandler) {
|
|
|
129
151
|
testRunsCompleted,
|
|
130
152
|
findingsFound,
|
|
131
153
|
durationMs,
|
|
154
|
+
aiSummary,
|
|
155
|
+
expertiseSummary,
|
|
132
156
|
};
|
|
133
157
|
wrappedHandler.onScanComplete({
|
|
134
158
|
totalPages: pagesFound,
|
|
135
159
|
totalFindings: findingsFound,
|
|
136
160
|
durationMs,
|
|
161
|
+
aiSummary,
|
|
162
|
+
expertiseSummary,
|
|
137
163
|
});
|
|
138
164
|
return result;
|
|
139
165
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/orchestrator/orchestrator.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/orchestrator/orchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { BrowserAdapter } from "../adapter";
|
|
2
|
+
import type { ApiClient } from "../api/client";
|
|
3
|
+
import type { ScanConfig, ScanEventHandler } from "./types";
|
|
4
|
+
export interface CapturePageOptions {
|
|
5
|
+
testRunId?: number;
|
|
6
|
+
markDiscovered?: boolean;
|
|
7
|
+
captureState?: boolean;
|
|
8
|
+
createDecompositionJob?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface CapturePageResult {
|
|
11
|
+
pageId: number;
|
|
12
|
+
relativePath: string;
|
|
13
|
+
pageStateId?: number;
|
|
14
|
+
decompositionJobId?: number;
|
|
15
|
+
createdNewState: boolean;
|
|
16
|
+
matchedExistingState: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function resetCapturedPagePaths(): void;
|
|
19
|
+
export declare function seedCapturedPagePath(relativePath: string): void;
|
|
20
|
+
export declare function hasCapturedPagePath(relativePath: string): boolean;
|
|
21
|
+
export declare function captureCurrentPage(adapter: BrowserAdapter, config: ScanConfig, api: ApiClient, events: ScanEventHandler, options?: CapturePageOptions): Promise<CapturePageResult | null>;
|
|
22
|
+
//# sourceMappingURL=page-capture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-capture.d.ts","sourceRoot":"","sources":["../../src/orchestrator/page-capture.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAM5D,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,OAAO,CAAC;IACzB,oBAAoB,EAAE,OAAO,CAAC;CAC/B;AAID,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C;AAED,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAE/D;AAED,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,gBAAgB,EACxB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAgHnC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { computeHashes } from "../browser/page-utils";
|
|
2
|
+
import { toRelativePath } from "../crawler/url-normalizer";
|
|
3
|
+
import { extractActionableItems } from "../extractors";
|
|
4
|
+
import { executePageExpertises } from "./expertise";
|
|
5
|
+
const capturedPagePaths = new Set();
|
|
6
|
+
export function resetCapturedPagePaths() {
|
|
7
|
+
capturedPagePaths.clear();
|
|
8
|
+
}
|
|
9
|
+
export function seedCapturedPagePath(relativePath) {
|
|
10
|
+
capturedPagePaths.add(relativePath);
|
|
11
|
+
}
|
|
12
|
+
export function hasCapturedPagePath(relativePath) {
|
|
13
|
+
return capturedPagePaths.has(relativePath);
|
|
14
|
+
}
|
|
15
|
+
export async function captureCurrentPage(adapter, config, api, events, options = {}) {
|
|
16
|
+
const currentUrl = await adapter.getUrl();
|
|
17
|
+
const current = new URL(currentUrl);
|
|
18
|
+
const base = new URL(config.baseUrl);
|
|
19
|
+
if (current.origin !== base.origin) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
const relativePath = toRelativePath(currentUrl);
|
|
23
|
+
const page = await api.findOrCreatePage(config.runnerId, relativePath);
|
|
24
|
+
if (options.markDiscovered) {
|
|
25
|
+
events.onPageFound({ relativePath, pageId: page.id });
|
|
26
|
+
if (config.testEnvironmentId) {
|
|
27
|
+
await api.createDiscoveredPages({
|
|
28
|
+
testEnvironmentId: config.testEnvironmentId,
|
|
29
|
+
pages: [{ relativePath, isPublic: true }],
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
if (config.testEnvironmentId && options.testRunId) {
|
|
33
|
+
await api.createPageVisit({
|
|
34
|
+
testRunId: options.testRunId,
|
|
35
|
+
testEnvironmentId: config.testEnvironmentId,
|
|
36
|
+
relativePath,
|
|
37
|
+
status: "visited",
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (hasCapturedPagePath(relativePath)) {
|
|
42
|
+
return {
|
|
43
|
+
pageId: page.id,
|
|
44
|
+
relativePath,
|
|
45
|
+
createdNewState: false,
|
|
46
|
+
matchedExistingState: false,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
if (options.captureState === false) {
|
|
50
|
+
return {
|
|
51
|
+
pageId: page.id,
|
|
52
|
+
relativePath,
|
|
53
|
+
createdNewState: false,
|
|
54
|
+
matchedExistingState: false,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const html = await adapter.content();
|
|
58
|
+
const items = await extractActionableItems(adapter);
|
|
59
|
+
const hashes = await computeHashes(html, items);
|
|
60
|
+
const existingState = await api.findMatchingPageState(page.id, hashes, config.sizeClass);
|
|
61
|
+
if (existingState) {
|
|
62
|
+
seedCapturedPagePath(relativePath);
|
|
63
|
+
return {
|
|
64
|
+
pageId: page.id,
|
|
65
|
+
relativePath,
|
|
66
|
+
pageStateId: existingState.id,
|
|
67
|
+
createdNewState: false,
|
|
68
|
+
matchedExistingState: true,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const pageState = await api.createPageState({
|
|
72
|
+
pageId: page.id,
|
|
73
|
+
sizeClass: config.sizeClass,
|
|
74
|
+
hashes,
|
|
75
|
+
contentText: html.slice(0, 5000),
|
|
76
|
+
createdByTestRunId: options.testRunId,
|
|
77
|
+
});
|
|
78
|
+
seedCapturedPagePath(relativePath);
|
|
79
|
+
events.onPageStateCreated({
|
|
80
|
+
pageStateId: pageState.id,
|
|
81
|
+
pageId: page.id,
|
|
82
|
+
});
|
|
83
|
+
await executePageExpertises(adapter, config, api, events, pageState.id, page.id, relativePath);
|
|
84
|
+
let decompositionJobId;
|
|
85
|
+
if (options.createDecompositionJob) {
|
|
86
|
+
const job = await api.createDecompositionJob(config.scanId, pageState.id);
|
|
87
|
+
decompositionJobId = job.id;
|
|
88
|
+
events.onDecompositionJobCreated({
|
|
89
|
+
jobId: job.id,
|
|
90
|
+
pageStateId: pageState.id,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
pageId: page.id,
|
|
95
|
+
relativePath,
|
|
96
|
+
pageStateId: pageState.id,
|
|
97
|
+
decompositionJobId,
|
|
98
|
+
createdNewState: true,
|
|
99
|
+
matchedExistingState: false,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=page-capture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-capture.js","sourceRoot":"","sources":["../../src/orchestrator/page-capture.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-execution.d.ts","sourceRoot":"","sources":["../../src/orchestrator/test-execution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"test-execution.d.ts","sourceRoot":"","sources":["../../src/orchestrator/test-execution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAiI5D,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,cAAc,EACvB,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,gBAAgB,EACxB,WAAW,EAAE,MAAM,EAAE,GACpB,OAAO,CAAC,OAAO,CAAC,CA0NlB"}
|