@qa-ai-stlc/explorer 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accessibility-tree.d.ts +14 -0
- package/dist/accessibility-tree.d.ts.map +1 -0
- package/dist/accessibility-tree.js +73 -0
- package/dist/accessibility-tree.js.map +1 -0
- package/dist/analyze-page.d.ts +10 -0
- package/dist/analyze-page.d.ts.map +1 -0
- package/dist/analyze-page.js +25 -0
- package/dist/analyze-page.js.map +1 -0
- package/dist/analyze-pages.d.ts +24 -0
- package/dist/analyze-pages.d.ts.map +1 -0
- package/dist/analyze-pages.js +42 -0
- package/dist/analyze-pages.js.map +1 -0
- package/dist/crawl.d.ts +3 -7
- package/dist/crawl.d.ts.map +1 -1
- package/dist/crawl.js +4 -13
- package/dist/crawl.js.map +1 -1
- package/dist/identity.d.ts +11 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +13 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/normalize.d.ts +25 -0
- package/dist/normalize.d.ts.map +1 -0
- package/dist/normalize.js +31 -0
- package/dist/normalize.js.map +1 -0
- package/dist/page-elements.d.ts +13 -0
- package/dist/page-elements.d.ts.map +1 -0
- package/dist/page-elements.js +164 -0
- package/dist/page-elements.js.map +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AccessibilityNode } from '@qa-ai-stlc/schemas';
|
|
2
|
+
import { type NormalizeLimits } from './normalize.js';
|
|
3
|
+
export interface NormalizedAccessibilityTree {
|
|
4
|
+
readonly tree: AccessibilityNode;
|
|
5
|
+
readonly truncated: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Turns the free-form JSON `AuthPage.ariaSnapshotJSON()` returns into a capped
|
|
9
|
+
* `AccessibilityNode` tree. The input is untrusted, page-derived data (development plan section
|
|
10
|
+
* 2.6): every field is read defensively, string fields are length-capped, and the total node
|
|
11
|
+
* count is capped so one page can never grow the artifact — or an agent's context — unbounded.
|
|
12
|
+
*/
|
|
13
|
+
export declare function normalizeAccessibilityTree(raw: unknown, limits?: NormalizeLimits): NormalizedAccessibilityTree;
|
|
14
|
+
//# sourceMappingURL=accessibility-tree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accessibility-tree.d.ts","sourceRoot":"","sources":["../src/accessibility-tree.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAA0C,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAO9F,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,OAAO,EACZ,MAAM,GAAE,eAA0C,GACjD,2BAA2B,CA+D7B"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Copyright The QA-AI-STLC Authors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { DEFAULT_NORMALIZE_LIMITS, truncateText } from './normalize.js';
|
|
4
|
+
const FALLBACK_ROLE = 'generic';
|
|
5
|
+
const TEXT_ROLE = 'text';
|
|
6
|
+
const ROOT_ROLE = 'root';
|
|
7
|
+
const BOOLEAN_FLAGS = ['checked', 'disabled', 'expanded', 'pressed', 'selected'];
|
|
8
|
+
/**
|
|
9
|
+
* Turns the free-form JSON `AuthPage.ariaSnapshotJSON()` returns into a capped
|
|
10
|
+
* `AccessibilityNode` tree. The input is untrusted, page-derived data (development plan section
|
|
11
|
+
* 2.6): every field is read defensively, string fields are length-capped, and the total node
|
|
12
|
+
* count is capped so one page can never grow the artifact — or an agent's context — unbounded.
|
|
13
|
+
*/
|
|
14
|
+
export function normalizeAccessibilityTree(raw, limits = DEFAULT_NORMALIZE_LIMITS) {
|
|
15
|
+
let nodeCount = 0;
|
|
16
|
+
let truncated = false;
|
|
17
|
+
function normalizeText(text) {
|
|
18
|
+
const result = truncateText(text, limits);
|
|
19
|
+
if (result.truncated) {
|
|
20
|
+
truncated = true;
|
|
21
|
+
}
|
|
22
|
+
return result.text;
|
|
23
|
+
}
|
|
24
|
+
function visit(node) {
|
|
25
|
+
nodeCount += 1;
|
|
26
|
+
if (nodeCount > limits.maxTreeNodes) {
|
|
27
|
+
truncated = true;
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
// A static text fragment is serialized as a bare string, not an object with role: "text"
|
|
31
|
+
// (Playwright's own `ariaSnapshotJSON` format).
|
|
32
|
+
if (typeof node === 'string') {
|
|
33
|
+
return { role: TEXT_ROLE, text: normalizeText(node) };
|
|
34
|
+
}
|
|
35
|
+
const record = typeof node === 'object' && node !== null && !Array.isArray(node)
|
|
36
|
+
? node
|
|
37
|
+
: {};
|
|
38
|
+
const result = { role: typeof record.role === 'string' ? record.role : FALLBACK_ROLE };
|
|
39
|
+
if (typeof record.name === 'string') {
|
|
40
|
+
result.name = normalizeText(record.name);
|
|
41
|
+
}
|
|
42
|
+
if (typeof record.text === 'string') {
|
|
43
|
+
result.text = normalizeText(record.text);
|
|
44
|
+
}
|
|
45
|
+
for (const flag of BOOLEAN_FLAGS) {
|
|
46
|
+
if (typeof record[flag] === 'boolean') {
|
|
47
|
+
result[flag] = record[flag];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (Array.isArray(record.children)) {
|
|
51
|
+
const children = record.children
|
|
52
|
+
.map(visit)
|
|
53
|
+
.filter((child) => child !== undefined);
|
|
54
|
+
if (children.length > 0) {
|
|
55
|
+
result.children = children;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
// `ariaSnapshotJSON()` returns a *list* of root-level nodes, not one root object; a
|
|
61
|
+
// single-element list is unwrapped, and a multi-element one gets a synthetic root so the
|
|
62
|
+
// schema's single `accessibilityTree` field always has exactly one tree to hold.
|
|
63
|
+
// `Array.isArray` narrows to `any[]`, so the elements are re-typed `unknown` explicitly.
|
|
64
|
+
const rootNodes = Array.isArray(raw) ? raw : undefined;
|
|
65
|
+
const rootInput = rootNodes === undefined
|
|
66
|
+
? raw
|
|
67
|
+
: rootNodes.length === 1
|
|
68
|
+
? rootNodes[0]
|
|
69
|
+
: { role: ROOT_ROLE, children: rootNodes };
|
|
70
|
+
const tree = visit(rootInput) ?? { role: FALLBACK_ROLE };
|
|
71
|
+
return { tree, truncated };
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=accessibility-tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accessibility-tree.js","sourceRoot":"","sources":["../src/accessibility-tree.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AuthPage } from '@qa-ai-stlc/core';
|
|
2
|
+
import type { PageModel } from '@qa-ai-stlc/schemas';
|
|
3
|
+
import { type NormalizeLimits } from './normalize.js';
|
|
4
|
+
/**
|
|
5
|
+
* Builds a `PageModel` for the page `page` is currently showing: its accessibility tree,
|
|
6
|
+
* interactive elements, forms, tables and dialogs, all length- and count-capped (development plan
|
|
7
|
+
* section 2.6). Does not navigate; the caller decides which URL is current.
|
|
8
|
+
*/
|
|
9
|
+
export declare function analyzePage(page: AuthPage, url: string, limits?: NormalizeLimits): Promise<PageModel>;
|
|
10
|
+
//# sourceMappingURL=analyze-page.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-page.d.ts","sourceRoot":"","sources":["../src/analyze-page.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAA4B,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGhF;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,QAAQ,EACd,GAAG,EAAE,MAAM,EACX,MAAM,GAAE,eAA0C,GACjD,OAAO,CAAC,SAAS,CAAC,CAiBpB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Copyright The QA-AI-STLC Authors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { normalizeAccessibilityTree } from './accessibility-tree.js';
|
|
4
|
+
import { DEFAULT_NORMALIZE_LIMITS } from './normalize.js';
|
|
5
|
+
import { extractPageElements } from './page-elements.js';
|
|
6
|
+
/**
|
|
7
|
+
* Builds a `PageModel` for the page `page` is currently showing: its accessibility tree,
|
|
8
|
+
* interactive elements, forms, tables and dialogs, all length- and count-capped (development plan
|
|
9
|
+
* section 2.6). Does not navigate; the caller decides which URL is current.
|
|
10
|
+
*/
|
|
11
|
+
export async function analyzePage(page, url, limits = DEFAULT_NORMALIZE_LIMITS) {
|
|
12
|
+
const rawAccessibilityTree = await page.ariaSnapshotJSON();
|
|
13
|
+
const { tree, truncated: accessibilityTruncated } = normalizeAccessibilityTree(rawAccessibilityTree, limits);
|
|
14
|
+
const elements = await extractPageElements(page, limits);
|
|
15
|
+
return {
|
|
16
|
+
url,
|
|
17
|
+
accessibilityTree: tree,
|
|
18
|
+
interactiveElements: elements.interactiveElements,
|
|
19
|
+
forms: elements.forms,
|
|
20
|
+
tables: elements.tables,
|
|
21
|
+
dialogs: elements.dialogs,
|
|
22
|
+
truncated: accessibilityTruncated || elements.truncated,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=analyze-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-page.js","sourceRoot":"","sources":["../src/analyze-page.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAItC,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAwB,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAc,EACd,GAAW,EACX,SAA0B,wBAAwB;IAElD,MAAM,oBAAoB,GAAG,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC3D,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,sBAAsB,EAAE,GAAG,0BAA0B,CAC5E,oBAAoB,EACpB,MAAM,CACP,CAAC;IACF,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAEzD,OAAO;QACL,GAAG;QACH,iBAAiB,EAAE,IAAI;QACvB,mBAAmB,EAAE,QAAQ,CAAC,mBAAmB;QACjD,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,SAAS,EAAE,sBAAsB,IAAI,QAAQ,CAAC,SAAS;KACxD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type BrowserLauncher, type Clock } from '@qa-ai-stlc/core';
|
|
2
|
+
import { type PageModelSet } from '@qa-ai-stlc/schemas';
|
|
3
|
+
import { type ExplorerIdentity } from './identity.js';
|
|
4
|
+
import { type NormalizeLimits } from './normalize.js';
|
|
5
|
+
export interface AnalyzePagesOptions {
|
|
6
|
+
readonly urls: readonly string[];
|
|
7
|
+
readonly browserLauncher: BrowserLauncher;
|
|
8
|
+
/** Signs in before analyzing, reusing `authenticate()` (P1-05). Omit to analyze anonymously. */
|
|
9
|
+
readonly identity?: ExplorerIdentity;
|
|
10
|
+
readonly limits?: NormalizeLimits;
|
|
11
|
+
readonly clock?: Clock;
|
|
12
|
+
}
|
|
13
|
+
export interface AnalyzePagesResult {
|
|
14
|
+
readonly pageModelSet: PageModelSet;
|
|
15
|
+
/** Every non-GET request safe mode intercepted and cancelled; always 0 unless something is broken. */
|
|
16
|
+
readonly blockedRequestCount: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Analyzes every URL in `urls` — typically a crawl's `RouteMap.routes` — in one browser session,
|
|
20
|
+
* in safe mode (development plan section 6.3 step 3): navigating for analysis never sends a
|
|
21
|
+
* non-GET request either. Produces one `PageModel` per URL, in the given order.
|
|
22
|
+
*/
|
|
23
|
+
export declare function analyzePages(options: AnalyzePagesOptions): Promise<AnalyzePagesResult>;
|
|
24
|
+
//# sourceMappingURL=analyze-pages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-pages.d.ts","sourceRoot":"","sources":["../src/analyze-pages.ts"],"names":[],"mappings":"AAGA,OAAO,EAAe,KAAK,eAAe,EAAE,KAAK,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EAAkC,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExF,OAAO,EAAuB,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAA4B,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGhF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAC1C,gGAAgG;IAChG,QAAQ,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,sGAAsG;IACtG,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;CACtC;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAgC5F"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Copyright The QA-AI-STLC Authors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { systemClock } from '@qa-ai-stlc/core';
|
|
4
|
+
import { SCHEMA_VERSION } from '@qa-ai-stlc/schemas';
|
|
5
|
+
import { analyzePage } from './analyze-page.js';
|
|
6
|
+
import { resolveStorageState } from './identity.js';
|
|
7
|
+
import { DEFAULT_NORMALIZE_LIMITS } from './normalize.js';
|
|
8
|
+
import { createSafeModeRouteHandler } from './safe-mode.js';
|
|
9
|
+
/**
|
|
10
|
+
* Analyzes every URL in `urls` — typically a crawl's `RouteMap.routes` — in one browser session,
|
|
11
|
+
* in safe mode (development plan section 6.3 step 3): navigating for analysis never sends a
|
|
12
|
+
* non-GET request either. Produces one `PageModel` per URL, in the given order.
|
|
13
|
+
*/
|
|
14
|
+
export async function analyzePages(options) {
|
|
15
|
+
const clock = options.clock ?? systemClock;
|
|
16
|
+
const limits = options.limits ?? DEFAULT_NORMALIZE_LIMITS;
|
|
17
|
+
const storageState = await resolveStorageState(options.browserLauncher, options.identity);
|
|
18
|
+
const browser = await options.browserLauncher.launch();
|
|
19
|
+
try {
|
|
20
|
+
const context = await browser.newContext(storageState === undefined ? {} : { storageState });
|
|
21
|
+
const page = await context.newPage();
|
|
22
|
+
let blockedRequestCount = 0;
|
|
23
|
+
await page.route('**/*', createSafeModeRouteHandler(() => {
|
|
24
|
+
blockedRequestCount += 1;
|
|
25
|
+
}));
|
|
26
|
+
const pages = [];
|
|
27
|
+
for (const url of options.urls) {
|
|
28
|
+
await page.goto(url);
|
|
29
|
+
pages.push(await analyzePage(page, url, limits));
|
|
30
|
+
}
|
|
31
|
+
const pageModelSet = {
|
|
32
|
+
schemaVersion: SCHEMA_VERSION,
|
|
33
|
+
generatedAt: clock.now().toISOString(),
|
|
34
|
+
pages,
|
|
35
|
+
};
|
|
36
|
+
return { pageModelSet, blockedRequestCount };
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
await browser.close();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=analyze-pages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-pages.js","sourceRoot":"","sources":["../src/analyze-pages.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAEtC,OAAO,EAAE,WAAW,EAAoC,MAAM,kBAAkB,CAAC;AACjF,OAAO,EAAE,cAAc,EAAqC,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAyB,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAwB,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAiB5D;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAA4B;IAC7D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,WAAW,CAAC;IAC3C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,wBAAwB,CAAC;IAC1D,MAAM,YAAY,GAAG,MAAM,mBAAmB,CAAC,OAAO,CAAC,eAAe,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAE1F,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC;IACvD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC;QAC7F,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QACrC,IAAI,mBAAmB,GAAG,CAAC,CAAC;QAC5B,MAAM,IAAI,CAAC,KAAK,CACd,MAAM,EACN,0BAA0B,CAAC,GAAG,EAAE;YAC9B,mBAAmB,IAAI,CAAC,CAAC;QAC3B,CAAC,CAAC,CACH,CAAC;QAEF,MAAM,KAAK,GAAgB,EAAE,CAAC;QAC9B,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YAC/B,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,MAAM,WAAW,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;QACnD,CAAC;QAED,MAAM,YAAY,GAAiB;YACjC,aAAa,EAAE,cAAc;YAC7B,WAAW,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;YACtC,KAAK;SACN,CAAC;QACF,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,CAAC;IAC/C,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
|
package/dist/crawl.d.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { type BrowserLauncher, type Clock } from '@qa-ai-stlc/core';
|
|
2
|
-
import { type
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
readonly env: Readonly<Record<string, string | undefined>>;
|
|
6
|
-
/** Required, and only used, when `identity.config.auth` is `"cdp-attach"`. */
|
|
7
|
-
readonly cdpEndpointUrl?: string;
|
|
8
|
-
}
|
|
2
|
+
import { type RouteMap } from '@qa-ai-stlc/schemas';
|
|
3
|
+
import { type ExplorerIdentity } from './identity.js';
|
|
4
|
+
export type CrawlIdentity = ExplorerIdentity;
|
|
9
5
|
export interface CrawlOptions {
|
|
10
6
|
readonly startUrl: string;
|
|
11
7
|
/** Hostnames the crawl may navigate to (development plan section 6.4); a link outside it is dropped. */
|
package/dist/crawl.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crawl.d.ts","sourceRoot":"","sources":["../src/crawl.ts"],"names":[],"mappings":"AAGA,OAAO,
|
|
1
|
+
{"version":3,"file":"crawl.d.ts","sourceRoot":"","sources":["../src/crawl.ts"],"names":[],"mappings":"AAGA,OAAO,EAA8B,KAAK,eAAe,EAAE,KAAK,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAChG,OAAO,EAAwC,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAG1F,OAAO,EAAuB,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAM3E,MAAM,MAAM,aAAa,GAAG,gBAAgB,CAAC;AAE7C,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,wGAAwG;IACxG,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAC1C,6FAA6F;IAC7F,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC;IAClC,2FAA2F;IAC3F,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,sGAAsG;IACtG,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,sGAAsG;IACtG,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;CACtC;AAQD;;;;;GAKG;AACH,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAoCvE"}
|
package/dist/crawl.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// Copyright The QA-AI-STLC Authors
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
import {
|
|
4
|
-
import { SCHEMA_VERSION
|
|
3
|
+
import { systemClock } from '@qa-ai-stlc/core';
|
|
4
|
+
import { SCHEMA_VERSION } from '@qa-ai-stlc/schemas';
|
|
5
5
|
import { isAllowedUrl, normalizeUrl } from './allowlist.js';
|
|
6
6
|
import { extractLinks } from './extract-links.js';
|
|
7
|
+
import { resolveStorageState } from './identity.js';
|
|
7
8
|
import { buildRequestLogHar } from './request-log.js';
|
|
8
9
|
import { createSafeModeRouteHandler } from './safe-mode.js';
|
|
9
10
|
const DEFAULT_MAX_PAGES = 50;
|
|
@@ -16,7 +17,7 @@ const DEFAULT_MAX_PAGES = 50;
|
|
|
16
17
|
export async function crawl(options) {
|
|
17
18
|
const clock = options.clock ?? systemClock;
|
|
18
19
|
const maxPages = options.maxPages ?? DEFAULT_MAX_PAGES;
|
|
19
|
-
const storageState = await resolveStorageState(options);
|
|
20
|
+
const storageState = await resolveStorageState(options.browserLauncher, options.identity);
|
|
20
21
|
const browser = await options.browserLauncher.launch();
|
|
21
22
|
try {
|
|
22
23
|
const context = await browser.newContext(storageState === undefined ? {} : { storageState });
|
|
@@ -44,16 +45,6 @@ export async function crawl(options) {
|
|
|
44
45
|
await browser.close();
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
|
-
async function resolveStorageState(options) {
|
|
48
|
-
if (options.identity === undefined) {
|
|
49
|
-
return undefined;
|
|
50
|
-
}
|
|
51
|
-
return authenticate(options.browserLauncher, options.identity.config, options.identity.env, {
|
|
52
|
-
...(options.identity.cdpEndpointUrl !== undefined
|
|
53
|
-
? { cdpEndpointUrl: options.identity.cdpEndpointUrl }
|
|
54
|
-
: {}),
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
48
|
async function visitAllowedRoutes(page, options, maxPages, logEntries) {
|
|
58
49
|
const visited = new Set();
|
|
59
50
|
const routes = [];
|
package/dist/crawl.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crawl.js","sourceRoot":"","sources":["../src/crawl.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAEtC,OAAO,
|
|
1
|
+
{"version":3,"file":"crawl.js","sourceRoot":"","sources":["../src/crawl.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type BrowserLauncher, type StorageState } from '@qa-ai-stlc/core';
|
|
2
|
+
import type { IdentityConfig } from '@qa-ai-stlc/schemas';
|
|
3
|
+
export interface ExplorerIdentity {
|
|
4
|
+
readonly config: IdentityConfig;
|
|
5
|
+
readonly env: Readonly<Record<string, string | undefined>>;
|
|
6
|
+
/** Required, and only used, when `identity.config.auth` is `"cdp-attach"`. */
|
|
7
|
+
readonly cdpEndpointUrl?: string;
|
|
8
|
+
}
|
|
9
|
+
/** Signs in through P1-05's `authenticate()` when an identity is given; `undefined` for an anonymous session. */
|
|
10
|
+
export declare function resolveStorageState(browserLauncher: BrowserLauncher, identity: ExplorerIdentity | undefined): Promise<StorageState | undefined>;
|
|
11
|
+
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgB,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IAC3D,8EAA8E;IAC9E,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,iHAAiH;AACjH,wBAAsB,mBAAmB,CACvC,eAAe,EAAE,eAAe,EAChC,QAAQ,EAAE,gBAAgB,GAAG,SAAS,GACrC,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAOnC"}
|
package/dist/identity.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Copyright The QA-AI-STLC Authors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { authenticate } from '@qa-ai-stlc/core';
|
|
4
|
+
/** Signs in through P1-05's `authenticate()` when an identity is given; `undefined` for an anonymous session. */
|
|
5
|
+
export async function resolveStorageState(browserLauncher, identity) {
|
|
6
|
+
if (identity === undefined) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
return authenticate(browserLauncher, identity.config, identity.env, {
|
|
10
|
+
...(identity.cdpEndpointUrl !== undefined ? { cdpEndpointUrl: identity.cdpEndpointUrl } : {}),
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAEtC,OAAO,EAAE,YAAY,EAA2C,MAAM,kBAAkB,CAAC;AAUzF,iHAAiH;AACjH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,eAAgC,EAChC,QAAsC;IAEtC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,YAAY,CAAC,eAAe,EAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,EAAE;QAClE,GAAG,CAAC,QAAQ,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,QAAQ,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9F,CAAC,CAAC;AACL,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
export * from './accessibility-tree.js';
|
|
1
2
|
export * from './allowlist.js';
|
|
3
|
+
export * from './analyze-page.js';
|
|
4
|
+
export * from './analyze-pages.js';
|
|
2
5
|
export * from './crawl.js';
|
|
3
6
|
export * from './extract-links.js';
|
|
7
|
+
export * from './identity.js';
|
|
8
|
+
export * from './normalize.js';
|
|
9
|
+
export * from './page-elements.js';
|
|
4
10
|
export * from './request-log.js';
|
|
11
|
+
export * from './safe-mode.js';
|
|
5
12
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,yBAAyB,CAAC;AACxC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
// Copyright The QA-AI-STLC Authors
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
export * from './accessibility-tree.js';
|
|
3
4
|
export * from './allowlist.js';
|
|
5
|
+
export * from './analyze-page.js';
|
|
6
|
+
export * from './analyze-pages.js';
|
|
4
7
|
export * from './crawl.js';
|
|
5
8
|
export * from './extract-links.js';
|
|
9
|
+
export * from './identity.js';
|
|
10
|
+
export * from './normalize.js';
|
|
11
|
+
export * from './page-elements.js';
|
|
6
12
|
export * from './request-log.js';
|
|
13
|
+
export * from './safe-mode.js';
|
|
7
14
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAEtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAEtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface NormalizeLimits {
|
|
2
|
+
readonly maxTextLength: number;
|
|
3
|
+
readonly maxArrayLength: number;
|
|
4
|
+
readonly maxTreeNodes: number;
|
|
5
|
+
}
|
|
6
|
+
export declare const DEFAULT_NORMALIZE_LIMITS: NormalizeLimits;
|
|
7
|
+
/**
|
|
8
|
+
* Caps a single piece of page-derived text (development plan section 2.6): untrusted content
|
|
9
|
+
* from the application under test is never passed on unbounded. Returns the text unchanged, and
|
|
10
|
+
* `truncated: false`, when it is already within the limit.
|
|
11
|
+
*/
|
|
12
|
+
export declare function truncateText(text: string, limits?: NormalizeLimits): {
|
|
13
|
+
readonly text: string;
|
|
14
|
+
readonly truncated: boolean;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Caps how many items of a page-derived list (interactive elements, table rows, ...) are kept.
|
|
18
|
+
* Every element on a page still gets *counted* elsewhere; this only bounds how many are carried
|
|
19
|
+
* into the artifact and, eventually, into an agent's context.
|
|
20
|
+
*/
|
|
21
|
+
export declare function capArray<T>(items: readonly T[], limits?: NormalizeLimits): {
|
|
22
|
+
readonly items: readonly T[];
|
|
23
|
+
readonly truncated: boolean;
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=normalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../src/normalize.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,eAAO,MAAM,wBAAwB,EAAE,eAItC,CAAC;AAIF;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,eAA0C,GACjD;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAKxD;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EACxB,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,MAAM,GAAE,eAA0C,GACjD;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAK/D"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Copyright The QA-AI-STLC Authors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
export const DEFAULT_NORMALIZE_LIMITS = {
|
|
4
|
+
maxTextLength: 200,
|
|
5
|
+
maxArrayLength: 200,
|
|
6
|
+
maxTreeNodes: 500,
|
|
7
|
+
};
|
|
8
|
+
const TRUNCATION_SUFFIX = '…';
|
|
9
|
+
/**
|
|
10
|
+
* Caps a single piece of page-derived text (development plan section 2.6): untrusted content
|
|
11
|
+
* from the application under test is never passed on unbounded. Returns the text unchanged, and
|
|
12
|
+
* `truncated: false`, when it is already within the limit.
|
|
13
|
+
*/
|
|
14
|
+
export function truncateText(text, limits = DEFAULT_NORMALIZE_LIMITS) {
|
|
15
|
+
if (text.length <= limits.maxTextLength) {
|
|
16
|
+
return { text, truncated: false };
|
|
17
|
+
}
|
|
18
|
+
return { text: text.slice(0, limits.maxTextLength) + TRUNCATION_SUFFIX, truncated: true };
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Caps how many items of a page-derived list (interactive elements, table rows, ...) are kept.
|
|
22
|
+
* Every element on a page still gets *counted* elsewhere; this only bounds how many are carried
|
|
23
|
+
* into the artifact and, eventually, into an agent's context.
|
|
24
|
+
*/
|
|
25
|
+
export function capArray(items, limits = DEFAULT_NORMALIZE_LIMITS) {
|
|
26
|
+
if (items.length <= limits.maxArrayLength) {
|
|
27
|
+
return { items, truncated: false };
|
|
28
|
+
}
|
|
29
|
+
return { items: items.slice(0, limits.maxArrayLength), truncated: true };
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=normalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../src/normalize.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAQtC,MAAM,CAAC,MAAM,wBAAwB,GAAoB;IACvD,aAAa,EAAE,GAAG;IAClB,cAAc,EAAE,GAAG;IACnB,YAAY,EAAE,GAAG;CAClB,CAAC;AAEF,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC1B,IAAY,EACZ,SAA0B,wBAAwB;IAElD,IAAI,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;QACxC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACpC,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,aAAa,CAAC,GAAG,iBAAiB,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AAC5F,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CACtB,KAAmB,EACnB,SAA0B,wBAAwB;IAElD,IAAI,KAAK,CAAC,MAAM,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;QAC1C,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACrC,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AAC3E,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AuthPage } from '@qa-ai-stlc/core';
|
|
2
|
+
import type { Dialog, Form, InteractiveElement, Table } from '@qa-ai-stlc/schemas';
|
|
3
|
+
import { type NormalizeLimits } from './normalize.js';
|
|
4
|
+
export interface PageElements {
|
|
5
|
+
readonly interactiveElements: InteractiveElement[];
|
|
6
|
+
readonly forms: Form[];
|
|
7
|
+
readonly tables: Table[];
|
|
8
|
+
readonly dialogs: Dialog[];
|
|
9
|
+
readonly truncated: boolean;
|
|
10
|
+
}
|
|
11
|
+
/** Extracts and normalizes every interactive element, form, table and dialog on the current page. */
|
|
12
|
+
export declare function extractPageElements(page: AuthPage, limits: NormalizeLimits): Promise<PageElements>;
|
|
13
|
+
//# sourceMappingURL=page-elements.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-elements.d.ts","sourceRoot":"","sources":["../src/page-elements.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EACV,MAAM,EACN,IAAI,EAEJ,kBAAkB,EAElB,KAAK,EACN,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAA0B,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAqC9E,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,mBAAmB,EAAE,kBAAkB,EAAE,CAAC;IACnD,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAoJD,qGAAqG;AACrG,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,CAuCxG"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// Copyright The QA-AI-STLC Authors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { capArray, truncateText } from './normalize.js';
|
|
4
|
+
const INTERACTIVE_ELEMENT_KINDS = [
|
|
5
|
+
'button',
|
|
6
|
+
'link',
|
|
7
|
+
'input',
|
|
8
|
+
'select',
|
|
9
|
+
'textarea',
|
|
10
|
+
];
|
|
11
|
+
function isInteractiveElementKind(value) {
|
|
12
|
+
return INTERACTIVE_ELEMENT_KINDS.includes(value);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Reads every interactive element, form, table and dialog on the current page. The callback runs
|
|
16
|
+
* inside the browser (Playwright serializes it across the CDP boundary), so it can reference DOM
|
|
17
|
+
* globals unavailable to the rest of this package.
|
|
18
|
+
*/
|
|
19
|
+
async function readRawPageElements(page) {
|
|
20
|
+
/* v8 ignore next 60 -- runs in the browser's own V8 instance, invisible to Node coverage */
|
|
21
|
+
const result = await page.evaluate(() => {
|
|
22
|
+
function accessibleName(element) {
|
|
23
|
+
const ariaLabel = element.getAttribute('aria-label');
|
|
24
|
+
if (ariaLabel !== null && ariaLabel.trim().length > 0) {
|
|
25
|
+
return ariaLabel;
|
|
26
|
+
}
|
|
27
|
+
const text = element.textContent.trim();
|
|
28
|
+
return text.length > 0 ? text : undefined;
|
|
29
|
+
}
|
|
30
|
+
const kindByTagName = {
|
|
31
|
+
a: 'link',
|
|
32
|
+
button: 'button',
|
|
33
|
+
input: 'input',
|
|
34
|
+
select: 'select',
|
|
35
|
+
textarea: 'textarea',
|
|
36
|
+
};
|
|
37
|
+
const interactiveElements = Array.from(document.querySelectorAll('button, a[href], input, select, textarea')).map((element) => ({
|
|
38
|
+
kind: kindByTagName[element.tagName.toLowerCase()] ?? element.tagName.toLowerCase(),
|
|
39
|
+
accessibleName: accessibleName(element),
|
|
40
|
+
testId: element.getAttribute('data-testid') ?? undefined,
|
|
41
|
+
}));
|
|
42
|
+
const forms = Array.from(document.querySelectorAll('form')).map((form) => ({
|
|
43
|
+
action: form.getAttribute('action') ?? undefined,
|
|
44
|
+
method: (form.getAttribute('method') ?? 'get').toLowerCase(),
|
|
45
|
+
fields: Array.from(form.querySelectorAll('input, select, textarea')).map((field) => ({
|
|
46
|
+
name: field.getAttribute('name') ?? undefined,
|
|
47
|
+
type: field.getAttribute('type') ?? field.tagName.toLowerCase(),
|
|
48
|
+
required: field.hasAttribute('required'),
|
|
49
|
+
})),
|
|
50
|
+
}));
|
|
51
|
+
const tables = Array.from(document.querySelectorAll('table')).map((table) => ({
|
|
52
|
+
columnHeaders: Array.from(table.querySelectorAll('thead th')).map((header) => header.textContent.trim()),
|
|
53
|
+
rowCount: table.querySelectorAll('tbody tr').length,
|
|
54
|
+
}));
|
|
55
|
+
const dialogs = Array.from(document.querySelectorAll('dialog, [role="dialog"]')).map((dialog) => ({
|
|
56
|
+
accessibleName: accessibleName(dialog),
|
|
57
|
+
open: dialog.hasAttribute('open'),
|
|
58
|
+
}));
|
|
59
|
+
return { interactiveElements, forms, tables, dialogs };
|
|
60
|
+
});
|
|
61
|
+
return isRawPageElements(result) ? result : undefined;
|
|
62
|
+
}
|
|
63
|
+
function isRawPageElements(value) {
|
|
64
|
+
if (typeof value !== 'object' || value === null) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
const record = value;
|
|
68
|
+
return (Array.isArray(record.interactiveElements) &&
|
|
69
|
+
Array.isArray(record.forms) &&
|
|
70
|
+
Array.isArray(record.tables) &&
|
|
71
|
+
Array.isArray(record.dialogs));
|
|
72
|
+
}
|
|
73
|
+
function normalizeInteractiveElement(raw, limits, onTruncated) {
|
|
74
|
+
if (!isInteractiveElementKind(raw.kind)) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
const element = { kind: raw.kind };
|
|
78
|
+
if (raw.accessibleName !== undefined) {
|
|
79
|
+
const { text, truncated } = truncateText(raw.accessibleName, limits);
|
|
80
|
+
element.accessibleName = text;
|
|
81
|
+
if (truncated) {
|
|
82
|
+
onTruncated();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (raw.testId !== undefined) {
|
|
86
|
+
element.testId = raw.testId;
|
|
87
|
+
}
|
|
88
|
+
return element;
|
|
89
|
+
}
|
|
90
|
+
function normalizeForm(raw) {
|
|
91
|
+
const form = {
|
|
92
|
+
method: raw.method,
|
|
93
|
+
fields: raw.fields.map((field) => {
|
|
94
|
+
const result = { type: field.type, required: field.required };
|
|
95
|
+
if (field.name !== undefined) {
|
|
96
|
+
result.name = field.name;
|
|
97
|
+
}
|
|
98
|
+
return result;
|
|
99
|
+
}),
|
|
100
|
+
};
|
|
101
|
+
if (raw.action !== undefined) {
|
|
102
|
+
form.action = raw.action;
|
|
103
|
+
}
|
|
104
|
+
return form;
|
|
105
|
+
}
|
|
106
|
+
function normalizeTable(raw, limits, onTruncated) {
|
|
107
|
+
const headers = raw.columnHeaders.map((header) => {
|
|
108
|
+
const { text, truncated } = truncateText(header, limits);
|
|
109
|
+
if (truncated) {
|
|
110
|
+
onTruncated();
|
|
111
|
+
}
|
|
112
|
+
return text;
|
|
113
|
+
});
|
|
114
|
+
return { columnHeaders: headers, rowCount: raw.rowCount };
|
|
115
|
+
}
|
|
116
|
+
function normalizeDialog(raw, limits, onTruncated) {
|
|
117
|
+
const dialog = { open: raw.open };
|
|
118
|
+
if (raw.accessibleName !== undefined) {
|
|
119
|
+
const { text, truncated } = truncateText(raw.accessibleName, limits);
|
|
120
|
+
dialog.accessibleName = text;
|
|
121
|
+
if (truncated) {
|
|
122
|
+
onTruncated();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return dialog;
|
|
126
|
+
}
|
|
127
|
+
/** Extracts and normalizes every interactive element, form, table and dialog on the current page. */
|
|
128
|
+
export async function extractPageElements(page, limits) {
|
|
129
|
+
const raw = await readRawPageElements(page);
|
|
130
|
+
if (raw === undefined) {
|
|
131
|
+
return { interactiveElements: [], forms: [], tables: [], dialogs: [], truncated: true };
|
|
132
|
+
}
|
|
133
|
+
let truncated = false;
|
|
134
|
+
const markTruncated = () => {
|
|
135
|
+
truncated = true;
|
|
136
|
+
};
|
|
137
|
+
const interactiveElements = capArray(raw.interactiveElements, limits);
|
|
138
|
+
if (interactiveElements.truncated) {
|
|
139
|
+
truncated = true;
|
|
140
|
+
}
|
|
141
|
+
const forms = capArray(raw.forms, limits);
|
|
142
|
+
if (forms.truncated) {
|
|
143
|
+
truncated = true;
|
|
144
|
+
}
|
|
145
|
+
const tables = capArray(raw.tables, limits);
|
|
146
|
+
if (tables.truncated) {
|
|
147
|
+
truncated = true;
|
|
148
|
+
}
|
|
149
|
+
const dialogs = capArray(raw.dialogs, limits);
|
|
150
|
+
if (dialogs.truncated) {
|
|
151
|
+
truncated = true;
|
|
152
|
+
}
|
|
153
|
+
const normalizedInteractiveElements = interactiveElements.items
|
|
154
|
+
.map((element) => normalizeInteractiveElement(element, limits, markTruncated))
|
|
155
|
+
.filter((element) => element !== undefined);
|
|
156
|
+
return {
|
|
157
|
+
interactiveElements: normalizedInteractiveElements,
|
|
158
|
+
forms: forms.items.map(normalizeForm),
|
|
159
|
+
tables: tables.items.map((table) => normalizeTable(table, limits, markTruncated)),
|
|
160
|
+
dialogs: dialogs.items.map((dialog) => normalizeDialog(dialog, limits, markTruncated)),
|
|
161
|
+
truncated,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=page-elements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-elements.js","sourceRoot":"","sources":["../src/page-elements.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qa-ai-stlc/explorer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "The crawler: route discovery in safe mode, redacted request logging, and the route map every later explorer phase builds on.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"clean": "node ../../scripts/clean-dir.mjs dist"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@qa-ai-stlc/core": "0.
|
|
32
|
-
"@qa-ai-stlc/schemas": "0.
|
|
31
|
+
"@qa-ai-stlc/core": "0.2.0",
|
|
32
|
+
"@qa-ai-stlc/schemas": "0.2.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@qa-ai-stlc/test-utils": "0.0.0"
|