@qa-ai-stlc/explorer 0.3.0 → 0.4.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/build-selector-registry.d.ts +51 -0
- package/dist/build-selector-registry.d.ts.map +1 -0
- package/dist/build-selector-registry.js +0 -0
- package/dist/build-selector-registry.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/stability-scoring.d.ts +19 -0
- package/dist/stability-scoring.d.ts.map +1 -0
- package/dist/stability-scoring.js +82 -0
- package/dist/stability-scoring.js.map +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type BrowserLauncher, type Clock, type ViewportSize } from '@qa-ai-stlc/core';
|
|
2
|
+
import { type PageModelSet, type SelectorElement, type SelectorRegistry } from '@qa-ai-stlc/schemas';
|
|
3
|
+
import { type ExplorerIdentity } from './identity.js';
|
|
4
|
+
import { type LocatorPolicy } from './synthesize-locators.js';
|
|
5
|
+
export interface BuildSelectorRegistryOptions {
|
|
6
|
+
readonly pageModelSet: PageModelSet;
|
|
7
|
+
readonly browserLauncher: BrowserLauncher;
|
|
8
|
+
/** Signs in before re-navigating to score candidates. Omit to score anonymously. */
|
|
9
|
+
readonly identity?: ExplorerIdentity;
|
|
10
|
+
readonly policy?: LocatorPolicy;
|
|
11
|
+
readonly viewports?: readonly ViewportSize[];
|
|
12
|
+
readonly clock?: Clock;
|
|
13
|
+
}
|
|
14
|
+
export interface BuildSelectorRegistryResult {
|
|
15
|
+
readonly registry: SelectorRegistry;
|
|
16
|
+
/** Every non-GET request safe mode intercepted and cancelled; always 0 unless something is broken. */
|
|
17
|
+
readonly blockedRequestCount: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Builds a `SelectorRegistry` from a `PageModelSet` produced by `analyzePages()` (development
|
|
21
|
+
* plan section 6.3 steps 4-6): synthesizes locator candidates for every interactive element under
|
|
22
|
+
* the configured policy, scores the first (primary) candidate's stability in a fresh live pass
|
|
23
|
+
* over the same URLs, and assigns each element a stable id. Every entry's `source` is `'crawl'` -
|
|
24
|
+
* the only source this pipeline produces (`static`/`manual` come from other tasks).
|
|
25
|
+
*/
|
|
26
|
+
export declare function buildSelectorRegistry(options: BuildSelectorRegistryOptions): Promise<BuildSelectorRegistryResult>;
|
|
27
|
+
/**
|
|
28
|
+
* Merges a freshly built registry onto a previously stored one, keeping history (development plan
|
|
29
|
+
* section 6.3.6): every element the fresh crawl found replaces its previous entry outright
|
|
30
|
+
* (un-deprecating it, if it had been). An element the fresh crawl did not find is kept rather than
|
|
31
|
+
* deleted, with `deprecatedAt` set to `generatedAt` the first time it goes missing; once
|
|
32
|
+
* deprecated, its `deprecatedAt` is never overwritten by a later run that still does not find it.
|
|
33
|
+
*/
|
|
34
|
+
export declare function mergeSelectorRegistry(previous: SelectorRegistry, fresh: SelectorRegistry, generatedAt: string): SelectorRegistry;
|
|
35
|
+
export interface DegradedSelectorElement {
|
|
36
|
+
readonly elementId: string;
|
|
37
|
+
readonly previousScore: number;
|
|
38
|
+
readonly currentScore: number;
|
|
39
|
+
}
|
|
40
|
+
export interface SelectorRegistryDiff {
|
|
41
|
+
readonly added: readonly SelectorElement[];
|
|
42
|
+
readonly removed: readonly SelectorElement[];
|
|
43
|
+
readonly degraded: readonly DegradedSelectorElement[];
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Compares two crawls' registries by `elementId`: elements only the current crawl found, elements
|
|
47
|
+
* only the previous crawl found, and elements both found where the current stability score is
|
|
48
|
+
* lower than before.
|
|
49
|
+
*/
|
|
50
|
+
export declare function diffSelectorRegistry(previous: SelectorRegistry, current: SelectorRegistry): SelectorRegistryDiff;
|
|
51
|
+
//# sourceMappingURL=build-selector-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-selector-registry.d.ts","sourceRoot":"","sources":["../src/build-selector-registry.ts"],"names":[],"mappings":"AAGA,OAAO,EAAyB,KAAK,eAAe,EAAE,KAAK,KAAK,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC9G,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAuB,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAG3E,OAAO,EAA+B,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE3F,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAC1C,oFAAoF;IACpF,QAAQ,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IAC7C,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;CACxB;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,sGAAsG;IACtG,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;CACtC;AAoBD;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,2BAA2B,CAAC,CAoDtC;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,gBAAgB,EACvB,WAAW,EAAE,MAAM,GAClB,gBAAgB,CAalB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IAC7C,QAAQ,CAAC,QAAQ,EAAE,SAAS,uBAAuB,EAAE,CAAC;CACvD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,EAAE,gBAAgB,GACxB,oBAAoB,CAoBtB"}
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-selector-registry.js","sourceRoot":"","sources":["../src/build-selector-registry.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from './accessibility-tree.js';
|
|
|
2
2
|
export * from './allowlist.js';
|
|
3
3
|
export * from './analyze-page.js';
|
|
4
4
|
export * from './analyze-pages.js';
|
|
5
|
+
export * from './build-selector-registry.js';
|
|
5
6
|
export * from './crawl.js';
|
|
6
7
|
export * from './extract-links.js';
|
|
7
8
|
export * from './identity.js';
|
|
@@ -9,5 +10,6 @@ export * from './normalize.js';
|
|
|
9
10
|
export * from './page-elements.js';
|
|
10
11
|
export * from './request-log.js';
|
|
11
12
|
export * from './safe-mode.js';
|
|
13
|
+
export * from './stability-scoring.js';
|
|
12
14
|
export * from './synthesize-locators.js';
|
|
13
15
|
//# 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,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;AAC/B,cAAc,0BAA0B,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,8BAA8B,CAAC;AAC7C,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;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export * from './accessibility-tree.js';
|
|
|
4
4
|
export * from './allowlist.js';
|
|
5
5
|
export * from './analyze-page.js';
|
|
6
6
|
export * from './analyze-pages.js';
|
|
7
|
+
export * from './build-selector-registry.js';
|
|
7
8
|
export * from './crawl.js';
|
|
8
9
|
export * from './extract-links.js';
|
|
9
10
|
export * from './identity.js';
|
|
@@ -11,5 +12,6 @@ export * from './normalize.js';
|
|
|
11
12
|
export * from './page-elements.js';
|
|
12
13
|
export * from './request-log.js';
|
|
13
14
|
export * from './safe-mode.js';
|
|
15
|
+
export * from './stability-scoring.js';
|
|
14
16
|
export * from './synthesize-locators.js';
|
|
15
17
|
//# 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,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;AAC/B,cAAc,0BAA0B,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,8BAA8B,CAAC;AAC7C,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;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AuthPage, PageLocator, ViewportSize } from '@qa-ai-stlc/core';
|
|
2
|
+
import type { LocatorCandidate } from '@qa-ai-stlc/schemas';
|
|
3
|
+
export interface StabilityScoringOptions {
|
|
4
|
+
/** Viewport sizes checked after uniqueness and reload survival; defaults to desktop/tablet/mobile. */
|
|
5
|
+
readonly viewports?: readonly ViewportSize[];
|
|
6
|
+
}
|
|
7
|
+
export declare const DEFAULT_VIEWPORTS: readonly ViewportSize[];
|
|
8
|
+
/** Resolves one of P1-08's `LocatorCandidate` values to a live `PageLocator`, by strategy. */
|
|
9
|
+
export declare function resolveCandidateLocator(page: AuthPage, candidate: LocatorCandidate): PageLocator;
|
|
10
|
+
/**
|
|
11
|
+
* Verifies one locator candidate against the current live page: uniqueness now, then survival
|
|
12
|
+
* across a reload and across each configured viewport size (development plan section 6.3.5).
|
|
13
|
+
* Uniqueness is a hard gate — a candidate that does not resolve to exactly one element right now
|
|
14
|
+
* cannot be called stable, so reload/viewport are never checked against a candidate that has
|
|
15
|
+
* already failed. The page's original viewport size is restored before returning, so scoring one
|
|
16
|
+
* element's candidate does not affect the next.
|
|
17
|
+
*/
|
|
18
|
+
export declare function scoreLocatorStability(page: AuthPage, candidate: LocatorCandidate, options?: StabilityScoringOptions): Promise<number>;
|
|
19
|
+
//# sourceMappingURL=stability-scoring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stability-scoring.d.ts","sourceRoot":"","sources":["../src/stability-scoring.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE5E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,MAAM,WAAW,uBAAuB;IACtC,sGAAsG;IACtG,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;CAC9C;AAED,eAAO,MAAM,iBAAiB,EAAE,SAAS,YAAY,EAIpD,CAAC;AAkCF,8FAA8F;AAC9F,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,gBAAgB,GAAG,WAAW,CAmBhG;AAOD;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,QAAQ,EACd,SAAS,EAAE,gBAAgB,EAC3B,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,MAAM,CAAC,CA0BjB"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Copyright The QA-AI-STLC Authors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { QaError } from '@qa-ai-stlc/core';
|
|
4
|
+
export const DEFAULT_VIEWPORTS = [
|
|
5
|
+
{ width: 1280, height: 720 },
|
|
6
|
+
{ width: 768, height: 1024 },
|
|
7
|
+
{ width: 375, height: 667 },
|
|
8
|
+
];
|
|
9
|
+
function parseRoleCandidateValue(value) {
|
|
10
|
+
let parsed;
|
|
11
|
+
try {
|
|
12
|
+
parsed = JSON.parse(value);
|
|
13
|
+
}
|
|
14
|
+
catch (cause) {
|
|
15
|
+
throw new QaError('locator-candidate-invalid', `Role locator candidate value is not valid JSON: "${value}".`, { cause });
|
|
16
|
+
}
|
|
17
|
+
if (typeof parsed !== 'object' ||
|
|
18
|
+
parsed === null ||
|
|
19
|
+
typeof parsed.role !== 'string') {
|
|
20
|
+
throw new QaError('locator-candidate-invalid', `Role locator candidate value has no "role" string: "${value}".`);
|
|
21
|
+
}
|
|
22
|
+
const record = parsed;
|
|
23
|
+
return typeof record.name === 'string'
|
|
24
|
+
? { role: record.role, name: record.name }
|
|
25
|
+
: { role: record.role };
|
|
26
|
+
}
|
|
27
|
+
/** Resolves one of P1-08's `LocatorCandidate` values to a live `PageLocator`, by strategy. */
|
|
28
|
+
export function resolveCandidateLocator(page, candidate) {
|
|
29
|
+
switch (candidate.strategy) {
|
|
30
|
+
case 'role': {
|
|
31
|
+
const { role, name } = parseRoleCandidateValue(candidate.value);
|
|
32
|
+
return page.getByRole(role, name === undefined ? undefined : { name });
|
|
33
|
+
}
|
|
34
|
+
case 'testId':
|
|
35
|
+
return page.getByTestId(candidate.value);
|
|
36
|
+
case 'label':
|
|
37
|
+
return page.getByLabel(candidate.value);
|
|
38
|
+
case 'placeholder':
|
|
39
|
+
return page.getByPlaceholder(candidate.value);
|
|
40
|
+
case 'text':
|
|
41
|
+
return page.getByText(candidate.value);
|
|
42
|
+
case 'css':
|
|
43
|
+
return page.locator(candidate.value);
|
|
44
|
+
default:
|
|
45
|
+
throw new QaError('locator-strategy-unknown', `Unknown locator strategy "${candidate.strategy}".`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async function isUniqueMatch(page, candidate) {
|
|
49
|
+
const count = await resolveCandidateLocator(page, candidate).count();
|
|
50
|
+
return count === 1;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Verifies one locator candidate against the current live page: uniqueness now, then survival
|
|
54
|
+
* across a reload and across each configured viewport size (development plan section 6.3.5).
|
|
55
|
+
* Uniqueness is a hard gate — a candidate that does not resolve to exactly one element right now
|
|
56
|
+
* cannot be called stable, so reload/viewport are never checked against a candidate that has
|
|
57
|
+
* already failed. The page's original viewport size is restored before returning, so scoring one
|
|
58
|
+
* element's candidate does not affect the next.
|
|
59
|
+
*/
|
|
60
|
+
export async function scoreLocatorStability(page, candidate, options = {}) {
|
|
61
|
+
if (!(await isUniqueMatch(page, candidate))) {
|
|
62
|
+
return 0;
|
|
63
|
+
}
|
|
64
|
+
const viewports = options.viewports ?? DEFAULT_VIEWPORTS;
|
|
65
|
+
const originalViewport = page.viewportSize();
|
|
66
|
+
let survivedChecks = 0;
|
|
67
|
+
await page.reload();
|
|
68
|
+
if (await isUniqueMatch(page, candidate)) {
|
|
69
|
+
survivedChecks += 1;
|
|
70
|
+
}
|
|
71
|
+
for (const viewport of viewports) {
|
|
72
|
+
await page.setViewportSize(viewport);
|
|
73
|
+
if (await isUniqueMatch(page, candidate)) {
|
|
74
|
+
survivedChecks += 1;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (originalViewport !== null) {
|
|
78
|
+
await page.setViewportSize(originalViewport);
|
|
79
|
+
}
|
|
80
|
+
return survivedChecks / (1 + viewports.length);
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=stability-scoring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stability-scoring.js","sourceRoot":"","sources":["../src/stability-scoring.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.4.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.3.0",
|
|
32
|
+
"@qa-ai-stlc/schemas": "0.4.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@qa-ai-stlc/test-utils": "0.0.0"
|