@yasserkhanorg/e2e-agents 1.10.0 → 1.10.2
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/README.md +116 -99
- package/dist/agent/config.d.ts +1 -1
- package/dist/agent/config.d.ts.map +1 -1
- package/dist/agent/config.js +6 -1
- package/dist/cache/cached_provider.d.ts +4 -0
- package/dist/cache/cached_provider.d.ts.map +1 -1
- package/dist/cache/cached_provider.js +3 -0
- package/dist/cli/commands/crew.d.ts.map +1 -1
- package/dist/cli/commands/crew.js +1 -0
- package/dist/cli/commands/gate.d.ts.map +1 -1
- package/dist/cli/commands/gate.js +4 -1
- package/dist/cli/commands/impact.d.ts.map +1 -1
- package/dist/cli/commands/impact.js +7 -0
- package/dist/cli/commands/init.js +5 -5
- package/dist/cli/commands/llm_health.d.ts.map +1 -1
- package/dist/cli/commands/llm_health.js +10 -26
- package/dist/cli/defaults.d.ts.map +1 -1
- package/dist/cli/defaults.js +47 -0
- package/dist/cli/parse_args.d.ts.map +1 -1
- package/dist/cli/parse_args.js +3 -1
- package/dist/cli/types.d.ts +1 -0
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/cli/usage.d.ts.map +1 -1
- package/dist/cli/usage.js +28 -14
- package/dist/cli.js +6 -2
- package/dist/esm/agent/config.js +6 -1
- package/dist/esm/cache/cached_provider.js +3 -0
- package/dist/esm/cli/commands/crew.js +1 -0
- package/dist/esm/cli/commands/gate.js +4 -1
- package/dist/esm/cli/commands/impact.js +7 -0
- package/dist/esm/cli/commands/init.js +5 -5
- package/dist/esm/cli/commands/llm_health.js +10 -26
- package/dist/esm/cli/defaults.js +47 -0
- package/dist/esm/cli/parse_args.js +3 -1
- package/dist/esm/cli/usage.js +28 -14
- package/dist/esm/cli.js +6 -2
- package/dist/esm/prompts/coverage.js +2 -2
- package/dist/esm/prompts/cross-impact.js +1 -1
- package/dist/esm/prompts/generation.js +4 -4
- package/dist/esm/prompts/heal.js +4 -4
- package/dist/esm/prompts/impact.js +1 -1
- package/dist/esm/prompts/test-designer.js +1 -1
- package/dist/esm/provider_factory.js +17 -0
- package/dist/index.d.ts +1 -1
- package/dist/prompts/coverage.js +2 -2
- package/dist/prompts/cross-impact.js +1 -1
- package/dist/prompts/generation.js +4 -4
- package/dist/prompts/heal.js +4 -4
- package/dist/prompts/impact.js +1 -1
- package/dist/prompts/test-designer.js +1 -1
- package/dist/provider_factory.d.ts.map +1 -1
- package/dist/provider_factory.js +17 -0
- package/dist/provider_interface.d.ts +7 -0
- package/dist/provider_interface.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/cli/defaults.js
CHANGED
|
@@ -10,6 +10,42 @@ exports.resolveDefaults = resolveDefaults;
|
|
|
10
10
|
const fs_1 = require("fs");
|
|
11
11
|
const child_process_1 = require("child_process");
|
|
12
12
|
const path_1 = require("path");
|
|
13
|
+
function detectPytestFramework(appPath) {
|
|
14
|
+
const resolvedPath = (0, path_1.resolve)(appPath);
|
|
15
|
+
const pytestIni = (0, path_1.join)(resolvedPath, 'pytest.ini');
|
|
16
|
+
if ((0, fs_1.existsSync)(pytestIni)) {
|
|
17
|
+
return 'pytest';
|
|
18
|
+
}
|
|
19
|
+
const conftest = (0, path_1.join)(resolvedPath, 'conftest.py');
|
|
20
|
+
if ((0, fs_1.existsSync)(conftest)) {
|
|
21
|
+
return 'pytest';
|
|
22
|
+
}
|
|
23
|
+
const pyproject = (0, path_1.join)(resolvedPath, 'pyproject.toml');
|
|
24
|
+
if ((0, fs_1.existsSync)(pyproject)) {
|
|
25
|
+
try {
|
|
26
|
+
const content = (0, fs_1.readFileSync)(pyproject, 'utf-8');
|
|
27
|
+
if (content.includes('pytest')) {
|
|
28
|
+
return 'pytest';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// ignore malformed or unreadable file
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const setupCfg = (0, path_1.join)(resolvedPath, 'setup.cfg');
|
|
36
|
+
if ((0, fs_1.existsSync)(setupCfg)) {
|
|
37
|
+
try {
|
|
38
|
+
const content = (0, fs_1.readFileSync)(setupCfg, 'utf-8');
|
|
39
|
+
if (content.includes('[tool:pytest]') || content.includes('[pytest]')) {
|
|
40
|
+
return 'pytest';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// ignore malformed or unreadable file
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
13
49
|
/**
|
|
14
50
|
* Detect the test framework from package.json dependencies.
|
|
15
51
|
*/
|
|
@@ -17,6 +53,10 @@ function detectFramework(appPath) {
|
|
|
17
53
|
const resolvedPath = (0, path_1.resolve)(appPath);
|
|
18
54
|
const pkgPath = (0, path_1.join)(resolvedPath, 'package.json');
|
|
19
55
|
if (!(0, fs_1.existsSync)(pkgPath)) {
|
|
56
|
+
const pytestFramework = detectPytestFramework(resolvedPath);
|
|
57
|
+
if (pytestFramework) {
|
|
58
|
+
return pytestFramework;
|
|
59
|
+
}
|
|
20
60
|
return 'auto';
|
|
21
61
|
}
|
|
22
62
|
try {
|
|
@@ -28,6 +68,9 @@ function detectFramework(appPath) {
|
|
|
28
68
|
if (allDeps.cypress) {
|
|
29
69
|
return 'cypress';
|
|
30
70
|
}
|
|
71
|
+
if (allDeps.supertest) {
|
|
72
|
+
return 'supertest';
|
|
73
|
+
}
|
|
31
74
|
if (allDeps['selenium-webdriver'] || allDeps.webdriverio) {
|
|
32
75
|
return 'selenium';
|
|
33
76
|
}
|
|
@@ -35,6 +78,10 @@ function detectFramework(appPath) {
|
|
|
35
78
|
catch {
|
|
36
79
|
// ignore malformed package.json
|
|
37
80
|
}
|
|
81
|
+
const pytestFramework = detectPytestFramework(resolvedPath);
|
|
82
|
+
if (pytestFramework) {
|
|
83
|
+
return pytestFramework;
|
|
84
|
+
}
|
|
38
85
|
return 'auto';
|
|
39
86
|
}
|
|
40
87
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse_args.d.ts","sourceRoot":"","sources":["../../src/cli/parse_args.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAU,UAAU,EAAC,MAAM,YAAY,CAAC;AAEpD,eAAO,MAAM,iBAAiB,UAA8D,CAAC;AAE7F,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAmBlF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAmBtE;
|
|
1
|
+
{"version":3,"file":"parse_args.d.ts","sourceRoot":"","sources":["../../src/cli/parse_args.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAU,UAAU,EAAC,MAAM,YAAY,CAAC;AAEpD,eAAO,MAAM,iBAAiB,UAA8D,CAAC;AAE7F,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAmBlF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAmBtE;AA6JD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAyFpD"}
|
package/dist/cli/parse_args.js
CHANGED
|
@@ -133,6 +133,7 @@ const FLAGS = {
|
|
|
133
133
|
'--patterns': { key: 'testPatterns', type: 'csv' },
|
|
134
134
|
'--flow-patterns': { key: 'flowPatterns', type: 'csv' },
|
|
135
135
|
'--flow-exclude': { key: 'flowExclude', type: 'csv' },
|
|
136
|
+
'--plugins': { key: 'plugins', type: 'csv' },
|
|
136
137
|
'--policy-risky-patterns': { key: 'policyRiskyPatterns', type: 'csv' },
|
|
137
138
|
'--policy-block-actions': {
|
|
138
139
|
key: 'policyBlockActions',
|
|
@@ -180,7 +181,8 @@ function parseArgs(argv) {
|
|
|
180
181
|
if (COMMANDS.has(command)) {
|
|
181
182
|
parsed.command = command;
|
|
182
183
|
}
|
|
183
|
-
|
|
184
|
+
const startIndex = parsed.command ? 1 : 0;
|
|
185
|
+
for (let i = startIndex; i < argv.length; i += 1) {
|
|
184
186
|
const arg = argv[i];
|
|
185
187
|
const canonical = ALIAS_MAP[arg];
|
|
186
188
|
if (!canonical) {
|
package/dist/cli/types.d.ts
CHANGED
package/dist/cli/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/cli/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/cli/types.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/usage.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../src/cli/usage.ts"],"names":[],"mappings":"AAGA,wBAAgB,UAAU,IAAI,IAAI,
|
|
1
|
+
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../src/cli/usage.ts"],"names":[],"mappings":"AAGA,wBAAgB,UAAU,IAAI,IAAI,CAyGjC"}
|
package/dist/cli/usage.js
CHANGED
|
@@ -6,19 +6,32 @@ exports.printUsage = printUsage;
|
|
|
6
6
|
function printUsage() {
|
|
7
7
|
console.log([
|
|
8
8
|
'Usage:',
|
|
9
|
-
' e2e-ai-agents
|
|
10
|
-
'
|
|
11
|
-
'
|
|
12
|
-
'
|
|
13
|
-
'
|
|
14
|
-
'
|
|
15
|
-
'
|
|
16
|
-
'
|
|
17
|
-
'
|
|
18
|
-
'
|
|
19
|
-
'
|
|
20
|
-
'
|
|
21
|
-
'
|
|
9
|
+
' e2e-ai-agents <command> [options]',
|
|
10
|
+
'',
|
|
11
|
+
'Core CI workflow:',
|
|
12
|
+
' impact --path <app-root> [options]',
|
|
13
|
+
' plan --path <app-root> [options]',
|
|
14
|
+
' suggest --path <app-root> [options]',
|
|
15
|
+
' gate --path <app-root> --threshold <n> [--since <ref>]',
|
|
16
|
+
'',
|
|
17
|
+
'Optional AI workflow:',
|
|
18
|
+
' analyze --path <app-root> [--tests-root <path>] [--since <ref>] [--generate] [--generate-output <dir>] [--heal] [--heal-report <json>]',
|
|
19
|
+
' generate [--scenarios <path|json>] [--max-attempts <n>] [--dry-run]',
|
|
20
|
+
' heal --path <app-root> --traceability-report <json> [options]',
|
|
21
|
+
' finalize-generated-tests --path <app-root> [options]',
|
|
22
|
+
'',
|
|
23
|
+
'Setup and calibration:',
|
|
24
|
+
' init [--yes]',
|
|
25
|
+
' train --path <project-root> [--no-enrich] [--validate] [--since <ref>] [--pr <num>]',
|
|
26
|
+
' bootstrap --path <app-root> [options]',
|
|
27
|
+
' feedback --path <app-root> --feedback-input <json>',
|
|
28
|
+
' traceability-capture --path <app-root> --traceability-report <json>',
|
|
29
|
+
' traceability-ingest --path <app-root> --traceability-input <json>',
|
|
30
|
+
' cost-report [--path <app-root>]',
|
|
31
|
+
' llm-health',
|
|
32
|
+
'',
|
|
33
|
+
'Advanced / experimental:',
|
|
34
|
+
' crew --path <app-root> [--crew-workflow <name>] [--plugins <paths>]',
|
|
22
35
|
'',
|
|
23
36
|
'Options:',
|
|
24
37
|
' --config <path> Path to e2e-ai-agents.config.json (auto-discovered if present)',
|
|
@@ -26,10 +39,11 @@ function printUsage() {
|
|
|
26
39
|
' --profile <name> default | mattermost',
|
|
27
40
|
' --mattermost Shortcut for --profile mattermost',
|
|
28
41
|
' --tests-root <path> Path to tests root (optional)',
|
|
29
|
-
' --framework <name> auto | playwright | cypress | selenium',
|
|
42
|
+
' --framework <name> auto | playwright | cypress | pytest | supertest | selenium',
|
|
30
43
|
' --patterns <globs> Comma-separated test patterns',
|
|
31
44
|
' --flow-patterns <g> Comma-separated flow discovery patterns',
|
|
32
45
|
' --flow-exclude <g> Comma-separated flow exclude patterns',
|
|
46
|
+
' --plugins <paths> Comma-separated plugin module paths for crew workflows',
|
|
33
47
|
' --flow-catalog <path> Path to flow catalog JSON',
|
|
34
48
|
' --allow-fallback Allow impact analysis without diff',
|
|
35
49
|
' --pipeline Run Playwright AI pipeline for missing P0/P1 flows',
|
package/dist/cli.js
CHANGED
|
@@ -59,9 +59,13 @@ async function main() {
|
|
|
59
59
|
await (0, train_js_1.runTrainCommand)(args, autoConfig);
|
|
60
60
|
return;
|
|
61
61
|
}
|
|
62
|
-
if (args.help
|
|
62
|
+
if (args.help) {
|
|
63
63
|
(0, usage_js_1.printUsage)();
|
|
64
|
-
process.exit(
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
if (!args.command) {
|
|
67
|
+
(0, usage_js_1.printUsage)();
|
|
68
|
+
process.exit(1);
|
|
65
69
|
}
|
|
66
70
|
if (args.command === 'llm-health') {
|
|
67
71
|
await (0, llm_health_js_1.runLlmHealth)();
|
package/dist/esm/agent/config.js
CHANGED
|
@@ -335,7 +335,12 @@ function normalizeProfile(value) {
|
|
|
335
335
|
return undefined;
|
|
336
336
|
}
|
|
337
337
|
function normalizeFramework(value) {
|
|
338
|
-
if (value === 'auto' ||
|
|
338
|
+
if (value === 'auto' ||
|
|
339
|
+
value === 'playwright' ||
|
|
340
|
+
value === 'cypress' ||
|
|
341
|
+
value === 'pytest' ||
|
|
342
|
+
value === 'supertest' ||
|
|
343
|
+
value === 'selenium') {
|
|
339
344
|
return value;
|
|
340
345
|
}
|
|
341
346
|
return undefined;
|
|
@@ -65,6 +65,7 @@ export async function runCrewCommand(args, autoConfig) {
|
|
|
65
65
|
providerOverride: args.llmProvider,
|
|
66
66
|
budgetUSD: args.budgetUSD,
|
|
67
67
|
dryRun: degraded || args.dryRun,
|
|
68
|
+
plugins: args.plugins,
|
|
68
69
|
};
|
|
69
70
|
// Create orchestrator and register all agents
|
|
70
71
|
const orchestrator = new CrewOrchestrator();
|
|
@@ -17,7 +17,10 @@ export async function runGateCommand(args, autoConfig) {
|
|
|
17
17
|
console.error('Error: --path is required for gate command');
|
|
18
18
|
process.exit(1);
|
|
19
19
|
}
|
|
20
|
-
|
|
20
|
+
let threshold = args.gateThreshold ?? 80;
|
|
21
|
+
if (threshold > 0 && threshold < 1) {
|
|
22
|
+
threshold = threshold * 100;
|
|
23
|
+
}
|
|
21
24
|
const { config } = resolveConfig(process.cwd(), autoConfig, {
|
|
22
25
|
path: args.path,
|
|
23
26
|
profile: args.profile,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
2
2
|
// See LICENSE.txt for license information.
|
|
3
|
+
import { mkdirSync, writeFileSync } from 'fs';
|
|
4
|
+
import { join } from 'path';
|
|
3
5
|
import { getChangedFiles } from '../../agent/git.js';
|
|
4
6
|
import { analyzeImpact as analyzeImpactV2 } from '../../engine/impact_engine.js';
|
|
5
7
|
export function runImpactCommand(args, config) {
|
|
@@ -20,4 +22,9 @@ export function runImpactCommand(args, config) {
|
|
|
20
22
|
console.warn(` Warning: ${w}`);
|
|
21
23
|
}
|
|
22
24
|
}
|
|
25
|
+
const outputDir = join(reportRoot, '.e2e-ai-agents');
|
|
26
|
+
mkdirSync(outputDir, { recursive: true });
|
|
27
|
+
const planPath = join(outputDir, 'plan.json');
|
|
28
|
+
writeFileSync(planPath, JSON.stringify(impactResult, null, 2));
|
|
29
|
+
console.log(`Wrote ${planPath}`);
|
|
23
30
|
}
|
|
@@ -45,10 +45,10 @@ function buildConfig(answers) {
|
|
|
45
45
|
function printNextSteps() {
|
|
46
46
|
console.log('');
|
|
47
47
|
console.log(' Next steps:');
|
|
48
|
-
console.log(' 1.
|
|
49
|
-
console.log(' 2.
|
|
50
|
-
console.log(' 3.
|
|
51
|
-
console.log(' 4.
|
|
48
|
+
console.log(' 1. Start with impact analysis: npx e2e-ai-agents impact --path .');
|
|
49
|
+
console.log(' 2. Build a coverage plan: npx e2e-ai-agents plan --path .');
|
|
50
|
+
console.log(' 3. Optional AI setup: export ANTHROPIC_API_KEY=sk-ant-...');
|
|
51
|
+
console.log(' 4. Verify provider health: npx e2e-ai-agents llm-health');
|
|
52
52
|
console.log('');
|
|
53
53
|
}
|
|
54
54
|
export async function runInitCommand(yes = false) {
|
|
@@ -88,7 +88,7 @@ export async function runInitCommand(yes = false) {
|
|
|
88
88
|
try {
|
|
89
89
|
const appPath = await ask(rl, ' Path to your web app root', '.');
|
|
90
90
|
const detectedFramework = detectFramework(appPath);
|
|
91
|
-
const framework = await ask(rl, ' Test framework (auto | playwright | cypress | selenium)', detectedFramework);
|
|
91
|
+
const framework = await ask(rl, ' Test framework (auto | playwright | cypress | pytest | supertest | selenium)', detectedFramework);
|
|
92
92
|
const detectedTestsRoot = detectTestsRoot(appPath);
|
|
93
93
|
const testsRoot = await ask(rl, ' Path to tests root (relative to app root, "." if same)', detectedTestsRoot || '.');
|
|
94
94
|
const detectedBranch = detectGitDefaultBranch(appPath);
|
|
@@ -1,35 +1,19 @@
|
|
|
1
1
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
2
2
|
// See LICENSE.txt for license information.
|
|
3
|
-
import {
|
|
4
|
-
import { LLMProviderError } from '../../provider_interface.js';
|
|
3
|
+
import { LLMProviderFactory } from '../../provider_factory.js';
|
|
5
4
|
export async function runLlmHealth() {
|
|
6
|
-
if (!process.env.ANTHROPIC_API_KEY) {
|
|
7
|
-
console.error('ANTHROPIC_API_KEY is required for llm-health.');
|
|
8
|
-
process.exit(1);
|
|
9
|
-
}
|
|
10
|
-
const model = process.env.ANTHROPIC_MODEL || 'claude-sonnet-4-5-20250929';
|
|
11
|
-
const provider = new AnthropicProvider({
|
|
12
|
-
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
13
|
-
model,
|
|
14
|
-
});
|
|
15
5
|
try {
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
6
|
+
const provider = await LLMProviderFactory.createFromEnv();
|
|
7
|
+
const health = await provider.checkHealth();
|
|
8
|
+
if (!health.healthy) {
|
|
9
|
+
console.error(`${provider.name} failed: ${health.message}`);
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
console.log(`${provider.name} OK -> ${health.message}`);
|
|
19
13
|
}
|
|
20
14
|
catch (error) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
if (error.cause instanceof Error) {
|
|
24
|
-
console.error(`Cause: ${error.cause.message}`);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
else if (error instanceof Error) {
|
|
28
|
-
console.error(`Anthropic failed: ${error.message}`);
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
console.error(`Anthropic failed: ${String(error)}`);
|
|
32
|
-
}
|
|
15
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
16
|
+
console.error(`LLM health check failed: ${message}`);
|
|
33
17
|
process.exit(1);
|
|
34
18
|
}
|
|
35
19
|
}
|
package/dist/esm/cli/defaults.js
CHANGED
|
@@ -3,6 +3,42 @@
|
|
|
3
3
|
import { existsSync, readFileSync } from 'fs';
|
|
4
4
|
import { execFileSync } from 'child_process';
|
|
5
5
|
import { join, resolve } from 'path';
|
|
6
|
+
function detectPytestFramework(appPath) {
|
|
7
|
+
const resolvedPath = resolve(appPath);
|
|
8
|
+
const pytestIni = join(resolvedPath, 'pytest.ini');
|
|
9
|
+
if (existsSync(pytestIni)) {
|
|
10
|
+
return 'pytest';
|
|
11
|
+
}
|
|
12
|
+
const conftest = join(resolvedPath, 'conftest.py');
|
|
13
|
+
if (existsSync(conftest)) {
|
|
14
|
+
return 'pytest';
|
|
15
|
+
}
|
|
16
|
+
const pyproject = join(resolvedPath, 'pyproject.toml');
|
|
17
|
+
if (existsSync(pyproject)) {
|
|
18
|
+
try {
|
|
19
|
+
const content = readFileSync(pyproject, 'utf-8');
|
|
20
|
+
if (content.includes('pytest')) {
|
|
21
|
+
return 'pytest';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// ignore malformed or unreadable file
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const setupCfg = join(resolvedPath, 'setup.cfg');
|
|
29
|
+
if (existsSync(setupCfg)) {
|
|
30
|
+
try {
|
|
31
|
+
const content = readFileSync(setupCfg, 'utf-8');
|
|
32
|
+
if (content.includes('[tool:pytest]') || content.includes('[pytest]')) {
|
|
33
|
+
return 'pytest';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// ignore malformed or unreadable file
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
6
42
|
/**
|
|
7
43
|
* Detect the test framework from package.json dependencies.
|
|
8
44
|
*/
|
|
@@ -10,6 +46,10 @@ export function detectFramework(appPath) {
|
|
|
10
46
|
const resolvedPath = resolve(appPath);
|
|
11
47
|
const pkgPath = join(resolvedPath, 'package.json');
|
|
12
48
|
if (!existsSync(pkgPath)) {
|
|
49
|
+
const pytestFramework = detectPytestFramework(resolvedPath);
|
|
50
|
+
if (pytestFramework) {
|
|
51
|
+
return pytestFramework;
|
|
52
|
+
}
|
|
13
53
|
return 'auto';
|
|
14
54
|
}
|
|
15
55
|
try {
|
|
@@ -21,6 +61,9 @@ export function detectFramework(appPath) {
|
|
|
21
61
|
if (allDeps.cypress) {
|
|
22
62
|
return 'cypress';
|
|
23
63
|
}
|
|
64
|
+
if (allDeps.supertest) {
|
|
65
|
+
return 'supertest';
|
|
66
|
+
}
|
|
24
67
|
if (allDeps['selenium-webdriver'] || allDeps.webdriverio) {
|
|
25
68
|
return 'selenium';
|
|
26
69
|
}
|
|
@@ -28,6 +71,10 @@ export function detectFramework(appPath) {
|
|
|
28
71
|
catch {
|
|
29
72
|
// ignore malformed package.json
|
|
30
73
|
}
|
|
74
|
+
const pytestFramework = detectPytestFramework(resolvedPath);
|
|
75
|
+
if (pytestFramework) {
|
|
76
|
+
return pytestFramework;
|
|
77
|
+
}
|
|
31
78
|
return 'auto';
|
|
32
79
|
}
|
|
33
80
|
/**
|
|
@@ -127,6 +127,7 @@ const FLAGS = {
|
|
|
127
127
|
'--patterns': { key: 'testPatterns', type: 'csv' },
|
|
128
128
|
'--flow-patterns': { key: 'flowPatterns', type: 'csv' },
|
|
129
129
|
'--flow-exclude': { key: 'flowExclude', type: 'csv' },
|
|
130
|
+
'--plugins': { key: 'plugins', type: 'csv' },
|
|
130
131
|
'--policy-risky-patterns': { key: 'policyRiskyPatterns', type: 'csv' },
|
|
131
132
|
'--policy-block-actions': {
|
|
132
133
|
key: 'policyBlockActions',
|
|
@@ -174,7 +175,8 @@ export function parseArgs(argv) {
|
|
|
174
175
|
if (COMMANDS.has(command)) {
|
|
175
176
|
parsed.command = command;
|
|
176
177
|
}
|
|
177
|
-
|
|
178
|
+
const startIndex = parsed.command ? 1 : 0;
|
|
179
|
+
for (let i = startIndex; i < argv.length; i += 1) {
|
|
178
180
|
const arg = argv[i];
|
|
179
181
|
const canonical = ALIAS_MAP[arg];
|
|
180
182
|
if (!canonical) {
|
package/dist/esm/cli/usage.js
CHANGED
|
@@ -3,19 +3,32 @@
|
|
|
3
3
|
export function printUsage() {
|
|
4
4
|
console.log([
|
|
5
5
|
'Usage:',
|
|
6
|
-
' e2e-ai-agents
|
|
7
|
-
'
|
|
8
|
-
'
|
|
9
|
-
'
|
|
10
|
-
'
|
|
11
|
-
'
|
|
12
|
-
'
|
|
13
|
-
'
|
|
14
|
-
'
|
|
15
|
-
'
|
|
16
|
-
'
|
|
17
|
-
'
|
|
18
|
-
'
|
|
6
|
+
' e2e-ai-agents <command> [options]',
|
|
7
|
+
'',
|
|
8
|
+
'Core CI workflow:',
|
|
9
|
+
' impact --path <app-root> [options]',
|
|
10
|
+
' plan --path <app-root> [options]',
|
|
11
|
+
' suggest --path <app-root> [options]',
|
|
12
|
+
' gate --path <app-root> --threshold <n> [--since <ref>]',
|
|
13
|
+
'',
|
|
14
|
+
'Optional AI workflow:',
|
|
15
|
+
' analyze --path <app-root> [--tests-root <path>] [--since <ref>] [--generate] [--generate-output <dir>] [--heal] [--heal-report <json>]',
|
|
16
|
+
' generate [--scenarios <path|json>] [--max-attempts <n>] [--dry-run]',
|
|
17
|
+
' heal --path <app-root> --traceability-report <json> [options]',
|
|
18
|
+
' finalize-generated-tests --path <app-root> [options]',
|
|
19
|
+
'',
|
|
20
|
+
'Setup and calibration:',
|
|
21
|
+
' init [--yes]',
|
|
22
|
+
' train --path <project-root> [--no-enrich] [--validate] [--since <ref>] [--pr <num>]',
|
|
23
|
+
' bootstrap --path <app-root> [options]',
|
|
24
|
+
' feedback --path <app-root> --feedback-input <json>',
|
|
25
|
+
' traceability-capture --path <app-root> --traceability-report <json>',
|
|
26
|
+
' traceability-ingest --path <app-root> --traceability-input <json>',
|
|
27
|
+
' cost-report [--path <app-root>]',
|
|
28
|
+
' llm-health',
|
|
29
|
+
'',
|
|
30
|
+
'Advanced / experimental:',
|
|
31
|
+
' crew --path <app-root> [--crew-workflow <name>] [--plugins <paths>]',
|
|
19
32
|
'',
|
|
20
33
|
'Options:',
|
|
21
34
|
' --config <path> Path to e2e-ai-agents.config.json (auto-discovered if present)',
|
|
@@ -23,10 +36,11 @@ export function printUsage() {
|
|
|
23
36
|
' --profile <name> default | mattermost',
|
|
24
37
|
' --mattermost Shortcut for --profile mattermost',
|
|
25
38
|
' --tests-root <path> Path to tests root (optional)',
|
|
26
|
-
' --framework <name> auto | playwright | cypress | selenium',
|
|
39
|
+
' --framework <name> auto | playwright | cypress | pytest | supertest | selenium',
|
|
27
40
|
' --patterns <globs> Comma-separated test patterns',
|
|
28
41
|
' --flow-patterns <g> Comma-separated flow discovery patterns',
|
|
29
42
|
' --flow-exclude <g> Comma-separated flow exclude patterns',
|
|
43
|
+
' --plugins <paths> Comma-separated plugin module paths for crew workflows',
|
|
30
44
|
' --flow-catalog <path> Path to flow catalog JSON',
|
|
31
45
|
' --allow-fallback Allow impact analysis without diff',
|
|
32
46
|
' --pipeline Run Playwright AI pipeline for missing P0/P1 flows',
|
package/dist/esm/cli.js
CHANGED
|
@@ -57,9 +57,13 @@ async function main() {
|
|
|
57
57
|
await runTrainCommand(args, autoConfig);
|
|
58
58
|
return;
|
|
59
59
|
}
|
|
60
|
-
if (args.help
|
|
60
|
+
if (args.help) {
|
|
61
61
|
printUsage();
|
|
62
|
-
process.exit(
|
|
62
|
+
process.exit(0);
|
|
63
|
+
}
|
|
64
|
+
if (!args.command) {
|
|
65
|
+
printUsage();
|
|
66
|
+
process.exit(1);
|
|
63
67
|
}
|
|
64
68
|
if (args.command === 'llm-health') {
|
|
65
69
|
await runLlmHealth();
|
|
@@ -15,7 +15,7 @@ export function buildCoveragePrompt(ctx) {
|
|
|
15
15
|
})
|
|
16
16
|
.join('\n\n');
|
|
17
17
|
return [
|
|
18
|
-
`You are evaluating whether existing ${ctx.profile?.projectName || '
|
|
18
|
+
`You are evaluating whether existing ${ctx.profile?.projectName || 'the project'} ${ctx.profile?.testFramework || 'Playwright'} E2E tests cover the impacted flows.`,
|
|
19
19
|
'',
|
|
20
20
|
`IMPACTED FLOWS (${ctx.flows.length}):`,
|
|
21
21
|
flowsBlock,
|
|
@@ -38,7 +38,7 @@ export function buildCoveragePrompt(ctx) {
|
|
|
38
38
|
' Wrong: "test the new isEditing state"',
|
|
39
39
|
' Right: "test editing a scheduled message while it is in pending state"',
|
|
40
40
|
'- For add_scenarios, specify which existing spec file to extend in targetSpec.',
|
|
41
|
-
`- For create_spec, suggest a path following ${ctx.profile?.projectName || '
|
|
41
|
+
`- For create_spec, suggest a path following ${ctx.profile?.projectName || 'the project'} conventions.`,
|
|
42
42
|
'- Prefer adding scenarios to existing specs over creating new spec files.',
|
|
43
43
|
'',
|
|
44
44
|
'SEMANTIC MATCHING RULES (critical for accuracy):',
|
|
@@ -15,7 +15,7 @@ export function buildCrossImpactPrompt(ctx) {
|
|
|
15
15
|
.join('\n');
|
|
16
16
|
const changedBlock = ctx.changedFiles.map((f) => sanitizeForPrompt(f)).join('\n');
|
|
17
17
|
return [
|
|
18
|
-
`You are analyzing code changes in ${ctx.projectName || '
|
|
18
|
+
`You are analyzing code changes in ${ctx.projectName || 'the project'} to identify cross-family ripple effects.`,
|
|
19
19
|
'When a change in one route family could affect another family through shared dependencies,',
|
|
20
20
|
'that is a cross-impact.',
|
|
21
21
|
'',
|
|
@@ -36,7 +36,7 @@ function buildAssertionPatternsBlock(patterns) {
|
|
|
36
36
|
}
|
|
37
37
|
export function buildGenerationPrompt(ctx) {
|
|
38
38
|
const profile = ctx.profile;
|
|
39
|
-
const isMM = profile ? isMattermostProfile(profile) :
|
|
39
|
+
const isMM = profile ? isMattermostProfile(profile) : false;
|
|
40
40
|
const relevantClasses = resolveRelevantPageObjects(ctx.apiSurface, ctx.decision);
|
|
41
41
|
const apiBlock = relevantClasses.length > 0
|
|
42
42
|
? formatApiSurfaceForPrompt(ctx.apiSurface, relevantClasses)
|
|
@@ -52,9 +52,9 @@ export function buildGenerationPrompt(ctx) {
|
|
|
52
52
|
: `ADD scenarios to the EXISTING spec at: ${ctx.specPath}`;
|
|
53
53
|
const routeFamilyTag = ctx.decision.routeFamily;
|
|
54
54
|
// Build prompt based on profile
|
|
55
|
-
const projectName = profile?.projectName || '
|
|
55
|
+
const projectName = profile?.projectName || 'Project';
|
|
56
56
|
const testFramework = profile?.testFramework || 'Playwright';
|
|
57
|
-
const importStatement = profile?.importStatement || '@
|
|
57
|
+
const importStatement = profile?.importStatement || '@playwright/test';
|
|
58
58
|
// API test mode prompt
|
|
59
59
|
if (profile?.testMode === 'api') {
|
|
60
60
|
return buildApiTestPrompt(ctx, profile, scenariosBlock, routeFamilyTag);
|
|
@@ -226,7 +226,7 @@ export function parseGenerationResponse(text, expectedPath, mode, flowId, profil
|
|
|
226
226
|
if (!code.includes('test(') && !code.includes('it(') && !code.includes('describe(')) {
|
|
227
227
|
return null;
|
|
228
228
|
}
|
|
229
|
-
const importStatement = profile?.importStatement || '@
|
|
229
|
+
const importStatement = profile?.importStatement || '@playwright/test';
|
|
230
230
|
// Auto-add import if missing
|
|
231
231
|
if (!code.includes(importStatement)) {
|
|
232
232
|
if (profile?.testMode === 'api') {
|
package/dist/esm/prompts/heal.js
CHANGED
|
@@ -28,9 +28,9 @@ export function buildHealPrompt(ctx) {
|
|
|
28
28
|
const consoleBlock = ctx.consoleErrors && ctx.consoleErrors.length > 0
|
|
29
29
|
? `\nRecent console errors from test run:\n${ctx.consoleErrors.slice(-3).map((e) => ` - ${sanitizeForPrompt(e)}`).join('\n')}`
|
|
30
30
|
: '';
|
|
31
|
-
const importLib = ctx.profile?.importStatement || '@
|
|
32
|
-
const isMM = ctx.profile ? isMattermostProfile(ctx.profile) :
|
|
33
|
-
const projectLabel = ctx.profile?.projectName || '
|
|
31
|
+
const importLib = ctx.profile?.importStatement || '@playwright/test';
|
|
32
|
+
const isMM = ctx.profile ? isMattermostProfile(ctx.profile) : false;
|
|
33
|
+
const projectLabel = ctx.profile?.projectName || 'Project';
|
|
34
34
|
const frameworkLabel = ctx.profile?.testFramework || 'Playwright';
|
|
35
35
|
const constraints = isMM
|
|
36
36
|
? [
|
|
@@ -71,7 +71,7 @@ export function buildHealPrompt(ctx) {
|
|
|
71
71
|
* (e.g. contain test.describe, test.only, wrong imports).
|
|
72
72
|
*/
|
|
73
73
|
export function buildQualityFixPrompt(specPath, qualityIssues, profile) {
|
|
74
|
-
const importLib = profile?.importStatement || '@
|
|
74
|
+
const importLib = profile?.importStatement || '@playwright/test';
|
|
75
75
|
const frameworkLabel = profile?.testFramework || 'Playwright';
|
|
76
76
|
return [
|
|
77
77
|
`Fix quality issues in this ${frameworkLabel} spec file. Make minimal edits only.`,
|
|
@@ -24,7 +24,7 @@ export function buildImpactPrompt(ctx) {
|
|
|
24
24
|
})
|
|
25
25
|
.join('\n\n');
|
|
26
26
|
return [
|
|
27
|
-
`You are analyzing code changes in ${ctx.projectName || '
|
|
27
|
+
`You are analyzing code changes in ${ctx.projectName || 'the project'} to identify impacted user-facing flows.`,
|
|
28
28
|
'',
|
|
29
29
|
`ROUTE FAMILY: ${ctx.family.id}`,
|
|
30
30
|
`ROUTES: ${familyRoutes}`,
|
|
@@ -25,7 +25,7 @@ export function buildTestDesignerPrompt(ctx) {
|
|
|
25
25
|
: 'None detected.';
|
|
26
26
|
const categories = ctx.strategy.testCategories.join(', ');
|
|
27
27
|
return [
|
|
28
|
-
`You are a senior QA engineer designing comprehensive test cases for a ${ctx.profile?.projectName || '
|
|
28
|
+
`You are a senior QA engineer designing comprehensive test cases for a ${ctx.profile?.projectName || 'project'} user flow.`,
|
|
29
29
|
'',
|
|
30
30
|
`FLOW: ${ctx.flow.flowName}`,
|
|
31
31
|
`Flow ID: ${ctx.flow.flowId}`,
|