@avi770/testteam 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +54 -0
- package/LICENSE +21 -0
- package/README.md +167 -0
- package/agents/01-analyst.ts +100 -0
- package/agents/02-seed-architect.ts +59 -0
- package/agents/03-test-generator.ts +191 -0
- package/agents/04-unit-runner.ts +160 -0
- package/agents/05-browser-crawler.ts +790 -0
- package/agents/06-api-exerciser.ts +311 -0
- package/agents/07-security-scout.ts +188 -0
- package/agents/08-a11y-guardian.ts +212 -0
- package/agents/09-healer.ts +228 -0
- package/agents/10-reporter.ts +266 -0
- package/agents/11-fixer.ts +253 -0
- package/agents/12-ux-inspector.ts +444 -0
- package/agents/13-performance-profiler.ts +271 -0
- package/agents/14-data-integrity-auditor.ts +417 -0
- package/agents/15-regression-sentinel.ts +307 -0
- package/agents/16-chaos-agent.ts +228 -0
- package/agents/17-documentation-validator.ts +266 -0
- package/agents/18-integration-watchdog.ts +178 -0
- package/agents/19-tenant-isolation-auditor.ts +199 -0
- package/agents/20-workflow-completion-tester.ts +203 -0
- package/agents/21-state-session-tester.ts +262 -0
- package/agents/22-email-notification-verifier.ts +244 -0
- package/agents/23-migration-tester.ts +80 -0
- package/agents/__tests__/01-analyst.test.ts +188 -0
- package/agents/__tests__/02-seed-architect.test.ts +152 -0
- package/agents/__tests__/03-test-generator-full.test.ts +321 -0
- package/agents/__tests__/03-test-generator.test.ts +318 -0
- package/agents/__tests__/04-unit-runner.test.ts +320 -0
- package/agents/__tests__/05-browser-crawler-beta.test.ts +492 -0
- package/agents/__tests__/05-browser-crawler-release.test.ts +412 -0
- package/agents/__tests__/05-browser-crawler-uat.test.ts +578 -0
- package/agents/__tests__/05-browser-crawler.test.ts +518 -0
- package/agents/__tests__/06-api-exerciser.test.ts +619 -0
- package/agents/__tests__/07-security-scout.test.ts +382 -0
- package/agents/__tests__/08-a11y-guardian.test.ts +530 -0
- package/agents/__tests__/09-healer.test.ts +384 -0
- package/agents/__tests__/10-reporter.test.ts +366 -0
- package/agents/__tests__/11-fixer.test.ts +406 -0
- package/agents/__tests__/12-ux-inspector-extended.test.ts +465 -0
- package/agents/__tests__/12-ux-inspector.test.ts +443 -0
- package/agents/__tests__/13-performance-profiler.test.ts +411 -0
- package/agents/__tests__/14-data-integrity-auditor-extended.test.ts +573 -0
- package/agents/__tests__/14-data-integrity-auditor.test.ts +407 -0
- package/agents/__tests__/15-regression-sentinel.test.ts +657 -0
- package/agents/__tests__/16-chaos-agent.test.ts +427 -0
- package/agents/__tests__/17-documentation-validator.test.ts +402 -0
- package/agents/__tests__/18-integration-watchdog.test.ts +263 -0
- package/agents/__tests__/19-tenant-isolation-auditor.test.ts +400 -0
- package/agents/__tests__/20-workflow-completion-tester.test.ts +586 -0
- package/agents/__tests__/21-state-session-tester.test.ts +374 -0
- package/agents/__tests__/22-email-notification-verifier.test.ts +441 -0
- package/agents/__tests__/23-migration-tester.test.ts +145 -0
- package/agents/__tests__/base-agent.test.ts +188 -0
- package/agents/__tests__/registry.test.ts +218 -0
- package/agents/base-agent.ts +77 -0
- package/agents/registry.ts +136 -0
- package/baselines/api-schemas/.gitkeep +0 -0
- package/baselines/performance/.gitkeep +0 -0
- package/baselines/screenshots/.gitkeep +0 -0
- package/bin/testteam.js +10 -0
- package/core/__tests__/ci-output.test.ts +430 -0
- package/core/__tests__/cli.test.ts +387 -0
- package/core/__tests__/config.test.ts +78 -0
- package/core/__tests__/cost-tracker.test.ts +158 -0
- package/core/__tests__/evidence.test.ts +265 -0
- package/core/__tests__/fix-loop.test.ts +210 -0
- package/core/__tests__/health-check.test.ts +44 -0
- package/core/__tests__/init.test.ts +609 -0
- package/core/__tests__/integration.test.ts +204 -0
- package/core/__tests__/license-gen.test.ts +227 -0
- package/core/__tests__/license.test.ts +326 -0
- package/core/__tests__/multi-browser.test.ts +278 -0
- package/core/__tests__/orchestrator.test.ts +519 -0
- package/core/__tests__/phase-gate.test.ts +43 -0
- package/core/__tests__/report-html.test.ts +398 -0
- package/core/__tests__/report-upload.test.ts +325 -0
- package/core/__tests__/run-counter.test.ts +234 -0
- package/core/ci-output.ts +240 -0
- package/core/cli.ts +232 -0
- package/core/config.ts +178 -0
- package/core/cost-tracker.ts +59 -0
- package/core/evidence.ts +132 -0
- package/core/fix-loop.ts +85 -0
- package/core/health-check.ts +54 -0
- package/core/init.ts +546 -0
- package/core/license-gen.ts +212 -0
- package/core/license.ts +211 -0
- package/core/messages.ts +67 -0
- package/core/multi-browser.ts +136 -0
- package/core/orchestrator.ts +354 -0
- package/core/phase-gate.ts +55 -0
- package/core/report-html.ts +657 -0
- package/core/report-upload.ts +188 -0
- package/core/run-counter.ts +175 -0
- package/core/types.ts +57 -0
- package/dist/agents/01-analyst.d.ts +11 -0
- package/dist/agents/01-analyst.d.ts.map +1 -0
- package/dist/agents/01-analyst.js +75 -0
- package/dist/agents/01-analyst.js.map +1 -0
- package/dist/agents/02-seed-architect.d.ts +11 -0
- package/dist/agents/02-seed-architect.d.ts.map +1 -0
- package/dist/agents/02-seed-architect.js +51 -0
- package/dist/agents/02-seed-architect.js.map +1 -0
- package/dist/agents/03-test-generator.d.ts +9 -0
- package/dist/agents/03-test-generator.d.ts.map +1 -0
- package/dist/agents/03-test-generator.js +167 -0
- package/dist/agents/03-test-generator.js.map +1 -0
- package/dist/agents/04-unit-runner.d.ts +9 -0
- package/dist/agents/04-unit-runner.d.ts.map +1 -0
- package/dist/agents/04-unit-runner.js +113 -0
- package/dist/agents/04-unit-runner.js.map +1 -0
- package/dist/agents/05-browser-crawler.d.ts +30 -0
- package/dist/agents/05-browser-crawler.d.ts.map +1 -0
- package/dist/agents/05-browser-crawler.js +685 -0
- package/dist/agents/05-browser-crawler.js.map +1 -0
- package/dist/agents/06-api-exerciser.d.ts +23 -0
- package/dist/agents/06-api-exerciser.d.ts.map +1 -0
- package/dist/agents/06-api-exerciser.js +253 -0
- package/dist/agents/06-api-exerciser.js.map +1 -0
- package/dist/agents/07-security-scout.d.ts +11 -0
- package/dist/agents/07-security-scout.d.ts.map +1 -0
- package/dist/agents/07-security-scout.js +142 -0
- package/dist/agents/07-security-scout.js.map +1 -0
- package/dist/agents/08-a11y-guardian.d.ts +13 -0
- package/dist/agents/08-a11y-guardian.d.ts.map +1 -0
- package/dist/agents/08-a11y-guardian.js +176 -0
- package/dist/agents/08-a11y-guardian.js.map +1 -0
- package/dist/agents/09-healer.d.ts +33 -0
- package/dist/agents/09-healer.d.ts.map +1 -0
- package/dist/agents/09-healer.js +167 -0
- package/dist/agents/09-healer.js.map +1 -0
- package/dist/agents/10-reporter.d.ts +26 -0
- package/dist/agents/10-reporter.d.ts.map +1 -0
- package/dist/agents/10-reporter.js +215 -0
- package/dist/agents/10-reporter.js.map +1 -0
- package/dist/agents/11-fixer.d.ts +26 -0
- package/dist/agents/11-fixer.d.ts.map +1 -0
- package/dist/agents/11-fixer.js +195 -0
- package/dist/agents/11-fixer.js.map +1 -0
- package/dist/agents/12-ux-inspector.d.ts +15 -0
- package/dist/agents/12-ux-inspector.d.ts.map +1 -0
- package/dist/agents/12-ux-inspector.js +364 -0
- package/dist/agents/12-ux-inspector.js.map +1 -0
- package/dist/agents/13-performance-profiler.d.ts +13 -0
- package/dist/agents/13-performance-profiler.d.ts.map +1 -0
- package/dist/agents/13-performance-profiler.js +216 -0
- package/dist/agents/13-performance-profiler.js.map +1 -0
- package/dist/agents/14-data-integrity-auditor.d.ts +12 -0
- package/dist/agents/14-data-integrity-auditor.d.ts.map +1 -0
- package/dist/agents/14-data-integrity-auditor.js +356 -0
- package/dist/agents/14-data-integrity-auditor.js.map +1 -0
- package/dist/agents/15-regression-sentinel.d.ts +25 -0
- package/dist/agents/15-regression-sentinel.d.ts.map +1 -0
- package/dist/agents/15-regression-sentinel.js +251 -0
- package/dist/agents/15-regression-sentinel.js.map +1 -0
- package/dist/agents/16-chaos-agent.d.ts +9 -0
- package/dist/agents/16-chaos-agent.d.ts.map +1 -0
- package/dist/agents/16-chaos-agent.js +207 -0
- package/dist/agents/16-chaos-agent.js.map +1 -0
- package/dist/agents/17-documentation-validator.d.ts +31 -0
- package/dist/agents/17-documentation-validator.d.ts.map +1 -0
- package/dist/agents/17-documentation-validator.js +246 -0
- package/dist/agents/17-documentation-validator.js.map +1 -0
- package/dist/agents/18-integration-watchdog.d.ts +10 -0
- package/dist/agents/18-integration-watchdog.d.ts.map +1 -0
- package/dist/agents/18-integration-watchdog.js +138 -0
- package/dist/agents/18-integration-watchdog.js.map +1 -0
- package/dist/agents/19-tenant-isolation-auditor.d.ts +9 -0
- package/dist/agents/19-tenant-isolation-auditor.d.ts.map +1 -0
- package/dist/agents/19-tenant-isolation-auditor.js +166 -0
- package/dist/agents/19-tenant-isolation-auditor.js.map +1 -0
- package/dist/agents/20-workflow-completion-tester.d.ts +12 -0
- package/dist/agents/20-workflow-completion-tester.d.ts.map +1 -0
- package/dist/agents/20-workflow-completion-tester.js +159 -0
- package/dist/agents/20-workflow-completion-tester.js.map +1 -0
- package/dist/agents/21-state-session-tester.d.ts +10 -0
- package/dist/agents/21-state-session-tester.d.ts.map +1 -0
- package/dist/agents/21-state-session-tester.js +233 -0
- package/dist/agents/21-state-session-tester.js.map +1 -0
- package/dist/agents/22-email-notification-verifier.d.ts +11 -0
- package/dist/agents/22-email-notification-verifier.d.ts.map +1 -0
- package/dist/agents/22-email-notification-verifier.js +199 -0
- package/dist/agents/22-email-notification-verifier.js.map +1 -0
- package/dist/agents/23-migration-tester.d.ts +10 -0
- package/dist/agents/23-migration-tester.d.ts.map +1 -0
- package/dist/agents/23-migration-tester.js +74 -0
- package/dist/agents/23-migration-tester.js.map +1 -0
- package/dist/agents/base-agent.d.ts +19 -0
- package/dist/agents/base-agent.d.ts.map +1 -0
- package/dist/agents/base-agent.js +67 -0
- package/dist/agents/base-agent.js.map +1 -0
- package/dist/agents/registry.d.ts +29 -0
- package/dist/agents/registry.d.ts.map +1 -0
- package/dist/agents/registry.js +117 -0
- package/dist/agents/registry.js.map +1 -0
- package/dist/core/ci-output.d.ts +35 -0
- package/dist/core/ci-output.d.ts.map +1 -0
- package/dist/core/ci-output.js +193 -0
- package/dist/core/ci-output.js.map +1 -0
- package/dist/core/cli.d.ts +11 -0
- package/dist/core/cli.d.ts.map +1 -0
- package/dist/core/cli.js +197 -0
- package/dist/core/cli.js.map +1 -0
- package/dist/core/config.d.ts +111 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +42 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/cost-tracker.d.ts +22 -0
- package/dist/core/cost-tracker.d.ts.map +1 -0
- package/dist/core/cost-tracker.js +41 -0
- package/dist/core/cost-tracker.js.map +1 -0
- package/dist/core/evidence.d.ts +28 -0
- package/dist/core/evidence.d.ts.map +1 -0
- package/dist/core/evidence.js +95 -0
- package/dist/core/evidence.js.map +1 -0
- package/dist/core/fix-loop.d.ts +29 -0
- package/dist/core/fix-loop.d.ts.map +1 -0
- package/dist/core/fix-loop.js +70 -0
- package/dist/core/fix-loop.js.map +1 -0
- package/dist/core/health-check.d.ts +21 -0
- package/dist/core/health-check.d.ts.map +1 -0
- package/dist/core/health-check.js +26 -0
- package/dist/core/health-check.js.map +1 -0
- package/dist/core/init.d.ts +2 -0
- package/dist/core/init.d.ts.map +1 -0
- package/dist/core/init.js +435 -0
- package/dist/core/init.js.map +1 -0
- package/dist/core/license-gen.d.ts +12 -0
- package/dist/core/license-gen.d.ts.map +1 -0
- package/dist/core/license-gen.js +169 -0
- package/dist/core/license-gen.js.map +1 -0
- package/dist/core/license.d.ts +33 -0
- package/dist/core/license.d.ts.map +1 -0
- package/dist/core/license.js +170 -0
- package/dist/core/license.js.map +1 -0
- package/dist/core/messages.d.ts +10 -0
- package/dist/core/messages.d.ts.map +1 -0
- package/dist/core/messages.js +47 -0
- package/dist/core/messages.js.map +1 -0
- package/dist/core/multi-browser.d.ts +36 -0
- package/dist/core/multi-browser.d.ts.map +1 -0
- package/dist/core/multi-browser.js +88 -0
- package/dist/core/multi-browser.js.map +1 -0
- package/dist/core/orchestrator.d.ts +48 -0
- package/dist/core/orchestrator.d.ts.map +1 -0
- package/dist/core/orchestrator.js +291 -0
- package/dist/core/orchestrator.js.map +1 -0
- package/dist/core/phase-gate.d.ts +4 -0
- package/dist/core/phase-gate.d.ts.map +1 -0
- package/dist/core/phase-gate.js +39 -0
- package/dist/core/phase-gate.js.map +1 -0
- package/dist/core/report-html.d.ts +9 -0
- package/dist/core/report-html.d.ts.map +1 -0
- package/dist/core/report-html.js +617 -0
- package/dist/core/report-html.js.map +1 -0
- package/dist/core/report-upload.d.ts +16 -0
- package/dist/core/report-upload.d.ts.map +1 -0
- package/dist/core/report-upload.js +124 -0
- package/dist/core/report-upload.js.map +1 -0
- package/dist/core/run-counter.d.ts +40 -0
- package/dist/core/run-counter.d.ts.map +1 -0
- package/dist/core/run-counter.js +120 -0
- package/dist/core/run-counter.js.map +1 -0
- package/dist/core/types.d.ts +53 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/helpers/api-client.d.ts +30 -0
- package/dist/helpers/api-client.d.ts.map +1 -0
- package/dist/helpers/api-client.js +77 -0
- package/dist/helpers/api-client.js.map +1 -0
- package/dist/helpers/element-discovery.d.ts +18 -0
- package/dist/helpers/element-discovery.d.ts.map +1 -0
- package/dist/helpers/element-discovery.js +82 -0
- package/dist/helpers/element-discovery.js.map +1 -0
- package/dist/helpers/env-resolver.d.ts +29 -0
- package/dist/helpers/env-resolver.d.ts.map +1 -0
- package/dist/helpers/env-resolver.js +51 -0
- package/dist/helpers/env-resolver.js.map +1 -0
- package/dist/helpers/form-filler.d.ts +13 -0
- package/dist/helpers/form-filler.d.ts.map +1 -0
- package/dist/helpers/form-filler.js +98 -0
- package/dist/helpers/form-filler.js.map +1 -0
- package/dist/helpers/modal-handler.d.ts +16 -0
- package/dist/helpers/modal-handler.d.ts.map +1 -0
- package/dist/helpers/modal-handler.js +95 -0
- package/dist/helpers/modal-handler.js.map +1 -0
- package/dist/helpers/navigation.d.ts +37 -0
- package/dist/helpers/navigation.d.ts.map +1 -0
- package/dist/helpers/navigation.js +83 -0
- package/dist/helpers/navigation.js.map +1 -0
- package/dist/helpers/quality-gate.d.ts +17 -0
- package/dist/helpers/quality-gate.d.ts.map +1 -0
- package/dist/helpers/quality-gate.js +144 -0
- package/dist/helpers/quality-gate.js.map +1 -0
- package/dist/helpers/screenshot.d.ts +24 -0
- package/dist/helpers/screenshot.d.ts.map +1 -0
- package/dist/helpers/screenshot.js +76 -0
- package/dist/helpers/screenshot.js.map +1 -0
- package/dist/helpers/seed-validator.d.ts +15 -0
- package/dist/helpers/seed-validator.d.ts.map +1 -0
- package/dist/helpers/seed-validator.js +53 -0
- package/dist/helpers/seed-validator.js.map +1 -0
- package/helpers/__tests__/api-client.test.ts +199 -0
- package/helpers/__tests__/element-discovery.test.ts +202 -0
- package/helpers/__tests__/form-filler-extended.test.ts +212 -0
- package/helpers/__tests__/form-filler.test.ts +99 -0
- package/helpers/__tests__/modal-handler.test.ts +152 -0
- package/helpers/__tests__/navigation.test.ts +214 -0
- package/helpers/__tests__/quality-gate.test.ts +117 -0
- package/helpers/__tests__/screenshot.test.ts +139 -0
- package/helpers/__tests__/seed-validator.test.ts +114 -0
- package/helpers/api-client.ts +111 -0
- package/helpers/element-discovery.ts +105 -0
- package/helpers/env-resolver.ts +69 -0
- package/helpers/form-filler.ts +126 -0
- package/helpers/modal-handler.ts +108 -0
- package/helpers/navigation.ts +100 -0
- package/helpers/quality-gate.ts +180 -0
- package/helpers/screenshot.ts +111 -0
- package/helpers/seed-validator.ts +70 -0
- package/package.json +88 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.1.0] - Unreleased
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Release phase (phase 4) with Agent 10 (Reporter) generating consolidated release reports
|
|
12
|
+
- 4-gate pipeline architecture: Alpha -> Beta -> UAT -> Release with blocking/advisory classification
|
|
13
|
+
- Graceful degradation for agents that encounter missing dependencies or unavailable services
|
|
14
|
+
- Environment variable resolver with `TF_` prefix convention and fallback chain support
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- Browser Crawler (Agent 5) optimized: reduced redundant page visits, shared browser context across phases, parallel screenshot capture
|
|
18
|
+
- Pipeline orchestrator now supports `--phase release` and `--phase all` includes the release phase
|
|
19
|
+
- Improved error messages with structured error codes across all agents
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
- Environment resolver now correctly merges `.env`, `.env.local`, and process environment with proper precedence
|
|
23
|
+
- Browser Crawler no longer re-authenticates between module crawls within the same phase
|
|
24
|
+
- Gate evaluation handles advisory-only phases without false-positive blocking
|
|
25
|
+
- Reporter agent correctly aggregates findings across all prior phases when run standalone
|
|
26
|
+
|
|
27
|
+
## [1.0.0] - 2026-03-15
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
- 23 specialized testing agents covering unit, integration, e2e, security, accessibility, performance, and more
|
|
31
|
+
- 3-tier licensing model: Free (8 agents), Pro (17 agents), Enterprise (all 23 agents)
|
|
32
|
+
- 4-phase pipeline: Alpha, Beta, UAT, Release with quality gates between each phase
|
|
33
|
+
- Interactive init wizard (`npx testteam init`) with automatic framework and test runner detection
|
|
34
|
+
- CLI with `init`, `--phase`, `--dry-run`, `--agent`, and `--config` commands
|
|
35
|
+
- HTML report generation with per-agent findings, screenshots, and severity classification
|
|
36
|
+
- CI/CD templates for GitHub Actions, Azure DevOps, and GitLab CI
|
|
37
|
+
- Mintlify documentation site with full API reference and guides
|
|
38
|
+
- Self-healing fix loops: Healer (Agent 9) for test bugs, Fixer (Agent 11) for code bugs
|
|
39
|
+
- Visual regression detection with pixel-level diffing and baseline management
|
|
40
|
+
- Accessibility scanning via axe-core integration (Agent 8)
|
|
41
|
+
- Security auditing with dependency scanning and header validation (Agent 7)
|
|
42
|
+
- Performance profiling with Lighthouse scores, FCP, LCP, and memory tracking (Agent 13)
|
|
43
|
+
- Cost budget tracking with per-run and per-agent limits and configurable exceed policies
|
|
44
|
+
- Configurable agent classification (blocking vs. advisory) per phase
|
|
45
|
+
- Evidence collection: screenshots, DOM snapshots, network logs
|
|
46
|
+
- Enterprise features: chaos testing, tenant isolation, workflow completion, state/session testing, migration safety
|
|
47
|
+
- Multi-tenant isolation verification for SaaS applications (Agent 19)
|
|
48
|
+
- Database migration safety testing with up/down/idempotency checks (Agent 23)
|
|
49
|
+
- Helper utilities: navigation, API client, form filler, element discovery, modal handler, quality gate, screenshot comparison, seed validator
|
|
50
|
+
- 595 unit tests
|
|
51
|
+
- TypeScript strict mode throughout with full type safety
|
|
52
|
+
|
|
53
|
+
[1.1.0]: https://github.com/BAS-More/E2E-Tester/compare/v1.0.0...HEAD
|
|
54
|
+
[1.0.0]: https://github.com/BAS-More/E2E-Tester/releases/tag/v1.0.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 BAS & More Pty Ltd
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/logo-placeholder.png" alt="TestTeam" width="200" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">TestTeam</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>23-agent AI testing orchestration framework</strong>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://www.npmjs.com/package/testteam"><img src="https://img.shields.io/npm/v/testteam.svg" alt="npm version" /></a>
|
|
13
|
+
<a href="https://github.com/BAS-More/E2E-Tester/actions"><img src="https://img.shields.io/github/actions/workflow/status/BAS-More/E2E-Tester/ci.yml?label=CI" alt="CI Status" /></a>
|
|
14
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT" /></a>
|
|
15
|
+
<img src="https://img.shields.io/badge/tests-passing-brightgreen.svg" alt="Tests: passing" />
|
|
16
|
+
<img src="https://img.shields.io/badge/TypeScript-strict-blue.svg" alt="TypeScript strict" />
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
Autonomous multi-phase testing pipeline with 23 specialized agents. Runs Alpha through Release with quality gates, self-healing fix loops, and zero manual intervention.
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# 1. Initialize in your project
|
|
27
|
+
npx testteam init
|
|
28
|
+
|
|
29
|
+
# 2. Configure (edit the generated config)
|
|
30
|
+
vi testteam.config.ts
|
|
31
|
+
|
|
32
|
+
# 3. Run
|
|
33
|
+
npx testteam --phase alpha
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The init wizard auto-detects your framework, test runner, and scaffolds configuration.
|
|
37
|
+
|
|
38
|
+
## Why TestTeam
|
|
39
|
+
|
|
40
|
+
- **4-phase pipeline** -- Alpha, Beta, UAT, Release with quality gates that block promotion on failure
|
|
41
|
+
- **23 specialized agents** -- each owns a single testing concern (a11y, security, perf, visual regression, chaos, and more)
|
|
42
|
+
- **Self-healing fix loop** -- Healer and Fixer agents attempt automatic remediation before gate evaluation
|
|
43
|
+
- **Visual regression** -- pixel-level screenshot diffing with baseline management
|
|
44
|
+
- **Cost-controlled** -- per-run and per-agent budget limits with configurable abort/alert policies
|
|
45
|
+
- **Framework-agnostic** -- React, Next.js, Vue, Angular, NestJS, Express, or any project
|
|
46
|
+
|
|
47
|
+
## Agent Roster
|
|
48
|
+
|
|
49
|
+
| # | Agent | Phase(s) | Tier |
|
|
50
|
+
|---|-------|----------|------|
|
|
51
|
+
| 1 | Analyst | Alpha | Free |
|
|
52
|
+
| 2 | Seed Architect | Alpha | Free |
|
|
53
|
+
| 3 | Test Generator | Alpha | Free |
|
|
54
|
+
| 4 | Unit Runner | Alpha | Free |
|
|
55
|
+
| 5 | Browser Crawler | Alpha, Beta, UAT | Free |
|
|
56
|
+
| 6 | API Exerciser | Beta, UAT | Free |
|
|
57
|
+
| 7 | Security Scout | Beta | Free |
|
|
58
|
+
| 8 | A11y Guardian | Beta | Free |
|
|
59
|
+
| 9 | Healer | Fix Loop | Pro |
|
|
60
|
+
| 10 | Reporter | Release | Pro |
|
|
61
|
+
| 11 | Fixer | Fix Loop | Pro |
|
|
62
|
+
| 12 | UX Inspector | Beta, UAT | Pro |
|
|
63
|
+
| 13 | Performance Profiler | Beta, UAT | Pro |
|
|
64
|
+
| 14 | Data Integrity Auditor | Beta, UAT | Pro |
|
|
65
|
+
| 15 | Regression Sentinel | Beta, UAT | Pro |
|
|
66
|
+
| 16 | Chaos Agent | Beta | Enterprise |
|
|
67
|
+
| 17 | Documentation Validator | UAT | Enterprise |
|
|
68
|
+
| 18 | Integration Watchdog | Beta, UAT | Enterprise |
|
|
69
|
+
| 19 | Tenant Isolation Auditor | Beta, UAT | Enterprise |
|
|
70
|
+
| 20 | Workflow Completion Tester | UAT | Enterprise |
|
|
71
|
+
| 21 | State/Session Tester | Beta, UAT | Enterprise |
|
|
72
|
+
| 22 | Email/Notification Verifier | Beta, UAT | Enterprise |
|
|
73
|
+
| 23 | Migration Tester | Alpha | Enterprise |
|
|
74
|
+
|
|
75
|
+
## Architecture
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
Alpha --> [gate] --> Beta --> [gate] --> UAT --> [gate] --> Release
|
|
79
|
+
| | |
|
|
80
|
+
+------- Fix Loop (Healer + Fixer) ---+
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Each phase dispatches its agents, evaluates findings against blocking/advisory classification, and promotes to the next phase only if the gate passes. The fix loop runs automatically when agents detect issues.
|
|
84
|
+
|
|
85
|
+
## Pricing
|
|
86
|
+
|
|
87
|
+
| Plan | Price | Agents | Support |
|
|
88
|
+
|------|-------|--------|---------|
|
|
89
|
+
| **Free** | $0 | 8 agents (1--8) | Community |
|
|
90
|
+
| **Pro** | $49/mo | 17 agents (1--15) | Priority email |
|
|
91
|
+
| **Enterprise** | $199/mo | All 23 agents + custom | Dedicated support, SLA |
|
|
92
|
+
|
|
93
|
+
All plans include the CLI, init wizard, and config validation. Pro and Enterprise unlock the fix loop, Reporter, and advanced agents.
|
|
94
|
+
|
|
95
|
+
## CI Integration
|
|
96
|
+
|
|
97
|
+
### GitHub Actions
|
|
98
|
+
|
|
99
|
+
```yaml
|
|
100
|
+
name: TestTeam
|
|
101
|
+
on: [push, pull_request]
|
|
102
|
+
|
|
103
|
+
jobs:
|
|
104
|
+
testteam:
|
|
105
|
+
runs-on: ubuntu-latest
|
|
106
|
+
steps:
|
|
107
|
+
- uses: actions/checkout@v4
|
|
108
|
+
- uses: actions/setup-node@v4
|
|
109
|
+
with:
|
|
110
|
+
node-version: 20
|
|
111
|
+
- run: npm ci
|
|
112
|
+
- run: npx playwright install --with-deps
|
|
113
|
+
- run: npx testteam --phase all
|
|
114
|
+
env:
|
|
115
|
+
TF_ADMIN_EMAIL: ${{ secrets.TF_ADMIN_EMAIL }}
|
|
116
|
+
TF_ADMIN_PASSWORD: ${{ secrets.TF_ADMIN_PASSWORD }}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## CLI Reference
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
Usage: testteam [options]
|
|
123
|
+
|
|
124
|
+
Commands:
|
|
125
|
+
init Initialize TestTeam
|
|
126
|
+
|
|
127
|
+
Options:
|
|
128
|
+
--phase <alpha|beta|uat|release|all> Phase to run
|
|
129
|
+
--dry-run Show dispatch plan without executing
|
|
130
|
+
--agent <id> Run a single agent by ID
|
|
131
|
+
--config <path> Path to config file
|
|
132
|
+
--help Show help
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Configuration
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
import type { TestTeamConfig } from 'testteam/config';
|
|
139
|
+
|
|
140
|
+
const config: TestTeamConfig = {
|
|
141
|
+
schemaVersion: 1,
|
|
142
|
+
name: 'my-app',
|
|
143
|
+
modules: [
|
|
144
|
+
{ id: 'dashboard', route: '/dashboard', sidebarIcon: true },
|
|
145
|
+
],
|
|
146
|
+
environments: {
|
|
147
|
+
alpha: { baseUrl: 'http://localhost:3000', seed: true },
|
|
148
|
+
beta: { baseUrl: 'https://staging.example.com', seed: false },
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export default config;
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
See the [full configuration reference](https://docs.testteam.dev/configuration) for all options including auth, breakpoints, cost budgets, thresholds, and agent classification.
|
|
156
|
+
|
|
157
|
+
## Contributing
|
|
158
|
+
|
|
159
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for setup instructions, how to create custom agents, code style, and PR workflow.
|
|
160
|
+
|
|
161
|
+
## Documentation
|
|
162
|
+
|
|
163
|
+
Full docs: [docs.testteam.dev](https://docs.testteam.dev)
|
|
164
|
+
|
|
165
|
+
## License
|
|
166
|
+
|
|
167
|
+
[MIT](LICENSE) -- Copyright 2026 BAS & More Pty Ltd
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
import { writeFile } from 'node:fs/promises';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { BaseAgent } from './base-agent';
|
|
6
|
+
import type { Finding } from '../core/types';
|
|
7
|
+
|
|
8
|
+
const execFileAsync = promisify(execFile);
|
|
9
|
+
|
|
10
|
+
/** Shared-dependency file patterns whose changes elevate all modules to critical risk */
|
|
11
|
+
const SHARED_DEPENDENCY_PATTERNS = ['AuthContext', 'App.tsx', 'router'];
|
|
12
|
+
|
|
13
|
+
interface TestPlanModule {
|
|
14
|
+
id: string;
|
|
15
|
+
risk: 'critical' | 'high' | 'low';
|
|
16
|
+
changedFiles: string[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface TestPlan {
|
|
20
|
+
modules: TestPlanModule[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class AnalystAgent extends BaseAgent {
|
|
24
|
+
readonly agentId = 1;
|
|
25
|
+
readonly agentName = 'Analyst';
|
|
26
|
+
|
|
27
|
+
protected async preFlight(): Promise<void> {
|
|
28
|
+
await execFileAsync('git', ['--version'], { shell: true });
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Auto-detect the default branch: try 'main', fall back to 'master', then 'HEAD'. */
|
|
32
|
+
private async detectDefaultBranch(): Promise<string> {
|
|
33
|
+
for (const candidate of ['main', 'master']) {
|
|
34
|
+
try {
|
|
35
|
+
await execFileAsync('git', ['rev-parse', '--verify', candidate], { shell: true });
|
|
36
|
+
return candidate;
|
|
37
|
+
} catch {
|
|
38
|
+
// branch does not exist, try next
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return 'HEAD';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
protected async execute(): Promise<Finding[]> {
|
|
45
|
+
const defaultBranch = await this.detectDefaultBranch();
|
|
46
|
+
const { stdout } = await execFileAsync('git', ['diff', `${defaultBranch}...HEAD`, '--name-only'], { shell: true });
|
|
47
|
+
const changedFiles = stdout.split('\n').map(f => f.trim()).filter(Boolean);
|
|
48
|
+
|
|
49
|
+
this.addEvidence({
|
|
50
|
+
type: 'log',
|
|
51
|
+
path: join(this.runDir, 'changed-files.txt'),
|
|
52
|
+
description: `${changedFiles.length} files changed since ${defaultBranch}`,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const hasSharedDependencyChange = changedFiles.some(file =>
|
|
56
|
+
SHARED_DEPENDENCY_PATTERNS.some(pattern => file.includes(pattern)),
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const moduleMap = new Map<string, string[]>();
|
|
60
|
+
for (const module of this.config.modules) {
|
|
61
|
+
moduleMap.set(module.id, []);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
for (const file of changedFiles) {
|
|
65
|
+
for (const module of this.config.modules) {
|
|
66
|
+
const routeKey = module.route.replace(/^\//, '');
|
|
67
|
+
if (routeKey && file.includes(routeKey)) {
|
|
68
|
+
moduleMap.get(module.id)?.push(file);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const testPlanModules: TestPlanModule[] = this.config.modules.map(module => {
|
|
74
|
+
const moduleChangedFiles = moduleMap.get(module.id) ?? [];
|
|
75
|
+
|
|
76
|
+
let risk: 'critical' | 'high' | 'low';
|
|
77
|
+
if (hasSharedDependencyChange) {
|
|
78
|
+
risk = 'critical';
|
|
79
|
+
} else if (moduleChangedFiles.length > 0) {
|
|
80
|
+
risk = 'high';
|
|
81
|
+
} else {
|
|
82
|
+
risk = 'low';
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return { id: module.id, risk, changedFiles: moduleChangedFiles };
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const testPlan: TestPlan = { modules: testPlanModules };
|
|
89
|
+
const testPlanPath = join(this.runDir, 'test-plan.json');
|
|
90
|
+
await writeFile(testPlanPath, JSON.stringify(testPlan, null, 2), 'utf-8');
|
|
91
|
+
|
|
92
|
+
this.addEvidence({
|
|
93
|
+
type: 'report',
|
|
94
|
+
path: testPlanPath,
|
|
95
|
+
description: 'Generated test plan with module risk scores',
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { BaseAgent } from './base-agent';
|
|
4
|
+
import { validateSeedCompleteness } from '../helpers/seed-validator';
|
|
5
|
+
import type { Finding } from '../core/types';
|
|
6
|
+
|
|
7
|
+
export class SeedArchitectAgent extends BaseAgent {
|
|
8
|
+
readonly agentId = 2;
|
|
9
|
+
readonly agentName = 'Seed Architect';
|
|
10
|
+
|
|
11
|
+
private get projectRoot(): string {
|
|
12
|
+
const envConfig = this.config.environments['alpha'] ?? Object.values(this.config.environments)[0];
|
|
13
|
+
// Use projectRoot from environment config if available, otherwise fall back to cwd
|
|
14
|
+
const root = (envConfig as unknown as Record<string, unknown> | undefined)?.['projectRoot'];
|
|
15
|
+
return typeof root === 'string' ? root : process.cwd();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
private get seedFilePath(): string {
|
|
19
|
+
return join(this.projectRoot, 'prisma', 'seed.ts');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
protected async preFlight(): Promise<void> {
|
|
23
|
+
// Seed file is optional — missing file produces a warning finding instead of throwing
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
protected async execute(): Promise<Finding[]> {
|
|
27
|
+
if (!existsSync(this.seedFilePath)) {
|
|
28
|
+
return [{
|
|
29
|
+
id: `${this.agentId}-seed-file-missing`,
|
|
30
|
+
type: 'infra-issue' as const,
|
|
31
|
+
severity: 'medium' as const,
|
|
32
|
+
agentId: this.agentId,
|
|
33
|
+
module: 'seed',
|
|
34
|
+
description: `Seed file not found at ${this.seedFilePath}. Seed validation skipped.`,
|
|
35
|
+
suggestedFix: `Create a seed file at prisma/seed.ts or set projectRoot in your environment config.`,
|
|
36
|
+
}];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const moduleIds = this.config.modules.map(m => m.id);
|
|
40
|
+
const result = await validateSeedCompleteness(this.seedFilePath, moduleIds);
|
|
41
|
+
|
|
42
|
+
this.addEvidence({
|
|
43
|
+
type: 'report',
|
|
44
|
+
path: this.seedFilePath,
|
|
45
|
+
description: `Seed validation: ${result.covered.length} covered, ${result.missing.length} missing`,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
return result.missing.map((moduleId, index) => ({
|
|
49
|
+
id: `${this.agentId}-seed-missing-${index}`,
|
|
50
|
+
type: 'code-bug-logic' as const,
|
|
51
|
+
severity: 'medium' as const,
|
|
52
|
+
agentId: this.agentId,
|
|
53
|
+
module: moduleId,
|
|
54
|
+
description: `Module "${moduleId}" has no seed data in prisma/seed.ts`,
|
|
55
|
+
file: this.seedFilePath,
|
|
56
|
+
suggestedFix: `Add a data-creation block for module "${moduleId}" in prisma/seed.ts`,
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { readdir, readFile, stat } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import type { Finding } from '../core/types';
|
|
4
|
+
import { BaseAgent } from './base-agent';
|
|
5
|
+
import { validateCodeQuality } from '../helpers/quality-gate';
|
|
6
|
+
|
|
7
|
+
interface FileCoverage {
|
|
8
|
+
lines: { pct: number };
|
|
9
|
+
functions: { pct: number };
|
|
10
|
+
branches: { pct: number };
|
|
11
|
+
statements: { pct: number };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type CoverageSummary = Record<string, FileCoverage>;
|
|
15
|
+
|
|
16
|
+
const COVERAGE_DIR = 'coverage';
|
|
17
|
+
const GENERATED_TESTS_DIR = 'tests/generated';
|
|
18
|
+
const VITEST_CONFIG_PATHS = ['vitest.config.ts', 'vitest.config.js', 'vite.config.ts'];
|
|
19
|
+
|
|
20
|
+
async function fileExists(p: string): Promise<boolean> {
|
|
21
|
+
try { await stat(p); return true; } catch { return false; }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function findCoverageJsonFiles(dir: string): Promise<string[]> {
|
|
25
|
+
try {
|
|
26
|
+
const entries = await readdir(dir);
|
|
27
|
+
return entries.filter((f) => f.endsWith('.json')).map((f) => join(dir, f));
|
|
28
|
+
} catch {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function parseCoverageSummary(filePath: string): Promise<CoverageSummary | null> {
|
|
34
|
+
try {
|
|
35
|
+
const raw = await readFile(filePath, 'utf8');
|
|
36
|
+
const parsed: unknown = JSON.parse(raw);
|
|
37
|
+
if (parsed !== null && typeof parsed === 'object' && 'total' in parsed) {
|
|
38
|
+
return parsed as CoverageSummary;
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
} catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function findGeneratedTestFiles(dir: string): Promise<string[]> {
|
|
47
|
+
try {
|
|
48
|
+
const entries = await readdir(dir);
|
|
49
|
+
return entries
|
|
50
|
+
.filter((f) => f.endsWith('.ts') || f.endsWith('.tsx') || f.endsWith('.js'))
|
|
51
|
+
.map((f) => join(dir, f));
|
|
52
|
+
} catch {
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export class TestGeneratorAgent extends BaseAgent {
|
|
58
|
+
readonly agentId = 3;
|
|
59
|
+
readonly agentName = 'Test Generator';
|
|
60
|
+
|
|
61
|
+
protected async preFlight(): Promise<void> {
|
|
62
|
+
// Audit: verify coverage data availability (advisory only — may not exist on first run)
|
|
63
|
+
const coverageFiles = await findCoverageJsonFiles(COVERAGE_DIR);
|
|
64
|
+
if (coverageFiles.length === 0) {
|
|
65
|
+
// Advisory — not a hard pre-flight failure; coverage may not exist on first run
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Validate: verify vitest config is present so generated tests can actually run
|
|
69
|
+
const vitestConfigChecks = await Promise.all(VITEST_CONFIG_PATHS.map((p) => fileExists(p)));
|
|
70
|
+
const vitestConfigExists = vitestConfigChecks.some(Boolean);
|
|
71
|
+
if (!vitestConfigExists) {
|
|
72
|
+
// Advisory only — project may use a differently-named config
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Pre-check: note whether generated tests directory exists
|
|
76
|
+
const generatedDirExists = await fileExists(GENERATED_TESTS_DIR);
|
|
77
|
+
if (!generatedDirExists) {
|
|
78
|
+
// Advisory — directory will be created when tests are first generated
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
protected async execute(): Promise<Finding[]> {
|
|
83
|
+
const findings: Finding[] = [];
|
|
84
|
+
|
|
85
|
+
// -----------------------------------------------------------------------
|
|
86
|
+
// Phase 1: Coverage gap detection
|
|
87
|
+
// -----------------------------------------------------------------------
|
|
88
|
+
|
|
89
|
+
const coverageFiles = await findCoverageJsonFiles(COVERAGE_DIR);
|
|
90
|
+
|
|
91
|
+
if (coverageFiles.length === 0) {
|
|
92
|
+
findings.push({
|
|
93
|
+
id: '3-no-coverage-data',
|
|
94
|
+
type: 'code-bug-logic',
|
|
95
|
+
severity: 'medium',
|
|
96
|
+
agentId: this.agentId,
|
|
97
|
+
module: 'test-coverage',
|
|
98
|
+
description:
|
|
99
|
+
'Coverage analysis not available: no JSON files found in coverage/. ' +
|
|
100
|
+
'Run vitest with --coverage to generate coverage data.',
|
|
101
|
+
});
|
|
102
|
+
} else {
|
|
103
|
+
const thresholds = this.config.thresholds.unitCoverage;
|
|
104
|
+
|
|
105
|
+
for (const filePath of coverageFiles) {
|
|
106
|
+
const summary = await parseCoverageSummary(filePath);
|
|
107
|
+
if (!summary) continue;
|
|
108
|
+
|
|
109
|
+
this.addEvidence({
|
|
110
|
+
type: 'report',
|
|
111
|
+
path: filePath,
|
|
112
|
+
description: `Coverage summary from ${filePath}`,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
for (const [entry, coverage] of Object.entries(summary)) {
|
|
116
|
+
if (entry === 'total') continue;
|
|
117
|
+
|
|
118
|
+
const gaps: string[] = [];
|
|
119
|
+
|
|
120
|
+
if (coverage.lines.pct < thresholds.lines) {
|
|
121
|
+
gaps.push(`lines ${coverage.lines.pct.toFixed(1)}% < ${thresholds.lines}%`);
|
|
122
|
+
}
|
|
123
|
+
if (coverage.functions.pct < thresholds.functions) {
|
|
124
|
+
gaps.push(`functions ${coverage.functions.pct.toFixed(1)}% < ${thresholds.functions}%`);
|
|
125
|
+
}
|
|
126
|
+
if (coverage.branches.pct < thresholds.branches) {
|
|
127
|
+
gaps.push(`branches ${coverage.branches.pct.toFixed(1)}% < ${thresholds.branches}%`);
|
|
128
|
+
}
|
|
129
|
+
if (coverage.statements.pct < thresholds.statements) {
|
|
130
|
+
gaps.push(`statements ${coverage.statements.pct.toFixed(1)}% < ${thresholds.statements}%`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (gaps.length > 0) {
|
|
134
|
+
findings.push({
|
|
135
|
+
id: `3-coverage-gap-${entry.replace(/[^a-zA-Z0-9]/g, '-').slice(0, 60)}`,
|
|
136
|
+
type: 'code-bug-logic',
|
|
137
|
+
severity: 'medium',
|
|
138
|
+
agentId: this.agentId,
|
|
139
|
+
module: 'test-coverage',
|
|
140
|
+
description: `Coverage below threshold for "${entry}": ${gaps.join(', ')}`,
|
|
141
|
+
file: entry,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// -----------------------------------------------------------------------
|
|
149
|
+
// Phase 2: Quality gate on generated test files
|
|
150
|
+
// AVI-OS: validate code quality of any previously generated tests
|
|
151
|
+
// -----------------------------------------------------------------------
|
|
152
|
+
|
|
153
|
+
const generatedTestFiles = await findGeneratedTestFiles(GENERATED_TESTS_DIR);
|
|
154
|
+
|
|
155
|
+
for (const testFilePath of generatedTestFiles) {
|
|
156
|
+
let fileContent: string;
|
|
157
|
+
try {
|
|
158
|
+
fileContent = await readFile(testFilePath, 'utf-8');
|
|
159
|
+
} catch {
|
|
160
|
+
// If we cannot read the file, skip it silently
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const violations = validateCodeQuality(fileContent, testFilePath);
|
|
165
|
+
|
|
166
|
+
for (const violation of violations) {
|
|
167
|
+
findings.push({
|
|
168
|
+
id: `3-quality-violation-${testFilePath.replace(/[^a-zA-Z0-9]/g, '-').slice(-50)}-L${violation.line ?? 0}`,
|
|
169
|
+
type: 'code-bug-logic',
|
|
170
|
+
severity: violation.severity === 'error' ? 'high' : 'medium',
|
|
171
|
+
agentId: this.agentId,
|
|
172
|
+
module: 'test-quality-gate',
|
|
173
|
+
description:
|
|
174
|
+
`Quality violation in generated test "${testFilePath}" [${violation.rule}]: ${violation.message}`,
|
|
175
|
+
file: testFilePath,
|
|
176
|
+
suggestedFix: `Fix the ${violation.rule} violation to comply with AVI-OS coding quality standards`,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (violations.length === 0) {
|
|
181
|
+
this.addEvidence({
|
|
182
|
+
type: 'log',
|
|
183
|
+
path: testFilePath,
|
|
184
|
+
description: `Quality gate passed for generated test: ${testFilePath}`,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return findings;
|
|
190
|
+
}
|
|
191
|
+
}
|