@yasserkhanorg/e2e-agents 1.8.5 → 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.
Files changed (256) hide show
  1. package/README.md +95 -8
  2. package/dist/adapters/cypress.d.ts +10 -0
  3. package/dist/adapters/cypress.d.ts.map +1 -0
  4. package/dist/adapters/cypress.js +86 -0
  5. package/dist/adapters/framework_adapter.d.ts +41 -0
  6. package/dist/adapters/framework_adapter.d.ts.map +1 -0
  7. package/dist/adapters/framework_adapter.js +152 -0
  8. package/dist/adapters/playwright.d.ts +10 -0
  9. package/dist/adapters/playwright.d.ts.map +1 -0
  10. package/dist/adapters/playwright.js +86 -0
  11. package/dist/adapters/pytest.d.ts +10 -0
  12. package/dist/adapters/pytest.d.ts.map +1 -0
  13. package/dist/adapters/pytest.js +96 -0
  14. package/dist/adapters/supertest.d.ts +12 -0
  15. package/dist/adapters/supertest.d.ts.map +1 -0
  16. package/dist/adapters/supertest.js +85 -0
  17. package/dist/agent/config.d.ts +1 -1
  18. package/dist/agent/config.d.ts.map +1 -1
  19. package/dist/agent/git.d.ts +1 -0
  20. package/dist/agent/git.d.ts.map +1 -1
  21. package/dist/agent/git.js +3 -0
  22. package/dist/agentic/fix_loop.d.ts.map +1 -1
  23. package/dist/agentic/fix_loop.js +5 -4
  24. package/dist/agentic/runner.d.ts +2 -0
  25. package/dist/agentic/runner.d.ts.map +1 -1
  26. package/dist/agentic/runner.js +15 -12
  27. package/dist/agents/cross-impact.d.ts.map +1 -1
  28. package/dist/agents/cross-impact.js +6 -1
  29. package/dist/agents/executor.d.ts.map +1 -1
  30. package/dist/agents/executor.js +6 -1
  31. package/dist/agents/strategist.d.ts.map +1 -1
  32. package/dist/agents/strategist.js +6 -1
  33. package/dist/agents/test-designer.d.ts.map +1 -1
  34. package/dist/agents/test-designer.js +6 -1
  35. package/dist/anthropic_provider.d.ts.map +1 -1
  36. package/dist/anthropic_provider.js +1 -0
  37. package/dist/base_provider.d.ts +56 -0
  38. package/dist/base_provider.d.ts.map +1 -1
  39. package/dist/base_provider.js +123 -1
  40. package/dist/budget_ledger.d.ts +28 -0
  41. package/dist/budget_ledger.d.ts.map +1 -0
  42. package/dist/budget_ledger.js +62 -0
  43. package/dist/cache/cached_provider.d.ts +45 -0
  44. package/dist/cache/cached_provider.d.ts.map +1 -0
  45. package/dist/cache/cached_provider.js +88 -0
  46. package/dist/cache/response_cache.d.ts +79 -0
  47. package/dist/cache/response_cache.d.ts.map +1 -0
  48. package/dist/cache/response_cache.js +177 -0
  49. package/dist/cli/commands/bootstrap.d.ts +3 -0
  50. package/dist/cli/commands/bootstrap.d.ts.map +1 -0
  51. package/dist/cli/commands/bootstrap.js +109 -0
  52. package/dist/cli/commands/cost_report.d.ts +3 -0
  53. package/dist/cli/commands/cost_report.d.ts.map +1 -0
  54. package/dist/cli/commands/cost_report.js +115 -0
  55. package/dist/cli/commands/crew.d.ts.map +1 -1
  56. package/dist/cli/commands/crew.js +118 -1
  57. package/dist/cli/commands/gate.d.ts +3 -0
  58. package/dist/cli/commands/gate.d.ts.map +1 -0
  59. package/dist/cli/commands/gate.js +86 -0
  60. package/dist/cli/commands/init.d.ts.map +1 -1
  61. package/dist/cli/commands/init.js +7 -62
  62. package/dist/cli/commands/train.d.ts.map +1 -1
  63. package/dist/cli/commands/train.js +16 -21
  64. package/dist/cli/defaults.d.ts +35 -0
  65. package/dist/cli/defaults.d.ts.map +1 -0
  66. package/dist/cli/defaults.js +125 -0
  67. package/dist/cli/errors.d.ts +27 -0
  68. package/dist/cli/errors.d.ts.map +1 -0
  69. package/dist/cli/errors.js +57 -0
  70. package/dist/cli/parse_args.d.ts.map +1 -1
  71. package/dist/cli/parse_args.js +24 -2
  72. package/dist/cli/types.d.ts +7 -1
  73. package/dist/cli/types.d.ts.map +1 -1
  74. package/dist/cli.js +47 -2
  75. package/dist/crew/context.d.ts +15 -0
  76. package/dist/crew/context.d.ts.map +1 -1
  77. package/dist/crew/orchestrator.d.ts +14 -0
  78. package/dist/crew/orchestrator.d.ts.map +1 -1
  79. package/dist/crew/orchestrator.js +162 -4
  80. package/dist/crew/protocol.d.ts +13 -0
  81. package/dist/crew/protocol.d.ts.map +1 -1
  82. package/dist/crew/provider.d.ts +15 -1
  83. package/dist/crew/provider.d.ts.map +1 -1
  84. package/dist/crew/provider.js +24 -4
  85. package/dist/custom_provider.d.ts.map +1 -1
  86. package/dist/custom_provider.js +1 -0
  87. package/dist/engine/diff_loader.d.ts.map +1 -1
  88. package/dist/engine/diff_loader.js +3 -14
  89. package/dist/engine/impact_engine.d.ts.map +1 -1
  90. package/dist/engine/impact_engine.js +9 -23
  91. package/dist/esm/adapters/cypress.js +49 -0
  92. package/dist/esm/adapters/framework_adapter.js +114 -0
  93. package/dist/esm/adapters/playwright.js +49 -0
  94. package/dist/esm/adapters/pytest.js +59 -0
  95. package/dist/esm/adapters/supertest.js +48 -0
  96. package/dist/esm/agent/git.js +3 -1
  97. package/dist/esm/agentic/fix_loop.js +5 -4
  98. package/dist/esm/agentic/runner.js +15 -12
  99. package/dist/esm/agents/cross-impact.js +6 -1
  100. package/dist/esm/agents/executor.js +6 -1
  101. package/dist/esm/agents/strategist.js +6 -1
  102. package/dist/esm/agents/test-designer.js +6 -1
  103. package/dist/esm/anthropic_provider.js +1 -0
  104. package/dist/esm/base_provider.js +121 -0
  105. package/dist/esm/budget_ledger.js +58 -0
  106. package/dist/esm/cache/cached_provider.js +82 -0
  107. package/dist/esm/cache/response_cache.js +140 -0
  108. package/dist/esm/cli/commands/bootstrap.js +106 -0
  109. package/dist/esm/cli/commands/cost_report.js +112 -0
  110. package/dist/esm/cli/commands/crew.js +118 -1
  111. package/dist/esm/cli/commands/gate.js +83 -0
  112. package/dist/esm/cli/commands/init.js +3 -58
  113. package/dist/esm/cli/commands/train.js +16 -21
  114. package/dist/esm/cli/defaults.js +118 -0
  115. package/dist/esm/cli/errors.js +52 -0
  116. package/dist/esm/cli/parse_args.js +24 -2
  117. package/dist/esm/cli.js +47 -2
  118. package/dist/esm/crew/orchestrator.js +162 -4
  119. package/dist/esm/crew/provider.js +24 -4
  120. package/dist/esm/custom_provider.js +1 -0
  121. package/dist/esm/engine/diff_loader.js +1 -12
  122. package/dist/esm/engine/impact_engine.js +9 -23
  123. package/dist/esm/index.js +21 -0
  124. package/dist/esm/knowledge/cluster_utils.js +60 -0
  125. package/dist/esm/knowledge/kg_bridge.js +381 -0
  126. package/dist/esm/knowledge/kg_types.js +3 -0
  127. package/dist/esm/knowledge/route_families.js +89 -0
  128. package/dist/esm/mcp-server.js +2 -4
  129. package/dist/esm/metrics/prometheus.js +149 -0
  130. package/dist/esm/model_router.js +59 -0
  131. package/dist/esm/ollama_provider.js +1 -0
  132. package/dist/esm/openai_provider.js +1 -0
  133. package/dist/esm/pipeline/orchestrator.js +6 -12
  134. package/dist/esm/pipeline/stage0_preprocess.js +12 -19
  135. package/dist/esm/pipeline/stage2_coverage.js +1 -0
  136. package/dist/esm/pipeline/stage3_generation.js +1 -0
  137. package/dist/esm/progress.js +112 -0
  138. package/dist/esm/prompts/coverage.js +7 -24
  139. package/dist/esm/prompts/cross-impact.js +3 -21
  140. package/dist/esm/prompts/generation.js +158 -36
  141. package/dist/esm/prompts/generation_profile.js +147 -0
  142. package/dist/esm/prompts/heal.js +33 -15
  143. package/dist/esm/prompts/impact.js +3 -22
  144. package/dist/esm/prompts/json_extract.js +36 -0
  145. package/dist/esm/prompts/strategist.js +2 -20
  146. package/dist/esm/prompts/test-designer.js +6 -21
  147. package/dist/esm/provider_factory.js +6 -4
  148. package/dist/esm/reporters/junit.js +86 -0
  149. package/dist/esm/reporters/reporter.js +3 -0
  150. package/dist/esm/reporters/sarif.js +131 -0
  151. package/dist/esm/resilience/circuit_breaker.js +78 -0
  152. package/dist/esm/resilience/retry.js +56 -0
  153. package/dist/esm/sanitize.js +66 -0
  154. package/dist/esm/training/kg_scanner.js +115 -0
  155. package/dist/esm/training/scanner.js +27 -34
  156. package/dist/esm/version.js +33 -0
  157. package/dist/index.d.ts +21 -1
  158. package/dist/index.d.ts.map +1 -1
  159. package/dist/index.js +45 -1
  160. package/dist/knowledge/cluster_utils.d.ts +28 -0
  161. package/dist/knowledge/cluster_utils.d.ts.map +1 -0
  162. package/dist/knowledge/cluster_utils.js +67 -0
  163. package/dist/knowledge/kg_bridge.d.ts +31 -0
  164. package/dist/knowledge/kg_bridge.d.ts.map +1 -0
  165. package/dist/knowledge/kg_bridge.js +388 -0
  166. package/dist/knowledge/kg_types.d.ts +75 -0
  167. package/dist/knowledge/kg_types.d.ts.map +1 -0
  168. package/dist/knowledge/kg_types.js +4 -0
  169. package/dist/knowledge/route_families.d.ts +18 -0
  170. package/dist/knowledge/route_families.d.ts.map +1 -1
  171. package/dist/knowledge/route_families.js +91 -0
  172. package/dist/mcp-server.d.ts.map +1 -1
  173. package/dist/mcp-server.js +2 -4
  174. package/dist/metrics/prometheus.d.ts +37 -0
  175. package/dist/metrics/prometheus.d.ts.map +1 -0
  176. package/dist/metrics/prometheus.js +153 -0
  177. package/dist/model_router.d.ts +28 -0
  178. package/dist/model_router.d.ts.map +1 -0
  179. package/dist/model_router.js +63 -0
  180. package/dist/ollama_provider.d.ts.map +1 -1
  181. package/dist/ollama_provider.js +1 -0
  182. package/dist/openai_provider.d.ts.map +1 -1
  183. package/dist/openai_provider.js +1 -0
  184. package/dist/pipeline/orchestrator.d.ts +2 -0
  185. package/dist/pipeline/orchestrator.d.ts.map +1 -1
  186. package/dist/pipeline/orchestrator.js +6 -12
  187. package/dist/pipeline/stage0_preprocess.d.ts.map +1 -1
  188. package/dist/pipeline/stage0_preprocess.js +11 -18
  189. package/dist/pipeline/stage2_coverage.d.ts +2 -0
  190. package/dist/pipeline/stage2_coverage.d.ts.map +1 -1
  191. package/dist/pipeline/stage2_coverage.js +1 -0
  192. package/dist/pipeline/stage3_generation.d.ts +2 -0
  193. package/dist/pipeline/stage3_generation.d.ts.map +1 -1
  194. package/dist/pipeline/stage3_generation.js +1 -0
  195. package/dist/pipeline/stage4_heal.d.ts +2 -0
  196. package/dist/pipeline/stage4_heal.d.ts.map +1 -1
  197. package/dist/progress.d.ts +22 -0
  198. package/dist/progress.d.ts.map +1 -0
  199. package/dist/progress.js +116 -0
  200. package/dist/prompts/coverage.d.ts +2 -0
  201. package/dist/prompts/coverage.d.ts.map +1 -1
  202. package/dist/prompts/coverage.js +7 -24
  203. package/dist/prompts/cross-impact.d.ts +1 -0
  204. package/dist/prompts/cross-impact.d.ts.map +1 -1
  205. package/dist/prompts/cross-impact.js +3 -21
  206. package/dist/prompts/generation.d.ts +3 -1
  207. package/dist/prompts/generation.d.ts.map +1 -1
  208. package/dist/prompts/generation.js +158 -36
  209. package/dist/prompts/generation_profile.d.ts +29 -0
  210. package/dist/prompts/generation_profile.d.ts.map +1 -0
  211. package/dist/prompts/generation_profile.js +151 -0
  212. package/dist/prompts/heal.d.ts +3 -1
  213. package/dist/prompts/heal.d.ts.map +1 -1
  214. package/dist/prompts/heal.js +33 -15
  215. package/dist/prompts/impact.d.ts +1 -0
  216. package/dist/prompts/impact.d.ts.map +1 -1
  217. package/dist/prompts/impact.js +3 -22
  218. package/dist/prompts/json_extract.d.ts +14 -0
  219. package/dist/prompts/json_extract.d.ts.map +1 -0
  220. package/dist/prompts/json_extract.js +39 -0
  221. package/dist/prompts/strategist.d.ts.map +1 -1
  222. package/dist/prompts/strategist.js +2 -20
  223. package/dist/prompts/test-designer.d.ts +2 -0
  224. package/dist/prompts/test-designer.d.ts.map +1 -1
  225. package/dist/prompts/test-designer.js +6 -21
  226. package/dist/provider_factory.d.ts.map +1 -1
  227. package/dist/provider_factory.js +6 -4
  228. package/dist/reporters/junit.d.ts +6 -0
  229. package/dist/reporters/junit.d.ts.map +1 -0
  230. package/dist/reporters/junit.js +89 -0
  231. package/dist/reporters/reporter.d.ts +42 -0
  232. package/dist/reporters/reporter.d.ts.map +1 -0
  233. package/dist/reporters/reporter.js +4 -0
  234. package/dist/reporters/sarif.d.ts +7 -0
  235. package/dist/reporters/sarif.d.ts.map +1 -0
  236. package/dist/reporters/sarif.js +134 -0
  237. package/dist/resilience/circuit_breaker.d.ts +36 -0
  238. package/dist/resilience/circuit_breaker.d.ts.map +1 -0
  239. package/dist/resilience/circuit_breaker.js +82 -0
  240. package/dist/resilience/retry.d.ts +11 -0
  241. package/dist/resilience/retry.d.ts.map +1 -0
  242. package/dist/resilience/retry.js +59 -0
  243. package/dist/sanitize.d.ts +15 -0
  244. package/dist/sanitize.d.ts.map +1 -0
  245. package/dist/sanitize.js +71 -0
  246. package/dist/training/kg_scanner.d.ts +13 -0
  247. package/dist/training/kg_scanner.d.ts.map +1 -0
  248. package/dist/training/kg_scanner.js +118 -0
  249. package/dist/training/scanner.d.ts +7 -2
  250. package/dist/training/scanner.d.ts.map +1 -1
  251. package/dist/training/scanner.js +27 -34
  252. package/dist/version.d.ts +6 -0
  253. package/dist/version.d.ts.map +1 -0
  254. package/dist/version.js +36 -0
  255. package/package.json +7 -2
  256. 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 frontend repositories.
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
  [![npm](https://img.shields.io/npm/v/%40yasserkhanorg%2Fe2e-agents)](https://www.npmjs.com/package/@yasserkhanorg/e2e-agents)
6
6
  [![License](https://img.shields.io/badge/license-Apache%202.0-blue)](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 tests — all from the CLI. 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.
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 (v1.8.0):** `impact` + `cross-impact` + `regression-advisor` → `strategist` → `test-designer` → `generator` → `executor` → `healer`
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 (v1.8.0)
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
- Key options:
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`** — `default` or `mattermost` (strict mode with escalation for heuristic-only mappings)
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 Playwright test templates with quality guardrails (no `test.describe`, single tag) and iterative heal attempts.
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"}