@yasserkhanorg/e2e-agents 1.8.4 → 1.9.5
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 +95 -8
- package/dist/adapters/cypress.d.ts +10 -0
- package/dist/adapters/cypress.d.ts.map +1 -0
- package/dist/adapters/cypress.js +86 -0
- package/dist/adapters/framework_adapter.d.ts +41 -0
- package/dist/adapters/framework_adapter.d.ts.map +1 -0
- package/dist/adapters/framework_adapter.js +152 -0
- package/dist/adapters/playwright.d.ts +10 -0
- package/dist/adapters/playwright.d.ts.map +1 -0
- package/dist/adapters/playwright.js +86 -0
- package/dist/adapters/pytest.d.ts +10 -0
- package/dist/adapters/pytest.d.ts.map +1 -0
- package/dist/adapters/pytest.js +96 -0
- package/dist/adapters/supertest.d.ts +12 -0
- package/dist/adapters/supertest.d.ts.map +1 -0
- package/dist/adapters/supertest.js +85 -0
- package/dist/agent/config.d.ts +1 -1
- package/dist/agent/config.d.ts.map +1 -1
- package/dist/agent/git.d.ts +1 -0
- package/dist/agent/git.d.ts.map +1 -1
- package/dist/agent/git.js +3 -0
- package/dist/agentic/fix_loop.d.ts.map +1 -1
- package/dist/agentic/fix_loop.js +5 -4
- package/dist/agentic/runner.d.ts +2 -0
- package/dist/agentic/runner.d.ts.map +1 -1
- package/dist/agentic/runner.js +15 -12
- package/dist/agents/cross-impact.d.ts.map +1 -1
- package/dist/agents/cross-impact.js +6 -1
- package/dist/agents/executor.d.ts.map +1 -1
- package/dist/agents/executor.js +6 -1
- package/dist/agents/strategist.d.ts.map +1 -1
- package/dist/agents/strategist.js +6 -1
- package/dist/agents/test-designer.d.ts.map +1 -1
- package/dist/agents/test-designer.js +6 -1
- package/dist/anthropic_provider.d.ts.map +1 -1
- package/dist/anthropic_provider.js +1 -0
- package/dist/base_provider.d.ts +56 -0
- package/dist/base_provider.d.ts.map +1 -1
- package/dist/base_provider.js +123 -1
- package/dist/budget_ledger.d.ts +28 -0
- package/dist/budget_ledger.d.ts.map +1 -0
- package/dist/budget_ledger.js +62 -0
- package/dist/cache/cached_provider.d.ts +45 -0
- package/dist/cache/cached_provider.d.ts.map +1 -0
- package/dist/cache/cached_provider.js +88 -0
- package/dist/cache/response_cache.d.ts +79 -0
- package/dist/cache/response_cache.d.ts.map +1 -0
- package/dist/cache/response_cache.js +177 -0
- package/dist/cli/commands/bootstrap.d.ts +3 -0
- package/dist/cli/commands/bootstrap.d.ts.map +1 -0
- package/dist/cli/commands/bootstrap.js +109 -0
- package/dist/cli/commands/cost_report.d.ts +3 -0
- package/dist/cli/commands/cost_report.d.ts.map +1 -0
- package/dist/cli/commands/cost_report.js +115 -0
- package/dist/cli/commands/crew.d.ts.map +1 -1
- package/dist/cli/commands/crew.js +118 -1
- package/dist/cli/commands/gate.d.ts +3 -0
- package/dist/cli/commands/gate.d.ts.map +1 -0
- package/dist/cli/commands/gate.js +86 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +7 -62
- package/dist/cli/commands/plan_crew.d.ts.map +1 -1
- package/dist/cli/commands/plan_crew.js +33 -21
- package/dist/cli/commands/train.d.ts.map +1 -1
- package/dist/cli/commands/train.js +16 -21
- package/dist/cli/defaults.d.ts +35 -0
- package/dist/cli/defaults.d.ts.map +1 -0
- package/dist/cli/defaults.js +125 -0
- package/dist/cli/errors.d.ts +27 -0
- package/dist/cli/errors.d.ts.map +1 -0
- package/dist/cli/errors.js +57 -0
- package/dist/cli/parse_args.d.ts.map +1 -1
- package/dist/cli/parse_args.js +24 -2
- package/dist/cli/types.d.ts +7 -1
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/cli.js +47 -2
- package/dist/crew/context.d.ts +15 -0
- package/dist/crew/context.d.ts.map +1 -1
- package/dist/crew/orchestrator.d.ts +14 -0
- package/dist/crew/orchestrator.d.ts.map +1 -1
- package/dist/crew/orchestrator.js +162 -4
- package/dist/crew/protocol.d.ts +13 -0
- package/dist/crew/protocol.d.ts.map +1 -1
- package/dist/crew/provider.d.ts +15 -1
- package/dist/crew/provider.d.ts.map +1 -1
- package/dist/crew/provider.js +24 -4
- package/dist/custom_provider.d.ts.map +1 -1
- package/dist/custom_provider.js +1 -0
- package/dist/engine/diff_loader.d.ts.map +1 -1
- package/dist/engine/diff_loader.js +3 -14
- package/dist/engine/impact_engine.d.ts.map +1 -1
- package/dist/engine/impact_engine.js +9 -23
- package/dist/esm/adapters/cypress.js +49 -0
- package/dist/esm/adapters/framework_adapter.js +114 -0
- package/dist/esm/adapters/playwright.js +49 -0
- package/dist/esm/adapters/pytest.js +59 -0
- package/dist/esm/adapters/supertest.js +48 -0
- package/dist/esm/agent/git.js +3 -1
- package/dist/esm/agentic/fix_loop.js +5 -4
- package/dist/esm/agentic/runner.js +15 -12
- package/dist/esm/agents/cross-impact.js +6 -1
- package/dist/esm/agents/executor.js +6 -1
- package/dist/esm/agents/strategist.js +6 -1
- package/dist/esm/agents/test-designer.js +6 -1
- package/dist/esm/anthropic_provider.js +1 -0
- package/dist/esm/base_provider.js +121 -0
- package/dist/esm/budget_ledger.js +58 -0
- package/dist/esm/cache/cached_provider.js +82 -0
- package/dist/esm/cache/response_cache.js +140 -0
- package/dist/esm/cli/commands/bootstrap.js +106 -0
- package/dist/esm/cli/commands/cost_report.js +112 -0
- package/dist/esm/cli/commands/crew.js +118 -1
- package/dist/esm/cli/commands/gate.js +83 -0
- package/dist/esm/cli/commands/init.js +3 -58
- package/dist/esm/cli/commands/plan_crew.js +33 -21
- package/dist/esm/cli/commands/train.js +16 -21
- package/dist/esm/cli/defaults.js +118 -0
- package/dist/esm/cli/errors.js +52 -0
- package/dist/esm/cli/parse_args.js +24 -2
- package/dist/esm/cli.js +47 -2
- package/dist/esm/crew/orchestrator.js +162 -4
- package/dist/esm/crew/provider.js +24 -4
- package/dist/esm/custom_provider.js +1 -0
- package/dist/esm/engine/diff_loader.js +1 -12
- package/dist/esm/engine/impact_engine.js +9 -23
- package/dist/esm/index.js +21 -0
- package/dist/esm/knowledge/cluster_utils.js +60 -0
- package/dist/esm/knowledge/kg_bridge.js +381 -0
- package/dist/esm/knowledge/kg_types.js +3 -0
- package/dist/esm/knowledge/route_families.js +89 -0
- package/dist/esm/mcp-server.js +2 -4
- package/dist/esm/metrics/prometheus.js +149 -0
- package/dist/esm/model_router.js +59 -0
- package/dist/esm/ollama_provider.js +1 -0
- package/dist/esm/openai_provider.js +1 -0
- package/dist/esm/pipeline/orchestrator.js +6 -12
- package/dist/esm/pipeline/stage0_preprocess.js +12 -19
- package/dist/esm/pipeline/stage2_coverage.js +1 -0
- package/dist/esm/pipeline/stage3_generation.js +1 -0
- package/dist/esm/progress.js +112 -0
- package/dist/esm/prompts/coverage.js +7 -24
- package/dist/esm/prompts/cross-impact.js +3 -21
- package/dist/esm/prompts/generation.js +158 -36
- package/dist/esm/prompts/generation_profile.js +147 -0
- package/dist/esm/prompts/heal.js +33 -15
- package/dist/esm/prompts/impact.js +3 -22
- package/dist/esm/prompts/json_extract.js +36 -0
- package/dist/esm/prompts/strategist.js +2 -20
- package/dist/esm/prompts/test-designer.js +6 -21
- package/dist/esm/provider_factory.js +6 -4
- package/dist/esm/reporters/junit.js +86 -0
- package/dist/esm/reporters/reporter.js +3 -0
- package/dist/esm/reporters/sarif.js +131 -0
- package/dist/esm/resilience/circuit_breaker.js +78 -0
- package/dist/esm/resilience/retry.js +56 -0
- package/dist/esm/sanitize.js +66 -0
- package/dist/esm/training/kg_scanner.js +115 -0
- package/dist/esm/training/scanner.js +27 -34
- package/dist/esm/version.js +33 -0
- package/dist/index.d.ts +21 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +45 -1
- package/dist/knowledge/cluster_utils.d.ts +28 -0
- package/dist/knowledge/cluster_utils.d.ts.map +1 -0
- package/dist/knowledge/cluster_utils.js +67 -0
- package/dist/knowledge/kg_bridge.d.ts +31 -0
- package/dist/knowledge/kg_bridge.d.ts.map +1 -0
- package/dist/knowledge/kg_bridge.js +388 -0
- package/dist/knowledge/kg_types.d.ts +75 -0
- package/dist/knowledge/kg_types.d.ts.map +1 -0
- package/dist/knowledge/kg_types.js +4 -0
- package/dist/knowledge/route_families.d.ts +18 -0
- package/dist/knowledge/route_families.d.ts.map +1 -1
- package/dist/knowledge/route_families.js +91 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +2 -4
- package/dist/metrics/prometheus.d.ts +37 -0
- package/dist/metrics/prometheus.d.ts.map +1 -0
- package/dist/metrics/prometheus.js +153 -0
- package/dist/model_router.d.ts +28 -0
- package/dist/model_router.d.ts.map +1 -0
- package/dist/model_router.js +63 -0
- package/dist/ollama_provider.d.ts.map +1 -1
- package/dist/ollama_provider.js +1 -0
- package/dist/openai_provider.d.ts.map +1 -1
- package/dist/openai_provider.js +1 -0
- package/dist/pipeline/orchestrator.d.ts +2 -0
- package/dist/pipeline/orchestrator.d.ts.map +1 -1
- package/dist/pipeline/orchestrator.js +6 -12
- package/dist/pipeline/stage0_preprocess.d.ts.map +1 -1
- package/dist/pipeline/stage0_preprocess.js +11 -18
- package/dist/pipeline/stage2_coverage.d.ts +2 -0
- package/dist/pipeline/stage2_coverage.d.ts.map +1 -1
- package/dist/pipeline/stage2_coverage.js +1 -0
- package/dist/pipeline/stage3_generation.d.ts +2 -0
- package/dist/pipeline/stage3_generation.d.ts.map +1 -1
- package/dist/pipeline/stage3_generation.js +1 -0
- package/dist/pipeline/stage4_heal.d.ts +2 -0
- package/dist/pipeline/stage4_heal.d.ts.map +1 -1
- package/dist/progress.d.ts +22 -0
- package/dist/progress.d.ts.map +1 -0
- package/dist/progress.js +116 -0
- package/dist/prompts/coverage.d.ts +2 -0
- package/dist/prompts/coverage.d.ts.map +1 -1
- package/dist/prompts/coverage.js +7 -24
- package/dist/prompts/cross-impact.d.ts +1 -0
- package/dist/prompts/cross-impact.d.ts.map +1 -1
- package/dist/prompts/cross-impact.js +3 -21
- package/dist/prompts/generation.d.ts +3 -1
- package/dist/prompts/generation.d.ts.map +1 -1
- package/dist/prompts/generation.js +158 -36
- package/dist/prompts/generation_profile.d.ts +29 -0
- package/dist/prompts/generation_profile.d.ts.map +1 -0
- package/dist/prompts/generation_profile.js +151 -0
- package/dist/prompts/heal.d.ts +3 -1
- package/dist/prompts/heal.d.ts.map +1 -1
- package/dist/prompts/heal.js +33 -15
- package/dist/prompts/impact.d.ts +1 -0
- package/dist/prompts/impact.d.ts.map +1 -1
- package/dist/prompts/impact.js +3 -22
- package/dist/prompts/json_extract.d.ts +14 -0
- package/dist/prompts/json_extract.d.ts.map +1 -0
- package/dist/prompts/json_extract.js +39 -0
- package/dist/prompts/strategist.d.ts.map +1 -1
- package/dist/prompts/strategist.js +2 -20
- package/dist/prompts/test-designer.d.ts +2 -0
- package/dist/prompts/test-designer.d.ts.map +1 -1
- package/dist/prompts/test-designer.js +6 -21
- package/dist/provider_factory.d.ts.map +1 -1
- package/dist/provider_factory.js +6 -4
- package/dist/reporters/junit.d.ts +6 -0
- package/dist/reporters/junit.d.ts.map +1 -0
- package/dist/reporters/junit.js +89 -0
- package/dist/reporters/reporter.d.ts +42 -0
- package/dist/reporters/reporter.d.ts.map +1 -0
- package/dist/reporters/reporter.js +4 -0
- package/dist/reporters/sarif.d.ts +7 -0
- package/dist/reporters/sarif.d.ts.map +1 -0
- package/dist/reporters/sarif.js +134 -0
- package/dist/resilience/circuit_breaker.d.ts +36 -0
- package/dist/resilience/circuit_breaker.d.ts.map +1 -0
- package/dist/resilience/circuit_breaker.js +82 -0
- package/dist/resilience/retry.d.ts +11 -0
- package/dist/resilience/retry.d.ts.map +1 -0
- package/dist/resilience/retry.js +59 -0
- package/dist/sanitize.d.ts +15 -0
- package/dist/sanitize.d.ts.map +1 -0
- package/dist/sanitize.js +71 -0
- package/dist/training/kg_scanner.d.ts +13 -0
- package/dist/training/kg_scanner.d.ts.map +1 -0
- package/dist/training/kg_scanner.js +118 -0
- package/dist/training/scanner.d.ts +7 -2
- package/dist/training/scanner.d.ts.map +1 -1
- package/dist/training/scanner.js +27 -34
- package/dist/version.d.ts +6 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +36 -0
- package/package.json +7 -2
- package/schemas/route-families.schema.json +31 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @yasserkhanorg/e2e-agents
|
|
2
2
|
|
|
3
|
-
AI-powered E2E test impact analysis, generation, healing, and autonomous QA for
|
|
3
|
+
AI-powered E2E test impact analysis, generation, healing, and autonomous QA for any project with route families — not just Mattermost.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@yasserkhanorg/e2e-agents)
|
|
6
6
|
[](LICENSE)
|
|
@@ -8,13 +8,31 @@ AI-powered E2E test impact analysis, generation, healing, and autonomous QA for
|
|
|
8
8
|
|
|
9
9
|
## What It Does
|
|
10
10
|
|
|
11
|
-
Given a git diff, `e2e-ai-agents` determines which E2E test flows are impacted, identifies coverage gaps, and can generate or heal Playwright
|
|
11
|
+
Given a git diff, `e2e-ai-agents` determines which E2E test flows are impacted, identifies coverage gaps, and can generate or heal tests for Playwright, Cypress, pytest (Python), or supertest/vitest (Node.js API) — all from the CLI. The tool is project-agnostic: any codebase with a `route-families.json` manifest works out of the box. The companion `e2e-qa-agent` goes further: it opens a real browser, explores your app autonomously, and produces a QA report with findings and a release-readiness verdict.
|
|
12
12
|
|
|
13
13
|
**Pipeline:** `impact` → `plan` → `generate` → `heal` → `finalize`
|
|
14
|
-
**Crew
|
|
14
|
+
**Multi-Agent Crew:** `impact` + `cross-impact` + `regression-advisor` → `strategist` → `test-designer` → `generator` → `executor` → `healer`
|
|
15
15
|
|
|
16
16
|
> **How does this compare to other tools?** See [docs/comparison.md](docs/comparison.md) for a detailed analysis against Launchable, Codecov ATS, Qodo, Testsigma, mabl, GitHub Copilot, and others.
|
|
17
17
|
|
|
18
|
+
## Free Tier
|
|
19
|
+
|
|
20
|
+
These commands work with **zero LLM cost** — no API key required:
|
|
21
|
+
|
|
22
|
+
| Command | What It Does |
|
|
23
|
+
|---------|-------------|
|
|
24
|
+
| `impact` | Deterministic impact analysis from git diff |
|
|
25
|
+
| `plan` | Coverage gap detection and test recommendations |
|
|
26
|
+
| `train --no-enrich` | Build route-families manifest (scanner only) |
|
|
27
|
+
| `bootstrap` | Generate route-families.json from a knowledge graph (deterministic) |
|
|
28
|
+
| `gate` | CI coverage gate — exit 1 if coverage is below threshold |
|
|
29
|
+
| `traceability-capture` | Extract test-file relationships from Playwright JSON |
|
|
30
|
+
| `traceability-ingest` | Merge traceability mappings into rolling manifest |
|
|
31
|
+
| `feedback` | Ingest recommendation outcomes for calibration |
|
|
32
|
+
| `cost-report` | View LLM cost breakdown from past runs |
|
|
33
|
+
|
|
34
|
+
AI-powered features (crew workflows, test generation, healing) require an API key from [Anthropic](https://console.anthropic.com/), [OpenAI](https://platform.openai.com/), or a local [Ollama](https://ollama.ai/) instance (free).
|
|
35
|
+
|
|
18
36
|
## Installation
|
|
19
37
|
|
|
20
38
|
```bash
|
|
@@ -38,6 +56,12 @@ npx e2e-ai-agents plan --path /path/to/project
|
|
|
38
56
|
# Generate tests for uncovered gaps (requires plan output)
|
|
39
57
|
npx e2e-ai-agents generate --path /path/to/project
|
|
40
58
|
|
|
59
|
+
# Bootstrap route-families.json from an Understand-Anything knowledge graph
|
|
60
|
+
npx e2e-ai-agents bootstrap --path <project-root> [--kg-path <path>] [--test-mode ui|api|both] [--max-families <n>] [--dry-run]
|
|
61
|
+
|
|
62
|
+
# CI coverage gate — fails with exit code 1 if coverage is below threshold
|
|
63
|
+
npx e2e-ai-agents gate --path <project-root> [--threshold <0-100>]
|
|
64
|
+
|
|
41
65
|
# Heal flaky/failing specs from a Playwright report
|
|
42
66
|
npx e2e-ai-agents heal --path /path/to/project --traceability-report ./playwright-report.json
|
|
43
67
|
|
|
@@ -57,7 +81,7 @@ npx e2e-ai-agents llm-health
|
|
|
57
81
|
|
|
58
82
|
`plan` and `suggest` are aliases. `analyze` is a convenience wrapper that runs impact + plan and optionally generation/healing in one invocation. Use `--help` for all available flags.
|
|
59
83
|
|
|
60
|
-
## Multi-Agent Crew
|
|
84
|
+
## Multi-Agent Crew
|
|
61
85
|
|
|
62
86
|
The Crew orchestrates 10 specialized agents for deep test analysis. While the standard pipeline gives a fast pass/fail gate, the Crew produces structured test designs, cross-family impact maps, and prioritized test strategies.
|
|
63
87
|
|
|
@@ -73,8 +97,58 @@ npx e2e-ai-agents crew --workflow full-qa --path /path/to/project --tests-root .
|
|
|
73
97
|
|
|
74
98
|
# With budget cap and JSON output
|
|
75
99
|
npx e2e-ai-agents crew --workflow design-only --budget-usd 2.00 --json --path /path/to/project --tests-root ./e2e-tests --since origin/master
|
|
100
|
+
|
|
101
|
+
# Dry run: preview what would happen without LLM calls
|
|
102
|
+
npx e2e-ai-agents crew --workflow design-only --dry-run --path /path/to/project --tests-root ./e2e-tests --since origin/master
|
|
103
|
+
|
|
104
|
+
# View LLM cost breakdown
|
|
105
|
+
npx e2e-ai-agents cost-report --path /path/to/project
|
|
76
106
|
```
|
|
77
107
|
|
|
108
|
+
### Budget Enforcement
|
|
109
|
+
|
|
110
|
+
The `--budget-usd` flag sets a hard cost limit for the entire crew run. Budget enforcement uses a **pre-reservation** model (like credit card authorization holds) to prevent parallel agents from overshooting:
|
|
111
|
+
|
|
112
|
+
1. Before each LLM call, the provider **reserves** estimated cost in a shared ledger
|
|
113
|
+
2. Other parallel agents see the in-flight hold and stop if the budget would be exceeded
|
|
114
|
+
3. After the call completes, the reservation is **settled** to actual cost
|
|
115
|
+
|
|
116
|
+
This means 3 agents running in parallel against a $1.00 budget will not collectively spend $1.20. The overshoot is bounded by the estimation error of a single call (~$0.01).
|
|
117
|
+
|
|
118
|
+
### Resilience
|
|
119
|
+
|
|
120
|
+
Provider calls are protected by a **circuit breaker** (3-failure threshold, 60s cooldown). If a provider goes down, calls fail fast instead of burning through retry timeouts. Circuit breakers are shared per provider type — if Anthropic is down, all agents discover it after 3 total failures.
|
|
121
|
+
|
|
122
|
+
Only transient errors (429, 5xx, network) trip the circuit. Budget exceeded and auth errors do not.
|
|
123
|
+
|
|
124
|
+
### Plugins
|
|
125
|
+
|
|
126
|
+
External agents can register into crew workflows via the `plugins` config:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
// my-plugin.ts
|
|
130
|
+
import type { AgentPlugin, AgentTask, AgentResult, CrewContext } from '@yasserkhanorg/e2e-agents';
|
|
131
|
+
|
|
132
|
+
const myPlugin: AgentPlugin = {
|
|
133
|
+
role: 'my-custom-analyzer',
|
|
134
|
+
phase: 'understand', // Run in the 'understand' phase
|
|
135
|
+
runAfter: ['impact-analyst'], // After impact-analyst completes
|
|
136
|
+
async execute(task: AgentTask, ctx: CrewContext): Promise<AgentResult> {
|
|
137
|
+
// Access ctx.impactedFlows, ctx.changedFiles, etc.
|
|
138
|
+
return { role: 'my-custom-analyzer', status: 'success', output: null, warnings: [] };
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
export default myPlugin;
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
npx e2e-ai-agents crew --plugins ./my-plugin.ts --workflow full-qa --path ./app
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Plugins with `runAfter` dependencies run sequentially after their dependencies. Plugins without `runAfter` run in parallel with other agents in their phase. Plugin paths must be relative and cannot escape the workspace directory.
|
|
149
|
+
|
|
150
|
+
See [docs/PLUGIN_API_STABILITY.md](docs/PLUGIN_API_STABILITY.md) for the full API contract and stability guarantees.
|
|
151
|
+
|
|
78
152
|
### What the Crew Adds Beyond the Pipeline
|
|
79
153
|
|
|
80
154
|
| Capability | Pipeline | Crew |
|
|
@@ -231,10 +305,23 @@ Create `e2e-ai-agents.config.json` in your project (auto-discovered):
|
|
|
231
305
|
}
|
|
232
306
|
```
|
|
233
307
|
|
|
234
|
-
|
|
308
|
+
### Generation Profiles
|
|
309
|
+
|
|
310
|
+
The tool auto-detects your project type and generates tests following the appropriate conventions. Use the `--profile` flag (or the `profile` config key) to select a profile explicitly:
|
|
311
|
+
|
|
312
|
+
| Profile | Description |
|
|
313
|
+
|---------|-------------|
|
|
314
|
+
| `mattermost` | Mattermost-specific conventions (strict mode, escalation for heuristic-only mappings) |
|
|
315
|
+
| `generic` | Generic Playwright project |
|
|
316
|
+
| `pytest` | Python projects using pytest + requests/httpx |
|
|
317
|
+
| `supertest` | Node.js API projects using supertest/vitest |
|
|
318
|
+
|
|
319
|
+
When `--profile` is omitted, the tool inspects `package.json`, `pyproject.toml`, and test directory structure to pick the best match automatically.
|
|
320
|
+
|
|
321
|
+
### Key options
|
|
235
322
|
|
|
236
323
|
- **`testsRoot`** — path to tests when they live outside the app root
|
|
237
|
-
- **`profile`** — `
|
|
324
|
+
- **`profile`** — `mattermost`, `generic`, `pytest`, or `supertest` (auto-detected when omitted)
|
|
238
325
|
- **`impact.dependencyGraph`** — static reverse dependency graph for transitive impact
|
|
239
326
|
- **`impact.traceability`** — file-to-test mapping from CI execution data
|
|
240
327
|
- **`impact.aiFlow`** — LLM-powered flow mapping (requires `ANTHROPIC_API_KEY`)
|
|
@@ -270,7 +357,7 @@ See [examples/github-actions/pr-impact.yml](examples/github-actions/pr-impact.ym
|
|
|
270
357
|
|
|
271
358
|
### Package Native (default)
|
|
272
359
|
|
|
273
|
-
Strategy-based
|
|
360
|
+
Strategy-based test templates for Playwright, Cypress, pytest, or supertest/vitest with quality guardrails and iterative heal attempts.
|
|
274
361
|
|
|
275
362
|
### MCP Mode (`--pipeline-mcp`)
|
|
276
363
|
|
|
@@ -400,7 +487,7 @@ Requires `agent-browser` CLI (`npm install -g agent-browser`) and `ANTHROPIC_API
|
|
|
400
487
|
|
|
401
488
|
## Production Usage
|
|
402
489
|
|
|
403
|
-
Used by [Mattermost](https://github.com/mattermost/mattermost) for CI-integrated E2E coverage gating, test generation, and spec healing. See the [Mattermost Playwright integration](https://github.com/mattermost/mattermost/tree/master/e2e-tests/playwright) for a real-world example.
|
|
490
|
+
The tool works with any project that has a `route-families.json` manifest — frontend, backend, or full-stack. Used in production by [Mattermost](https://github.com/mattermost/mattermost) for CI-integrated E2E coverage gating, test generation, and spec healing. See the [Mattermost Playwright integration](https://github.com/mattermost/mattermost/tree/master/e2e-tests/playwright) for a real-world example.
|
|
404
491
|
|
|
405
492
|
## License
|
|
406
493
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FrameworkAdapter, RunCommand, RunOptions } from './framework_adapter.js';
|
|
2
|
+
export declare class CypressAdapter implements FrameworkAdapter {
|
|
3
|
+
readonly name = "cypress";
|
|
4
|
+
readonly specGlob = "**/*.cy.{ts,js,tsx,jsx}";
|
|
5
|
+
readonly extractTestPattern: RegExp;
|
|
6
|
+
readonly configFileNames: string[];
|
|
7
|
+
detect(projectRoot: string): boolean;
|
|
8
|
+
buildRunCommand(specPath: string, options?: RunOptions): RunCommand;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=cypress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cypress.d.ts","sourceRoot":"","sources":["../../src/adapters/cypress.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAC,gBAAgB,EAAE,UAAU,EAAE,UAAU,EAAC,MAAM,wBAAwB,CAAC;AAErF,qBAAa,cAAe,YAAW,gBAAgB;IACnD,QAAQ,CAAC,IAAI,aAAa;IAE1B,QAAQ,CAAC,QAAQ,6BAA6B;IAE9C,QAAQ,CAAC,kBAAkB,SAAqC;IAEhE,QAAQ,CAAC,eAAe,WAA8C;IAEtE,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAwBpC,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,UAAU;CAqBtE"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
3
|
+
// See LICENSE.txt for license information.
|
|
4
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
5
|
+
if (k2 === undefined) k2 = k;
|
|
6
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
8
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
9
|
+
}
|
|
10
|
+
Object.defineProperty(o, k2, desc);
|
|
11
|
+
}) : (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
o[k2] = m[k];
|
|
14
|
+
}));
|
|
15
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
16
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
17
|
+
}) : function(o, v) {
|
|
18
|
+
o["default"] = v;
|
|
19
|
+
});
|
|
20
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
21
|
+
var ownKeys = function(o) {
|
|
22
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
23
|
+
var ar = [];
|
|
24
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
25
|
+
return ar;
|
|
26
|
+
};
|
|
27
|
+
return ownKeys(o);
|
|
28
|
+
};
|
|
29
|
+
return function (mod) {
|
|
30
|
+
if (mod && mod.__esModule) return mod;
|
|
31
|
+
var result = {};
|
|
32
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
33
|
+
__setModuleDefault(result, mod);
|
|
34
|
+
return result;
|
|
35
|
+
};
|
|
36
|
+
})();
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.CypressAdapter = void 0;
|
|
39
|
+
/**
|
|
40
|
+
* Cypress Adapter — FrameworkAdapter implementation for Cypress.
|
|
41
|
+
*/
|
|
42
|
+
const fs = __importStar(require("node:fs"));
|
|
43
|
+
const path = __importStar(require("node:path"));
|
|
44
|
+
class CypressAdapter {
|
|
45
|
+
constructor() {
|
|
46
|
+
this.name = 'cypress';
|
|
47
|
+
this.specGlob = '**/*.cy.{ts,js,tsx,jsx}';
|
|
48
|
+
this.extractTestPattern = /\b(?:it|describe|context)\s*\(/g;
|
|
49
|
+
this.configFileNames = ['cypress.config.ts', 'cypress.config.js'];
|
|
50
|
+
}
|
|
51
|
+
detect(projectRoot) {
|
|
52
|
+
const pkgPath = path.join(projectRoot, 'package.json');
|
|
53
|
+
if (!fs.existsSync(pkgPath)) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const raw = fs.readFileSync(pkgPath, 'utf-8');
|
|
58
|
+
const pkg = JSON.parse(raw);
|
|
59
|
+
const allDeps = {
|
|
60
|
+
...pkg.dependencies,
|
|
61
|
+
...pkg.devDependencies,
|
|
62
|
+
};
|
|
63
|
+
return 'cypress' in allDeps;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
buildRunCommand(specPath, options) {
|
|
70
|
+
const args = ['cypress', 'run', '--spec', specPath];
|
|
71
|
+
if (options?.headed) {
|
|
72
|
+
args.push('--headed');
|
|
73
|
+
}
|
|
74
|
+
if (options?.browser) {
|
|
75
|
+
args.push('--browser', options.browser);
|
|
76
|
+
}
|
|
77
|
+
if (options?.project) {
|
|
78
|
+
args.push('--project', options.project);
|
|
79
|
+
}
|
|
80
|
+
if (options?.timeout != null) {
|
|
81
|
+
args.push('--config', `defaultCommandTimeout=${options.timeout}`);
|
|
82
|
+
}
|
|
83
|
+
return { executable: 'npx', args };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
exports.CypressAdapter = CypressAdapter;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { KnowledgeGraph } from '../knowledge/kg_types.js';
|
|
2
|
+
import type { TestType } from '../knowledge/route_families.js';
|
|
3
|
+
/** Shared framework name lists used for test-mode detection across the codebase. */
|
|
4
|
+
export declare const UI_FRAMEWORKS: readonly ["playwright", "@playwright/test", "cypress", "selenium"];
|
|
5
|
+
export declare const API_FRAMEWORKS: readonly ["supertest", "pytest", "requests", "vitest", "jest"];
|
|
6
|
+
export interface RunOptions {
|
|
7
|
+
headed?: boolean;
|
|
8
|
+
browser?: string;
|
|
9
|
+
project?: string;
|
|
10
|
+
timeout?: number;
|
|
11
|
+
}
|
|
12
|
+
export interface RunCommand {
|
|
13
|
+
executable: string;
|
|
14
|
+
args: string[];
|
|
15
|
+
}
|
|
16
|
+
export interface FrameworkAdapter {
|
|
17
|
+
/** Human-readable framework identifier (e.g. 'playwright', 'cypress'). */
|
|
18
|
+
name: string;
|
|
19
|
+
/** Return true when `projectRoot` appears to use this framework. */
|
|
20
|
+
detect(projectRoot: string): boolean;
|
|
21
|
+
/** Glob that matches spec files for this framework. */
|
|
22
|
+
specGlob: string;
|
|
23
|
+
/** Regex that extracts test blocks from source text. */
|
|
24
|
+
extractTestPattern: RegExp;
|
|
25
|
+
/** Possible config file names to look for at the project root. */
|
|
26
|
+
configFileNames: string[];
|
|
27
|
+
/** Build a structured command to execute a single spec file. */
|
|
28
|
+
buildRunCommand(specPath: string, options?: RunOptions): RunCommand;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Auto-detect which test framework a project uses by inspecting its
|
|
32
|
+
* package.json dependencies. Falls back to Playwright when detection
|
|
33
|
+
* is inconclusive.
|
|
34
|
+
*/
|
|
35
|
+
export declare function detectFramework(projectRoot: string): FrameworkAdapter;
|
|
36
|
+
/**
|
|
37
|
+
* Detect the test mode for a project: UI testing, API testing, or both.
|
|
38
|
+
* Uses package.json / pyproject.toml dependencies and optional KG metadata.
|
|
39
|
+
*/
|
|
40
|
+
export declare function detectTestMode(projectRoot: string, kg?: KnowledgeGraph | null): TestType;
|
|
41
|
+
//# sourceMappingURL=framework_adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framework_adapter.d.ts","sourceRoot":"","sources":["../../src/adapters/framework_adapter.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,gCAAgC,CAAC;AAE7D,oFAAoF;AACpF,eAAO,MAAM,aAAa,oEAAqE,CAAC;AAChG,eAAO,MAAM,cAAc,gEAAiE,CAAC;AAE7F,MAAM,WAAW,UAAU;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC7B,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IAEb,oEAAoE;IACpE,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IAErC,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC;IAEjB,wDAAwD;IACxD,kBAAkB,EAAE,MAAM,CAAC;IAE3B,kEAAkE;IAClE,eAAe,EAAE,MAAM,EAAE,CAAC;IAE1B,gEAAgE;IAChE,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;CACvE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,gBAAgB,CAiDrE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,cAAc,GAAG,IAAI,GAAG,QAAQ,CAgDxF"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
3
|
+
// See LICENSE.txt for license information.
|
|
4
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
5
|
+
if (k2 === undefined) k2 = k;
|
|
6
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
8
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
9
|
+
}
|
|
10
|
+
Object.defineProperty(o, k2, desc);
|
|
11
|
+
}) : (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
o[k2] = m[k];
|
|
14
|
+
}));
|
|
15
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
16
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
17
|
+
}) : function(o, v) {
|
|
18
|
+
o["default"] = v;
|
|
19
|
+
});
|
|
20
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
21
|
+
var ownKeys = function(o) {
|
|
22
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
23
|
+
var ar = [];
|
|
24
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
25
|
+
return ar;
|
|
26
|
+
};
|
|
27
|
+
return ownKeys(o);
|
|
28
|
+
};
|
|
29
|
+
return function (mod) {
|
|
30
|
+
if (mod && mod.__esModule) return mod;
|
|
31
|
+
var result = {};
|
|
32
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
33
|
+
__setModuleDefault(result, mod);
|
|
34
|
+
return result;
|
|
35
|
+
};
|
|
36
|
+
})();
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.API_FRAMEWORKS = exports.UI_FRAMEWORKS = void 0;
|
|
39
|
+
exports.detectFramework = detectFramework;
|
|
40
|
+
exports.detectTestMode = detectTestMode;
|
|
41
|
+
/**
|
|
42
|
+
* Framework Adapter Interface — abstracts test-framework-specific logic
|
|
43
|
+
* behind a uniform contract so the rest of the pipeline is framework-agnostic.
|
|
44
|
+
*/
|
|
45
|
+
const fs = __importStar(require("node:fs"));
|
|
46
|
+
const path = __importStar(require("node:path"));
|
|
47
|
+
const playwright_js_1 = require("./playwright.js");
|
|
48
|
+
const cypress_js_1 = require("./cypress.js");
|
|
49
|
+
const supertest_js_1 = require("./supertest.js");
|
|
50
|
+
const pytest_js_1 = require("./pytest.js");
|
|
51
|
+
/** Shared framework name lists used for test-mode detection across the codebase. */
|
|
52
|
+
exports.UI_FRAMEWORKS = ['playwright', '@playwright/test', 'cypress', 'selenium'];
|
|
53
|
+
exports.API_FRAMEWORKS = ['supertest', 'pytest', 'requests', 'vitest', 'jest'];
|
|
54
|
+
/**
|
|
55
|
+
* Auto-detect which test framework a project uses by inspecting its
|
|
56
|
+
* package.json dependencies. Falls back to Playwright when detection
|
|
57
|
+
* is inconclusive.
|
|
58
|
+
*/
|
|
59
|
+
function detectFramework(projectRoot) {
|
|
60
|
+
const pkgPath = path.join(projectRoot, 'package.json');
|
|
61
|
+
if (fs.existsSync(pkgPath)) {
|
|
62
|
+
try {
|
|
63
|
+
const raw = fs.readFileSync(pkgPath, 'utf-8');
|
|
64
|
+
const pkg = JSON.parse(raw);
|
|
65
|
+
const allDeps = {
|
|
66
|
+
...pkg.dependencies,
|
|
67
|
+
...pkg.devDependencies,
|
|
68
|
+
};
|
|
69
|
+
if ('@playwright/test' in allDeps) {
|
|
70
|
+
return new playwright_js_1.PlaywrightAdapter();
|
|
71
|
+
}
|
|
72
|
+
if ('cypress' in allDeps) {
|
|
73
|
+
return new cypress_js_1.CypressAdapter();
|
|
74
|
+
}
|
|
75
|
+
// Backend API test frameworks
|
|
76
|
+
if ('supertest' in allDeps) {
|
|
77
|
+
const runner = 'vitest' in allDeps ? 'vitest' : 'jest';
|
|
78
|
+
return new supertest_js_1.SupertestAdapter(runner);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
// Malformed package.json — fall through to default.
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Check for Python project
|
|
86
|
+
const pyprojectPath = path.join(projectRoot, 'pyproject.toml');
|
|
87
|
+
if (fs.existsSync(pyprojectPath)) {
|
|
88
|
+
try {
|
|
89
|
+
const content = fs.readFileSync(pyprojectPath, 'utf-8');
|
|
90
|
+
if (content.includes('pytest')) {
|
|
91
|
+
return new pytest_js_1.PytestAdapter();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// fall through
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Default to Playwright when we cannot determine the framework.
|
|
99
|
+
return new playwright_js_1.PlaywrightAdapter();
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Detect the test mode for a project: UI testing, API testing, or both.
|
|
103
|
+
* Uses package.json / pyproject.toml dependencies and optional KG metadata.
|
|
104
|
+
*/
|
|
105
|
+
function detectTestMode(projectRoot, kg) {
|
|
106
|
+
// If KG provides framework hints, use them
|
|
107
|
+
if (kg) {
|
|
108
|
+
const frameworks = kg.project.frameworks.map((f) => f.toLowerCase());
|
|
109
|
+
const uiSet = new Set(exports.UI_FRAMEWORKS);
|
|
110
|
+
const apiSet = new Set(exports.API_FRAMEWORKS);
|
|
111
|
+
const hasUi = frameworks.some((f) => uiSet.has(f));
|
|
112
|
+
const hasApi = frameworks.some((f) => apiSet.has(f));
|
|
113
|
+
if (hasUi && hasApi)
|
|
114
|
+
return 'both';
|
|
115
|
+
if (hasApi)
|
|
116
|
+
return 'api';
|
|
117
|
+
if (hasUi)
|
|
118
|
+
return 'ui';
|
|
119
|
+
}
|
|
120
|
+
// Fall back to package.json inspection
|
|
121
|
+
const pkgPath = path.join(projectRoot, 'package.json');
|
|
122
|
+
if (fs.existsSync(pkgPath)) {
|
|
123
|
+
try {
|
|
124
|
+
const raw = fs.readFileSync(pkgPath, 'utf-8');
|
|
125
|
+
const pkg = JSON.parse(raw);
|
|
126
|
+
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
127
|
+
const hasUi = '@playwright/test' in allDeps || 'cypress' in allDeps;
|
|
128
|
+
const hasApi = 'supertest' in allDeps;
|
|
129
|
+
if (hasUi && hasApi)
|
|
130
|
+
return 'both';
|
|
131
|
+
if (hasApi)
|
|
132
|
+
return 'api'; // supertest alone means API-only when no UI framework is present
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// fall through
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Check for Python API testing
|
|
139
|
+
const pyprojectPath = path.join(projectRoot, 'pyproject.toml');
|
|
140
|
+
if (fs.existsSync(pyprojectPath)) {
|
|
141
|
+
try {
|
|
142
|
+
const content = fs.readFileSync(pyprojectPath, 'utf-8');
|
|
143
|
+
if (content.includes('pytest') && !fs.existsSync(path.join(projectRoot, 'package.json'))) {
|
|
144
|
+
return 'api';
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
// fall through
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return 'ui';
|
|
152
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FrameworkAdapter, RunCommand, RunOptions } from './framework_adapter.js';
|
|
2
|
+
export declare class PlaywrightAdapter implements FrameworkAdapter {
|
|
3
|
+
readonly name = "playwright";
|
|
4
|
+
readonly specGlob = "**/*.spec.{ts,js}";
|
|
5
|
+
readonly extractTestPattern: RegExp;
|
|
6
|
+
readonly configFileNames: string[];
|
|
7
|
+
detect(projectRoot: string): boolean;
|
|
8
|
+
buildRunCommand(specPath: string, options?: RunOptions): RunCommand;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=playwright.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright.d.ts","sourceRoot":"","sources":["../../src/adapters/playwright.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAC,gBAAgB,EAAE,UAAU,EAAE,UAAU,EAAC,MAAM,wBAAwB,CAAC;AAErF,qBAAa,iBAAkB,YAAW,gBAAgB;IACtD,QAAQ,CAAC,IAAI,gBAAgB;IAE7B,QAAQ,CAAC,QAAQ,uBAAuB;IAExC,QAAQ,CAAC,kBAAkB,SAAiC;IAE5D,QAAQ,CAAC,eAAe,WAAoD;IAE5E,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAwBpC,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,UAAU;CAqBtE"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
3
|
+
// See LICENSE.txt for license information.
|
|
4
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
5
|
+
if (k2 === undefined) k2 = k;
|
|
6
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
8
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
9
|
+
}
|
|
10
|
+
Object.defineProperty(o, k2, desc);
|
|
11
|
+
}) : (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
o[k2] = m[k];
|
|
14
|
+
}));
|
|
15
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
16
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
17
|
+
}) : function(o, v) {
|
|
18
|
+
o["default"] = v;
|
|
19
|
+
});
|
|
20
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
21
|
+
var ownKeys = function(o) {
|
|
22
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
23
|
+
var ar = [];
|
|
24
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
25
|
+
return ar;
|
|
26
|
+
};
|
|
27
|
+
return ownKeys(o);
|
|
28
|
+
};
|
|
29
|
+
return function (mod) {
|
|
30
|
+
if (mod && mod.__esModule) return mod;
|
|
31
|
+
var result = {};
|
|
32
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
33
|
+
__setModuleDefault(result, mod);
|
|
34
|
+
return result;
|
|
35
|
+
};
|
|
36
|
+
})();
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.PlaywrightAdapter = void 0;
|
|
39
|
+
/**
|
|
40
|
+
* Playwright Adapter — FrameworkAdapter implementation for @playwright/test.
|
|
41
|
+
*/
|
|
42
|
+
const fs = __importStar(require("node:fs"));
|
|
43
|
+
const path = __importStar(require("node:path"));
|
|
44
|
+
class PlaywrightAdapter {
|
|
45
|
+
constructor() {
|
|
46
|
+
this.name = 'playwright';
|
|
47
|
+
this.specGlob = '**/*.spec.{ts,js}';
|
|
48
|
+
this.extractTestPattern = /\btest(?:\.describe)?\s*\(/g;
|
|
49
|
+
this.configFileNames = ['playwright.config.ts', 'playwright.config.js'];
|
|
50
|
+
}
|
|
51
|
+
detect(projectRoot) {
|
|
52
|
+
const pkgPath = path.join(projectRoot, 'package.json');
|
|
53
|
+
if (!fs.existsSync(pkgPath)) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const raw = fs.readFileSync(pkgPath, 'utf-8');
|
|
58
|
+
const pkg = JSON.parse(raw);
|
|
59
|
+
const allDeps = {
|
|
60
|
+
...pkg.dependencies,
|
|
61
|
+
...pkg.devDependencies,
|
|
62
|
+
};
|
|
63
|
+
return '@playwright/test' in allDeps;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
buildRunCommand(specPath, options) {
|
|
70
|
+
const args = ['playwright', 'test', specPath];
|
|
71
|
+
if (options?.headed) {
|
|
72
|
+
args.push('--headed');
|
|
73
|
+
}
|
|
74
|
+
if (options?.browser) {
|
|
75
|
+
args.push('--browser', options.browser);
|
|
76
|
+
}
|
|
77
|
+
if (options?.project) {
|
|
78
|
+
args.push('--project', options.project);
|
|
79
|
+
}
|
|
80
|
+
if (options?.timeout != null) {
|
|
81
|
+
args.push('--timeout', String(options.timeout));
|
|
82
|
+
}
|
|
83
|
+
return { executable: 'npx', args };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
exports.PlaywrightAdapter = PlaywrightAdapter;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FrameworkAdapter, RunCommand, RunOptions } from './framework_adapter.js';
|
|
2
|
+
export declare class PytestAdapter implements FrameworkAdapter {
|
|
3
|
+
name: string;
|
|
4
|
+
specGlob: string;
|
|
5
|
+
extractTestPattern: RegExp;
|
|
6
|
+
configFileNames: string[];
|
|
7
|
+
detect(projectRoot: string): boolean;
|
|
8
|
+
buildRunCommand(specPath: string, options?: RunOptions): RunCommand;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=pytest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pytest.d.ts","sourceRoot":"","sources":["../../src/adapters/pytest.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAC,gBAAgB,EAAE,UAAU,EAAE,UAAU,EAAC,MAAM,wBAAwB,CAAC;AAErF,qBAAa,aAAc,YAAW,gBAAgB;IAClD,IAAI,SAAY;IAChB,QAAQ,SAAkB;IAC1B,kBAAkB,SAAuB;IACzC,eAAe,WAAgE;IAE/E,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAkCpC,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,UAAU;CAOtE"}
|