@qa-ai-stlc/explorer 0.6.4 → 0.7.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/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/operations/explore.d.ts +53 -0
- package/dist/operations/explore.d.ts.map +1 -0
- package/dist/operations/explore.js +242 -0
- package/dist/operations/explore.js.map +1 -0
- package/dist/package-version.d.ts +3 -0
- package/dist/package-version.d.ts.map +1 -0
- package/dist/package-version.js +10 -0
- package/dist/package-version.js.map +1 -0
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export * from './generate-locator-module.js';
|
|
|
12
12
|
export * from './identity.js';
|
|
13
13
|
export * from './naming.js';
|
|
14
14
|
export * from './normalize.js';
|
|
15
|
+
export * from './operations/explore.js';
|
|
15
16
|
export * from './page-elements.js';
|
|
16
17
|
export * from './pick-mode.js';
|
|
17
18
|
export * from './request-log.js';
|
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,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,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,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,7 @@ export * from './generate-locator-module.js';
|
|
|
14
14
|
export * from './identity.js';
|
|
15
15
|
export * from './naming.js';
|
|
16
16
|
export * from './normalize.js';
|
|
17
|
+
export * from './operations/explore.js';
|
|
17
18
|
export * from './page-elements.js';
|
|
18
19
|
export * from './pick-mode.js';
|
|
19
20
|
export * from './request-log.js';
|
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,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,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,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { ManifestStore, QaStore, type EngineContext } from '@qa-ai-stlc/core';
|
|
2
|
+
import { type Config, type EnvironmentConfig, type SelectorElement, type SelectorPolicy, type SelectorRegistry } from '@qa-ai-stlc/schemas';
|
|
3
|
+
import { type ExplorerIdentity } from '../identity.js';
|
|
4
|
+
import type { DegradedSelectorElement } from '../build-selector-registry.js';
|
|
5
|
+
export interface ExploreOptions {
|
|
6
|
+
readonly environment?: string;
|
|
7
|
+
readonly identity?: string;
|
|
8
|
+
readonly cdpEndpointUrl?: string;
|
|
9
|
+
readonly policy?: string;
|
|
10
|
+
readonly static?: boolean;
|
|
11
|
+
readonly maxPages?: number;
|
|
12
|
+
/** Re-checks the stored registry's candidates live instead of building a new one. */
|
|
13
|
+
readonly verify?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface ExploreReport {
|
|
16
|
+
readonly mode: 'explore' | 'verify';
|
|
17
|
+
readonly registryPath: string;
|
|
18
|
+
readonly elementCount: number;
|
|
19
|
+
readonly added: number;
|
|
20
|
+
readonly removed: number;
|
|
21
|
+
readonly degraded: readonly DegradedSelectorElement[];
|
|
22
|
+
readonly missingLocatorCount: number;
|
|
23
|
+
readonly blockedRequestCount: number;
|
|
24
|
+
}
|
|
25
|
+
export declare function resolvePolicy(config: Config, given: string | undefined): SelectorPolicy;
|
|
26
|
+
export declare function resolveEnvironment(config: Config, name: string | undefined): {
|
|
27
|
+
readonly name: string;
|
|
28
|
+
readonly config: EnvironmentConfig;
|
|
29
|
+
};
|
|
30
|
+
export declare function resolveIdentity(context: EngineContext, config: Config, options: {
|
|
31
|
+
readonly identity?: string;
|
|
32
|
+
readonly cdpEndpointUrl?: string;
|
|
33
|
+
}): ExplorerIdentity | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Writes a fresh (or merged) selector registry, the generated locator module and the
|
|
36
|
+
* missing-test-id report, and registers all three in the manifest. Exported so a CLI-only
|
|
37
|
+
* pick-mode session — which gathers `elements` interactively and is not exposed as an MCP tool
|
|
38
|
+
* (AGENTS.md 12.4: safe mode aside, a human physically clicking through a headed browser is not
|
|
39
|
+
* something an agent can drive over stdio) — shares this persistence tail with `runExplore`
|
|
40
|
+
* instead of duplicating it.
|
|
41
|
+
*/
|
|
42
|
+
export declare function persistExploreResult(context: EngineContext, store: QaStore, manifest: ManifestStore, previous: SelectorRegistry | undefined, elements: readonly SelectorElement[], blockedRequestCount: number): Promise<ExploreReport>;
|
|
43
|
+
/**
|
|
44
|
+
* `qa explore` / MCP `qa_explore` (P2-05): builds the selector registry (development plan section
|
|
45
|
+
* 6.3) by crawling, then merges in static source analysis (`--static`) when asked. `--verify`
|
|
46
|
+
* skips building anything: it re-checks every stored, non-deprecated element's primary candidate
|
|
47
|
+
* against the live page it was found on and fails (`degraded` non-empty) when one no longer
|
|
48
|
+
* resolves as well as it did when last recorded — the signal a stale selector (e.g. a renamed test
|
|
49
|
+
* ID) needs. Manual pick-mode capture is a separate, CLI-only entry point (see
|
|
50
|
+
* `persistExploreResult`).
|
|
51
|
+
*/
|
|
52
|
+
export declare function runExplore(context: EngineContext, options?: ExploreOptions): Promise<ExploreReport>;
|
|
53
|
+
//# sourceMappingURL=explore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explore.d.ts","sourceRoot":"","sources":["../../src/operations/explore.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,aAAa,EAEb,OAAO,EAIP,KAAK,aAAa,EAEnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAIL,KAAK,MAAM,EACX,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACtB,MAAM,qBAAqB,CAAC;AAW7B,OAAO,EAAuB,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAG5E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAY7E,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,qFAAqF;IACrF,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAC;IACpC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,SAAS,uBAAuB,EAAE,CAAC;IACtD,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;CACtC;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,cAAc,CAWvF;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GAAG,SAAS,GACvB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAA;CAAE,CA4B/D;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE;IAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,GACxE,gBAAgB,GAAG,SAAS,CAe9B;AA8ID;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,aAAa,EACvB,QAAQ,EAAE,gBAAgB,GAAG,SAAS,EACtC,QAAQ,EAAE,SAAS,eAAe,EAAE,EACpC,mBAAmB,EAAE,MAAM,GAC1B,OAAO,CAAC,aAAa,CAAC,CAsCxB;AAED;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,aAAa,CAAC,CAgBxB"}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
// Copyright The QA-AI-STLC Authors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { ManifestStore, QaError, QaStore, loadConfig, resolveRelativePath, toRelativePath, } from '@qa-ai-stlc/core';
|
|
4
|
+
import { SCHEMA_VERSION, SelectorPolicySchema, SelectorRegistrySchema, } from '@qa-ai-stlc/schemas';
|
|
5
|
+
import { analyzePages } from '../analyze-pages.js';
|
|
6
|
+
import { analyzeStaticSource } from '../analyze-static-source.js';
|
|
7
|
+
import { buildMissingTestIdReport } from '../build-missing-test-id-report.js';
|
|
8
|
+
import { buildSelectorRegistry, diffSelectorRegistry, mergeSelectorRegistry, } from '../build-selector-registry.js';
|
|
9
|
+
import { crawl } from '../crawl.js';
|
|
10
|
+
import { generateLocatorModule } from '../generate-locator-module.js';
|
|
11
|
+
import { resolveStorageState } from '../identity.js';
|
|
12
|
+
import { readPackageVersion } from '../package-version.js';
|
|
13
|
+
import { scoreLocatorStability } from '../stability-scoring.js';
|
|
14
|
+
const REGISTRY_PATH = 'selectors/registry.json';
|
|
15
|
+
const MISSING_TEST_ID_REPORT_PATH = 'selectors/missing-test-ids.json';
|
|
16
|
+
const LOCATOR_MODULE_PATH = 'tests/qa/locators.ts';
|
|
17
|
+
// EJS is included alongside the three frameworks the development plan names (React/Angular/Vue):
|
|
18
|
+
// its templates are plain HTML, the same literal-attribute shape analyzeStaticSource looks for in
|
|
19
|
+
// any of the three, and the demo app (the only fixture this operation is validated against) is
|
|
20
|
+
// server-rendered EJS.
|
|
21
|
+
const STATIC_SOURCE_EXTENSIONS = ['.tsx', '.jsx', '.ts', '.js', '.vue', '.html', '.ejs'];
|
|
22
|
+
export function resolvePolicy(config, given) {
|
|
23
|
+
if (given === undefined) {
|
|
24
|
+
return config.selectors.policy;
|
|
25
|
+
}
|
|
26
|
+
const result = SelectorPolicySchema.safeParse(given);
|
|
27
|
+
if (!result.success) {
|
|
28
|
+
throw new QaError('EXPLORE_POLICY_INVALID', `"${given}" is not a known selector policy`, {
|
|
29
|
+
remediation: `Use one of: ${SelectorPolicySchema.options.join(', ')}.`,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return result.data;
|
|
33
|
+
}
|
|
34
|
+
export function resolveEnvironment(config, name) {
|
|
35
|
+
const names = Object.keys(config.environments);
|
|
36
|
+
if (name !== undefined) {
|
|
37
|
+
const environment = config.environments[name];
|
|
38
|
+
if (environment === undefined) {
|
|
39
|
+
throw new QaError('EXPLORE_ENVIRONMENT_UNKNOWN', `No environment named "${name}" in config.yaml`, {
|
|
40
|
+
remediation: `Use one of: ${names.join(', ')}.`,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return { name, config: environment };
|
|
44
|
+
}
|
|
45
|
+
const [onlyEntry] = Object.entries(config.environments);
|
|
46
|
+
if (names.length === 1 && onlyEntry !== undefined) {
|
|
47
|
+
const [onlyName, onlyEnvironment] = onlyEntry;
|
|
48
|
+
return { name: onlyName, config: onlyEnvironment };
|
|
49
|
+
}
|
|
50
|
+
throw new QaError('EXPLORE_ENVIRONMENT_AMBIGUOUS', names.length === 0
|
|
51
|
+
? 'config.yaml defines no environments'
|
|
52
|
+
: 'No --environment given and config.yaml defines more than one', {
|
|
53
|
+
remediation: names.length === 0
|
|
54
|
+
? 'Add an environment to config.yaml.'
|
|
55
|
+
: `Pass --environment, one of: ${names.join(', ')}.`,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
export function resolveIdentity(context, config, options) {
|
|
59
|
+
if (options.identity === undefined) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
const identityConfig = config.identities[options.identity];
|
|
63
|
+
if (identityConfig === undefined) {
|
|
64
|
+
throw new QaError('EXPLORE_IDENTITY_UNKNOWN', `No identity named "${options.identity}" in config.yaml`, {
|
|
65
|
+
remediation: `Use one of: ${Object.keys(config.identities).join(', ')}.`,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
config: identityConfig,
|
|
70
|
+
env: context.env,
|
|
71
|
+
...(options.cdpEndpointUrl !== undefined ? { cdpEndpointUrl: options.cdpEndpointUrl } : {}),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
async function readStaticSourceFiles(fs, projectRoot, sourcePath) {
|
|
75
|
+
const absoluteSourceDir = resolveRelativePath(projectRoot, sourcePath);
|
|
76
|
+
const absolutePaths = (await fs.listFiles(absoluteSourceDir)).filter((path) => STATIC_SOURCE_EXTENSIONS.some((extension) => path.endsWith(extension)));
|
|
77
|
+
return Promise.all(absolutePaths.map(async (absolutePath) => ({
|
|
78
|
+
filePath: toRelativePath(projectRoot, absolutePath),
|
|
79
|
+
content: await fs.readFile(absolutePath),
|
|
80
|
+
})));
|
|
81
|
+
}
|
|
82
|
+
async function runCrawlAndBuild(context, config, options) {
|
|
83
|
+
const environment = resolveEnvironment(config, options.environment);
|
|
84
|
+
const identity = resolveIdentity(context, config, options);
|
|
85
|
+
const policy = resolvePolicy(config, options.policy);
|
|
86
|
+
const crawlResult = await crawl({
|
|
87
|
+
startUrl: environment.config.baseUrl,
|
|
88
|
+
allowlist: environment.config.allowlist,
|
|
89
|
+
browserLauncher: context.browserLauncher,
|
|
90
|
+
...(identity !== undefined ? { identity } : {}),
|
|
91
|
+
...(options.maxPages !== undefined ? { maxPages: options.maxPages } : {}),
|
|
92
|
+
});
|
|
93
|
+
const urls = crawlResult.routeMap.routes.map((route) => route.url);
|
|
94
|
+
const { pageModelSet, blockedRequestCount: analyzeBlocked } = await analyzePages({
|
|
95
|
+
urls,
|
|
96
|
+
browserLauncher: context.browserLauncher,
|
|
97
|
+
...(identity !== undefined ? { identity } : {}),
|
|
98
|
+
});
|
|
99
|
+
const { registry, blockedRequestCount: buildBlocked } = await buildSelectorRegistry({
|
|
100
|
+
pageModelSet,
|
|
101
|
+
browserLauncher: context.browserLauncher,
|
|
102
|
+
...(identity !== undefined ? { identity } : {}),
|
|
103
|
+
policy,
|
|
104
|
+
});
|
|
105
|
+
const elements = [...registry.elements];
|
|
106
|
+
if (options.static === true) {
|
|
107
|
+
if (config.source === undefined) {
|
|
108
|
+
throw new QaError('EXPLORE_STATIC_SOURCE_MISSING', '--static was given but config.yaml has no source.path', {
|
|
109
|
+
remediation: 'Set source.path in config.yaml to the application checkout to scan.',
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
const files = await readStaticSourceFiles(context.fs, context.projectRoot, config.source.path);
|
|
113
|
+
elements.push(...analyzeStaticSource({ files, clock: context.clock }).elements);
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
elements,
|
|
117
|
+
blockedRequestCount: crawlResult.blockedRequestCount + analyzeBlocked + buildBlocked,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
async function runVerify(context, store, config, options) {
|
|
121
|
+
const exists = await store.pathExists(REGISTRY_PATH);
|
|
122
|
+
if (!exists) {
|
|
123
|
+
throw new QaError('EXPLORE_NO_REGISTRY', 'No selector registry found to verify', {
|
|
124
|
+
remediation: 'Run "qa explore" first to build a registry.',
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
const stored = await store.readJson(REGISTRY_PATH, SelectorRegistrySchema);
|
|
128
|
+
const identity = resolveIdentity(context, config, options);
|
|
129
|
+
const storageState = await resolveStorageState(context.browserLauncher, identity);
|
|
130
|
+
const checkable = stored.elements.filter((element) => element.deprecatedAt === undefined &&
|
|
131
|
+
element.pageUrl !== undefined &&
|
|
132
|
+
element.locatorCandidates.length > 0);
|
|
133
|
+
const elementsByPageUrl = new Map();
|
|
134
|
+
for (const element of checkable) {
|
|
135
|
+
// eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style -- filtered above
|
|
136
|
+
const pageUrl = element.pageUrl;
|
|
137
|
+
const group = elementsByPageUrl.get(pageUrl);
|
|
138
|
+
if (group === undefined) {
|
|
139
|
+
elementsByPageUrl.set(pageUrl, [element]);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
group.push(element);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const degraded = [];
|
|
146
|
+
const browser = await context.browserLauncher.launch();
|
|
147
|
+
try {
|
|
148
|
+
const browserContext = await browser.newContext(storageState === undefined ? {} : { storageState });
|
|
149
|
+
const page = await browserContext.newPage();
|
|
150
|
+
for (const [pageUrl, elements] of elementsByPageUrl) {
|
|
151
|
+
await page.goto(pageUrl);
|
|
152
|
+
for (const element of elements) {
|
|
153
|
+
// eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style -- filtered above
|
|
154
|
+
const primary = element.locatorCandidates[0];
|
|
155
|
+
const currentScore = await scoreLocatorStability(page, primary);
|
|
156
|
+
if (currentScore < element.stabilityScore) {
|
|
157
|
+
degraded.push({
|
|
158
|
+
elementId: element.elementId,
|
|
159
|
+
previousScore: element.stabilityScore,
|
|
160
|
+
currentScore,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
finally {
|
|
167
|
+
await browser.close();
|
|
168
|
+
}
|
|
169
|
+
const missingLocatorCount = generateLocatorModule(stored, { generatorVersion: readPackageVersion() })
|
|
170
|
+
.missingLocators.length;
|
|
171
|
+
return {
|
|
172
|
+
mode: 'verify',
|
|
173
|
+
registryPath: REGISTRY_PATH,
|
|
174
|
+
elementCount: stored.elements.length,
|
|
175
|
+
added: 0,
|
|
176
|
+
removed: 0,
|
|
177
|
+
degraded,
|
|
178
|
+
missingLocatorCount,
|
|
179
|
+
blockedRequestCount: 0,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Writes a fresh (or merged) selector registry, the generated locator module and the
|
|
184
|
+
* missing-test-id report, and registers all three in the manifest. Exported so a CLI-only
|
|
185
|
+
* pick-mode session — which gathers `elements` interactively and is not exposed as an MCP tool
|
|
186
|
+
* (AGENTS.md 12.4: safe mode aside, a human physically clicking through a headed browser is not
|
|
187
|
+
* something an agent can drive over stdio) — shares this persistence tail with `runExplore`
|
|
188
|
+
* instead of duplicating it.
|
|
189
|
+
*/
|
|
190
|
+
export async function persistExploreResult(context, store, manifest, previous, elements, blockedRequestCount) {
|
|
191
|
+
const generatedAt = context.clock.now().toISOString();
|
|
192
|
+
const fresh = { schemaVersion: SCHEMA_VERSION, generatedAt, elements: [...elements] };
|
|
193
|
+
const merged = previous === undefined ? fresh : mergeSelectorRegistry(previous, fresh, generatedAt);
|
|
194
|
+
await store.writeJson(REGISTRY_PATH, merged);
|
|
195
|
+
await manifest.register(REGISTRY_PATH, JSON.stringify(merged));
|
|
196
|
+
const moduleResult = generateLocatorModule(merged, { generatorVersion: readPackageVersion() });
|
|
197
|
+
await context.fs.mkdir(resolveRelativePath(context.projectRoot, 'tests/qa'));
|
|
198
|
+
await context.fs.writeFile(resolveRelativePath(context.projectRoot, LOCATOR_MODULE_PATH), moduleResult.source);
|
|
199
|
+
await manifest.register(LOCATOR_MODULE_PATH, moduleResult.source);
|
|
200
|
+
const missingTestIdReport = buildMissingTestIdReport(merged);
|
|
201
|
+
await store.writeJson(MISSING_TEST_ID_REPORT_PATH, missingTestIdReport);
|
|
202
|
+
await manifest.register(MISSING_TEST_ID_REPORT_PATH, JSON.stringify(missingTestIdReport));
|
|
203
|
+
// Diffed against the fresh, unmerged registry, not the merged one: a merge always keeps an
|
|
204
|
+
// element the fresh run no longer found (deprecating it in place) rather than dropping it, so
|
|
205
|
+
// diffing the merged result would never show a "removed" element at all.
|
|
206
|
+
const diff = previous === undefined
|
|
207
|
+
? { added: fresh.elements, removed: [], degraded: [] }
|
|
208
|
+
: diffSelectorRegistry(previous, fresh);
|
|
209
|
+
return {
|
|
210
|
+
mode: 'explore',
|
|
211
|
+
registryPath: REGISTRY_PATH,
|
|
212
|
+
elementCount: merged.elements.length,
|
|
213
|
+
added: diff.added.length,
|
|
214
|
+
removed: diff.removed.length,
|
|
215
|
+
degraded: diff.degraded,
|
|
216
|
+
missingLocatorCount: moduleResult.missingLocators.length,
|
|
217
|
+
blockedRequestCount,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* `qa explore` / MCP `qa_explore` (P2-05): builds the selector registry (development plan section
|
|
222
|
+
* 6.3) by crawling, then merges in static source analysis (`--static`) when asked. `--verify`
|
|
223
|
+
* skips building anything: it re-checks every stored, non-deprecated element's primary candidate
|
|
224
|
+
* against the live page it was found on and fails (`degraded` non-empty) when one no longer
|
|
225
|
+
* resolves as well as it did when last recorded — the signal a stale selector (e.g. a renamed test
|
|
226
|
+
* ID) needs. Manual pick-mode capture is a separate, CLI-only entry point (see
|
|
227
|
+
* `persistExploreResult`).
|
|
228
|
+
*/
|
|
229
|
+
export async function runExplore(context, options = {}) {
|
|
230
|
+
const store = new QaStore({ projectRoot: context.projectRoot, fs: context.fs });
|
|
231
|
+
const manifest = new ManifestStore({ store, clock: context.clock });
|
|
232
|
+
const config = await loadConfig(store);
|
|
233
|
+
if (options.verify === true) {
|
|
234
|
+
return runVerify(context, store, config, options);
|
|
235
|
+
}
|
|
236
|
+
const previous = (await store.pathExists(REGISTRY_PATH))
|
|
237
|
+
? await store.readJson(REGISTRY_PATH, SelectorRegistrySchema)
|
|
238
|
+
: undefined;
|
|
239
|
+
const { elements, blockedRequestCount } = await runCrawlAndBuild(context, config, options);
|
|
240
|
+
return persistExploreResult(context, store, manifest, previous, elements, blockedRequestCount);
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=explore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explore.js","sourceRoot":"","sources":["../../src/operations/explore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-version.d.ts","sourceRoot":"","sources":["../src/package-version.ts"],"names":[],"mappings":"AAKA,wFAAwF;AACxF,wBAAgB,kBAAkB,IAAI,MAAM,CAI3C"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Copyright The QA-AI-STLC Authors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
4
|
+
/** The published version of this explorer package, read from its own `package.json`. */
|
|
5
|
+
export function readPackageVersion() {
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
const packageJson = require('../package.json');
|
|
8
|
+
return packageJson.version;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=package-version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-version.js","sourceRoot":"","sources":["../src/package-version.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,wFAAwF;AACxF,MAAM,UAAU,kBAAkB;IAChC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAiC,CAAC;IAC/E,OAAO,WAAW,CAAC,OAAO,CAAC;AAC7B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qa-ai-stlc/explorer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.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.9.0",
|
|
32
|
+
"@qa-ai-stlc/schemas": "0.8.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@qa-ai-stlc/test-utils": "0.0.0"
|