@yasserkhanorg/e2e-agents 0.5.3 → 0.5.4
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai_mapping.d.ts","sourceRoot":"","sources":["../../src/agent/ai_mapping.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,aAAa,CAAC;AACvD,OAAO,KAAK,EAAC,YAAY,EAAE,QAAQ,EAAC,MAAM,YAAY,CAAC;AA2BvD,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB;
|
|
1
|
+
{"version":3,"file":"ai_mapping.d.ts","sourceRoot":"","sources":["../../src/agent/ai_mapping.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,aAAa,CAAC;AACvD,OAAO,KAAK,EAAC,YAAY,EAAE,QAAQ,EAAC,MAAM,YAAY,CAAC;AA2BvD,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB;AAiOD,wBAAsB,iBAAiB,CACnC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,qBAAqB,EAC7B,KAAK,EAAE,UAAU,EAAE,EACnB,KAAK,EAAE,QAAQ,EAAE,GAClB,OAAO,CAAC,eAAe,CAAC,CAqN1B"}
|
package/dist/agent/ai_mapping.js
CHANGED
|
@@ -164,7 +164,19 @@ function selectCandidateTests(flows, tests, maxCandidateTests) {
|
|
|
164
164
|
.sort((a, b) => b.score - a.score || a.path.localeCompare(b.path))
|
|
165
165
|
.slice(0, perFlowLimit);
|
|
166
166
|
if (strongCandidates.length === 0) {
|
|
167
|
-
if (
|
|
167
|
+
// Exact-name fallback: if the flow ID has no effective keywords (all tokens are
|
|
168
|
+
// low-signal, e.g. view_user_group_modal), look for a test whose path contains
|
|
169
|
+
// the exact flow ID as a directory name or filename without extension.
|
|
170
|
+
const exactMatchPath = normalizedTests.find((testPath) => {
|
|
171
|
+
const segments = testPath.split('/');
|
|
172
|
+
return segments.some((seg) => seg === flow.id || seg.replace(/\.spec\.[tj]sx?$/, '') === flow.id);
|
|
173
|
+
});
|
|
174
|
+
if (exactMatchPath) {
|
|
175
|
+
byFlow.set(flow.id, new Set([exactMatchPath]));
|
|
176
|
+
evidence.push({ flowId: flow.id, candidates: [{ path: exactMatchPath, score: 999, matchedKeywords: [flow.id] }] });
|
|
177
|
+
selected.add(exactMatchPath);
|
|
178
|
+
}
|
|
179
|
+
else if (scored.length > 0) {
|
|
168
180
|
warnings.push(`AI mapping withheld weak path-only candidates for ${flow.id}; traceability evidence is required to reuse existing tests.`);
|
|
169
181
|
}
|
|
170
182
|
continue;
|
|
@@ -359,6 +371,25 @@ async function mapAITestsToFlows(appRoot, testsRoot, config, flows, tests) {
|
|
|
359
371
|
matchedTests.add(testPath);
|
|
360
372
|
}
|
|
361
373
|
}
|
|
374
|
+
// Post-AI exact-name fallback: for any flow still uncovered, if a candidate test
|
|
375
|
+
// was matched by exact name (score 999), map it directly regardless of AI confidence.
|
|
376
|
+
for (const flow of prioritizedFlows) {
|
|
377
|
+
if (mapped.has(flow.id)) {
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
const candidates = candidateSelection.byFlow.get(flow.id);
|
|
381
|
+
if (!candidates) {
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
const exactMatch = Array.from(candidates).find((testPath) => {
|
|
385
|
+
const segments = testPath.split('/');
|
|
386
|
+
return segments.some((seg) => seg === flow.id || seg.replace(/\.spec\.[tj]sx?$/, '') === flow.id);
|
|
387
|
+
});
|
|
388
|
+
if (exactMatch) {
|
|
389
|
+
mapped.set(flow.id, [exactMatch]);
|
|
390
|
+
matchedTests.add(exactMatch);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
362
393
|
const coverage = buildCoverage(flows, mapped);
|
|
363
394
|
if (mapped.size === 0) {
|
|
364
395
|
warnings.push(`AI mapping returned no valid test mappings (${provider.name}).`);
|
|
@@ -161,7 +161,19 @@ function selectCandidateTests(flows, tests, maxCandidateTests) {
|
|
|
161
161
|
.sort((a, b) => b.score - a.score || a.path.localeCompare(b.path))
|
|
162
162
|
.slice(0, perFlowLimit);
|
|
163
163
|
if (strongCandidates.length === 0) {
|
|
164
|
-
if (
|
|
164
|
+
// Exact-name fallback: if the flow ID has no effective keywords (all tokens are
|
|
165
|
+
// low-signal, e.g. view_user_group_modal), look for a test whose path contains
|
|
166
|
+
// the exact flow ID as a directory name or filename without extension.
|
|
167
|
+
const exactMatchPath = normalizedTests.find((testPath) => {
|
|
168
|
+
const segments = testPath.split('/');
|
|
169
|
+
return segments.some((seg) => seg === flow.id || seg.replace(/\.spec\.[tj]sx?$/, '') === flow.id);
|
|
170
|
+
});
|
|
171
|
+
if (exactMatchPath) {
|
|
172
|
+
byFlow.set(flow.id, new Set([exactMatchPath]));
|
|
173
|
+
evidence.push({ flowId: flow.id, candidates: [{ path: exactMatchPath, score: 999, matchedKeywords: [flow.id] }] });
|
|
174
|
+
selected.add(exactMatchPath);
|
|
175
|
+
}
|
|
176
|
+
else if (scored.length > 0) {
|
|
165
177
|
warnings.push(`AI mapping withheld weak path-only candidates for ${flow.id}; traceability evidence is required to reuse existing tests.`);
|
|
166
178
|
}
|
|
167
179
|
continue;
|
|
@@ -356,6 +368,25 @@ export async function mapAITestsToFlows(appRoot, testsRoot, config, flows, tests
|
|
|
356
368
|
matchedTests.add(testPath);
|
|
357
369
|
}
|
|
358
370
|
}
|
|
371
|
+
// Post-AI exact-name fallback: for any flow still uncovered, if a candidate test
|
|
372
|
+
// was matched by exact name (score 999), map it directly regardless of AI confidence.
|
|
373
|
+
for (const flow of prioritizedFlows) {
|
|
374
|
+
if (mapped.has(flow.id)) {
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
const candidates = candidateSelection.byFlow.get(flow.id);
|
|
378
|
+
if (!candidates) {
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
const exactMatch = Array.from(candidates).find((testPath) => {
|
|
382
|
+
const segments = testPath.split('/');
|
|
383
|
+
return segments.some((seg) => seg === flow.id || seg.replace(/\.spec\.[tj]sx?$/, '') === flow.id);
|
|
384
|
+
});
|
|
385
|
+
if (exactMatch) {
|
|
386
|
+
mapped.set(flow.id, [exactMatch]);
|
|
387
|
+
matchedTests.add(exactMatch);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
359
390
|
const coverage = buildCoverage(flows, mapped);
|
|
360
391
|
if (mapped.size === 0) {
|
|
361
392
|
warnings.push(`AI mapping returned no valid test mappings (${provider.name}).`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yasserkhanorg/e2e-agents",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.4",
|
|
4
4
|
"description": "Pluggable LLM provider library for AI-powered test automation. Use Claude, Ollama, or your own LLM. Integrate with Playwright, Jest, or any test framework. MCP server for test agents, cost tracking, and hybrid provider mode.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|