qa360 2.1.7 → 2.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/.BETA_TESTING_FEEDBACK.md +256 -0
- package/.claude/settings.local.json +154 -0
- package/.editorconfig +21 -0
- package/.github/CODEOWNERS +23 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +108 -0
- package/.github/ISSUE_TEMPLATE/feedback_dx.yml +121 -0
- package/.github/dependabot.yml +35 -0
- package/.github/workflows/mcp-dx.yml +106 -0
- package/.github/workflows/release.yml +26 -0
- package/.github/workflows/test.yml +93 -0
- package/.nvmrc +1 -0
- package/.qa360-artifacts/.gitkeep +0 -0
- package/.qa360-artifacts/baselines/.gitkeep +0 -0
- package/.qa360-artifacts/cache/.gitkeep +0 -0
- package/.qa360-artifacts/reports/.gitkeep +0 -0
- package/.qa360-artifacts/screenshots/.gitkeep +0 -0
- package/.qa360-baselines/www_xyqo_ai.baseline.json +33 -0
- package/CHANGELOG.md +234 -0
- package/CODEOWNERS +43 -0
- package/CONTRIBUTING.md +273 -0
- package/NOVICE_USER_GUIDE.md +272 -0
- package/QUICK_START.md +191 -0
- package/README.md +191 -163
- package/adapters/README.md +46 -0
- package/check-branches.sh +32 -0
- package/cli/.qa360/keys/ed25519.key +1 -0
- package/cli/.qa360/keys/ed25519.pub +1 -0
- package/cli/CHANGELOG.md +84 -0
- package/cli/LICENSE +24 -0
- package/cli/README.md +222 -0
- package/cli/examples/README.md +160 -0
- package/cli/package.json +76 -0
- package/cli/scripts/bundle-for-npm.sh +51 -0
- package/cli/scripts/validate-package.js +116 -0
- package/cli/src/__tests__/commands/doctor.test.ts +108 -0
- package/cli/src/__tests__/index.test.ts +15 -0
- package/cli/src/cli-minimal.ts +44 -0
- package/cli/src/commands/__tests__/crawl.test.ts +412 -0
- package/cli/src/commands/__tests__/doctor-qa360-home.test.ts +156 -0
- package/cli/src/commands/__tests__/e2e-ui-tests.test.ts +494 -0
- package/cli/src/commands/__tests__/e2e.test.ts +187 -0
- package/cli/src/commands/__tests__/flakiness.test.ts +528 -0
- package/cli/src/commands/__tests__/generate.test.ts +507 -0
- package/cli/src/commands/__tests__/history.integration.test.ts +358 -0
- package/cli/src/commands/__tests__/history.test.ts +433 -0
- package/cli/src/commands/__tests__/monitor-realworld.test.ts +199 -0
- package/cli/src/commands/__tests__/monitor.test.ts +81 -0
- package/cli/src/commands/__tests__/ollama.test.ts +529 -0
- package/cli/src/commands/__tests__/repair.test.ts +225 -0
- package/cli/src/commands/__tests__/report.integration.test.ts +167 -0
- package/cli/src/commands/__tests__/report.test.ts +294 -0
- package/cli/src/commands/__tests__/report.vitest.ts +288 -0
- package/cli/src/commands/__tests__/retry.test.ts +78 -0
- package/cli/src/commands/__tests__/run.integration.test.ts +240 -0
- package/cli/src/commands/__tests__/run.test.ts +346 -0
- package/cli/src/commands/__tests__/run.vitest.ts +301 -0
- package/cli/src/commands/__tests__/secrets.test.ts +114 -0
- package/cli/src/commands/__tests__/serve.test.ts +80 -0
- package/cli/src/commands/__tests__/verify.test.ts +103 -0
- package/cli/src/commands/ai.ts +702 -0
- package/cli/src/commands/ask.ts +678 -0
- package/cli/src/commands/coverage.ts +305 -0
- package/cli/src/commands/crawl.ts +155 -0
- package/cli/src/commands/doctor.ts +610 -0
- package/cli/src/commands/examples.ts +248 -0
- package/cli/src/commands/explain.ts +710 -0
- package/cli/src/commands/flakiness.ts +560 -0
- package/cli/src/commands/generate.ts +566 -0
- package/cli/src/commands/history.ts +914 -0
- package/cli/src/commands/init.ts +777 -0
- package/cli/src/commands/monitor.ts +270 -0
- package/cli/src/commands/ollama.ts +337 -0
- package/cli/src/commands/pack.ts +497 -0
- package/cli/src/commands/regression.ts +400 -0
- package/cli/src/commands/repair.ts +356 -0
- package/cli/src/commands/report.ts +463 -0
- package/cli/src/commands/retry.ts +380 -0
- package/cli/src/commands/run.ts +218 -0
- package/cli/src/commands/scan.ts +177 -0
- package/cli/src/commands/secrets.ts +340 -0
- package/cli/src/commands/serve.ts +194 -0
- package/cli/src/commands/slo.ts +387 -0
- package/cli/src/commands/verify-temp-note.md +11 -0
- package/cli/src/commands/verify.ts +322 -0
- package/cli/src/generators/index.ts +6 -0
- package/cli/src/generators/json-reporter.ts +15 -0
- package/cli/src/generators/test-generator.ts +90 -0
- package/cli/src/index.ts +289 -0
- package/cli/src/scanners/dom-scanner.ts +360 -0
- package/cli/src/scanners/index.ts +5 -0
- package/cli/src/types/scan.ts +84 -0
- package/cli/src/utils/config.ts +145 -0
- package/cli/tsconfig.bundle.json +12 -0
- package/cli/tsconfig.json +23 -0
- package/cli/vitest.config.ts +59 -0
- package/core/LICENSE +24 -0
- package/core/README.md +64 -0
- package/core/package.json +81 -0
- package/core/src/__tests__/adapters-contract/adapters-contract.test.md +156 -0
- package/core/src/__tests__/index.test.ts +31 -0
- package/core/src/__tests__/integration/phase3.test.ts +405 -0
- package/core/src/__tests__/pack/validator.test.ts +312 -0
- package/core/src/__tests__/secrets/crypto.test.ts +190 -0
- package/core/src/__tests__/secrets/manager.test.ts +316 -0
- package/core/src/__tests__/security/redactor-phase3.test.ts +233 -0
- package/core/src/__tests__/serve/health-checker.test.ts +155 -0
- package/core/src/__tests__/serve/process-manager.test.ts +213 -0
- package/core/src/__tests__/serve/server.test.ts +103 -0
- package/core/src/__tests__/vault/cas.test.ts +178 -0
- package/core/src/__tests__/vault/vault.test.ts +296 -0
- package/core/src/adapters/__tests__/fixtures/jest-coverage.json +8 -0
- package/core/src/adapters/__tests__/fixtures/jest-results.json +41 -0
- package/core/src/adapters/__tests__/fixtures/pytest-junit.xml +16 -0
- package/core/src/adapters/__tests__/fixtures/vitest-coverage.json +8 -0
- package/core/src/adapters/__tests__/fixtures/vitest-results.json +50 -0
- package/core/src/adapters/__tests__/gitleaks-secrets.test.ts +452 -0
- package/core/src/adapters/__tests__/jest-adapter.test.ts +276 -0
- package/core/src/adapters/__tests__/k6-perf.test.ts +538 -0
- package/core/src/adapters/__tests__/osv-deps.test.ts +471 -0
- package/core/src/adapters/__tests__/playwright-native-api.test.ts +792 -0
- package/core/src/adapters/__tests__/playwright-ui-e2e.test.ts +431 -0
- package/core/src/adapters/__tests__/playwright-ui.test.ts +1073 -0
- package/core/src/adapters/__tests__/pytest-adapter.test.ts +207 -0
- package/core/src/adapters/__tests__/semgrep-sast.test.ts +436 -0
- package/core/src/adapters/__tests__/vitest-adapter.test.ts +208 -0
- package/core/src/adapters/__tests__/zap-dast.test.ts +453 -0
- package/core/src/adapters/gitleaks-secrets.ts +521 -0
- package/core/src/adapters/jest-adapter.ts +306 -0
- package/core/src/adapters/k6-perf.ts +479 -0
- package/core/src/adapters/osv-deps.ts +467 -0
- package/core/src/adapters/playwright-native-adapter.ts +472 -0
- package/core/src/adapters/playwright-native-api.ts +619 -0
- package/core/src/adapters/playwright-ui.ts +1088 -0
- package/core/src/adapters/pytest-adapter.ts +472 -0
- package/core/src/adapters/semgrep-sast.ts +410 -0
- package/core/src/adapters/unit-test-types.ts +106 -0
- package/core/src/adapters/vitest-adapter.ts +295 -0
- package/core/src/adapters/zap-dast.ts +551 -0
- package/core/src/ai/__tests__/deepseek-provider.test.ts +586 -0
- package/core/src/ai/__tests__/ollama-provider.test.ts +641 -0
- package/core/src/ai/anthropic-provider.ts +262 -0
- package/core/src/ai/deepseek-provider.ts +315 -0
- package/core/src/ai/index.ts +87 -0
- package/core/src/ai/llm-client.ts +52 -0
- package/core/src/ai/mock-provider.ts +146 -0
- package/core/src/ai/ollama-provider.ts +269 -0
- package/core/src/ai/openai-provider.ts +240 -0
- package/core/src/ai/provider-factory.ts +408 -0
- package/core/src/artifacts/README.md +78 -0
- package/core/src/artifacts/index.ts +16 -0
- package/core/src/artifacts/ui-artifacts.ts +412 -0
- package/core/src/assertions/__tests__/engine.test.ts +360 -0
- package/core/src/assertions/engine.ts +577 -0
- package/core/src/assertions/index.ts +13 -0
- package/core/src/assertions/types.ts +229 -0
- package/core/src/auth/__tests__/api-key-provider.test.ts +282 -0
- package/core/src/auth/__tests__/auth-manager.test.ts +430 -0
- package/core/src/auth/__tests__/basic-auth-provider.test.ts +364 -0
- package/core/src/auth/__tests__/cloud-providers.test.ts +751 -0
- package/core/src/auth/__tests__/jwt-provider.test.ts +400 -0
- package/core/src/auth/__tests__/oauth2-provider.test.ts +383 -0
- package/core/src/auth/__tests__/totp-provider.test.ts +294 -0
- package/core/src/auth/__tests__/ui-login-provider.test.ts +323 -0
- package/core/src/auth/api-key-provider.ts +75 -0
- package/core/src/auth/aws-iam-provider.ts +212 -0
- package/core/src/auth/azure-ad-provider.ts +126 -0
- package/core/src/auth/basic-auth-provider.ts +133 -0
- package/core/src/auth/gcp-adc-provider.ts +146 -0
- package/core/src/auth/index.ts +342 -0
- package/core/src/auth/jwt-provider.ts +193 -0
- package/core/src/auth/manager.ts +281 -0
- package/core/src/auth/oauth2-provider.ts +141 -0
- package/core/src/auth/totp-provider.ts +163 -0
- package/core/src/auth/ui-login-provider.ts +242 -0
- package/core/src/cache/__tests__/lru-cache.test.ts +564 -0
- package/core/src/cache/index.ts +13 -0
- package/core/src/cache/lru-cache.ts +536 -0
- package/core/src/crawler/__tests__/journey-generator.test.ts +344 -0
- package/core/src/crawler/__tests__/selector-generator.test.ts +211 -0
- package/core/src/crawler/index.ts +335 -0
- package/core/src/crawler/journey-generator.ts +471 -0
- package/core/src/crawler/page-analyzer.ts +857 -0
- package/core/src/crawler/selector-generator.ts +280 -0
- package/core/src/crawler/types.ts +475 -0
- package/core/src/dashboard/__tests__/real-world.test.ts +430 -0
- package/core/src/dashboard/__tests__/server.test.ts +283 -0
- package/core/src/dashboard/__tests__/types.test.ts +208 -0
- package/core/src/dashboard/assets.ts +692 -0
- package/core/src/dashboard/index.ts +17 -0
- package/core/src/dashboard/server.ts +401 -0
- package/core/src/dashboard/types.ts +78 -0
- package/core/src/discoverer/__tests__/test-discoverer.test.ts +444 -0
- package/core/src/discoverer/index.ts +374 -0
- package/core/src/fixtures/__tests__/loader.test.ts +246 -0
- package/core/src/fixtures/__tests__/resolver.test.ts +334 -0
- package/core/src/fixtures/index.ts +9 -0
- package/core/src/fixtures/loader.ts +189 -0
- package/core/src/fixtures/resolver.ts +221 -0
- package/core/src/fixtures/types.ts +86 -0
- package/core/src/flakiness/__tests__/flakiness.test.ts +554 -0
- package/core/src/flakiness/index.ts +536 -0
- package/core/src/generation/__tests__/code-formatter.test.ts +170 -0
- package/core/src/generation/__tests__/code-generator-contract.test.ts +207 -0
- package/core/src/generation/__tests__/code-generator.test.ts +586 -0
- package/core/src/generation/__tests__/crawler-pack-generator.test.ts +479 -0
- package/core/src/generation/__tests__/generation-e2e-b2bshop.test.ts +718 -0
- package/core/src/generation/__tests__/generation-integration.test.ts +655 -0
- package/core/src/generation/__tests__/pack-generator.test.ts +408 -0
- package/core/src/generation/__tests__/prompt-builder.test.ts +200 -0
- package/core/src/generation/__tests__/real-provider-integration.test.ts +414 -0
- package/core/src/generation/__tests__/source-analyzer.test.ts +774 -0
- package/core/src/generation/__tests__/test-optimizer.test.ts +255 -0
- package/core/src/generation/code-formatter.ts +408 -0
- package/core/src/generation/code-generator.ts +470 -0
- package/core/src/generation/crawler-pack-generator.ts +289 -0
- package/core/src/generation/generator.ts +113 -0
- package/core/src/generation/index.ts +59 -0
- package/core/src/generation/pack-generator.ts +527 -0
- package/core/src/generation/prompt-builder.ts +772 -0
- package/core/src/generation/source-analyzer.ts +830 -0
- package/core/src/generation/test-optimizer.ts +474 -0
- package/core/src/generation/types.ts +217 -0
- package/core/src/hooks/__tests__/compose.test.ts +636 -0
- package/core/src/hooks/__tests__/runner.test.ts +478 -0
- package/core/src/hooks/compose.ts +268 -0
- package/core/src/hooks/runner.ts +364 -0
- package/core/src/index.ts +255 -0
- package/core/src/pack/__tests__/migrator.test.ts +594 -0
- package/core/src/pack/__tests__/validator.test.ts +759 -0
- package/core/src/pack/migrator.ts +353 -0
- package/core/src/pack/validator.ts +359 -0
- package/core/src/pack-v2/__tests__/loader.test.ts +533 -0
- package/core/src/pack-v2/__tests__/migrator.test.ts +455 -0
- package/core/src/pack-v2/__tests__/validator.test.ts +609 -0
- package/core/src/pack-v2/index.ts +41 -0
- package/core/src/pack-v2/loader.ts +358 -0
- package/core/src/pack-v2/migrator.ts +540 -0
- package/core/src/pack-v2/validator.ts +726 -0
- package/core/src/parallel/README.md +143 -0
- package/core/src/parallel/index.ts +16 -0
- package/core/src/parallel/parallel-runner.ts +282 -0
- package/core/src/pom/__tests__/loader.test.ts +378 -0
- package/core/src/pom/base-page.ts +425 -0
- package/core/src/pom/index.ts +45 -0
- package/core/src/pom/loader.ts +480 -0
- package/core/src/pom/types.ts +146 -0
- package/core/src/proof/__tests__/proof-roundtrip.test.ts +149 -0
- package/core/src/proof/__tests__/schema-validation-manual.mjs +211 -0
- package/core/src/proof/__tests__/schema-validation.test.ts +336 -0
- package/core/src/proof/__tests__/signer.test.ts +486 -0
- package/core/src/proof/__tests__/temporal-regression.test.ts +537 -0
- package/core/src/proof/__tests__/verifier-advanced.test.ts +588 -0
- package/core/src/proof/__tests__/verifier.test.ts +413 -0
- package/core/src/proof/bundle.ts +290 -0
- package/core/src/proof/canonicalize.ts +116 -0
- package/core/src/proof/index.ts +74 -0
- package/core/src/proof/schema.ts +285 -0
- package/core/src/proof/signer.ts +293 -0
- package/core/src/proof/verifier.ts +380 -0
- package/core/src/regression/__tests__/detector.test.ts +396 -0
- package/core/src/regression/__tests__/trend-analyzer.test.ts +300 -0
- package/core/src/regression/detector.ts +629 -0
- package/core/src/regression/index.ts +34 -0
- package/core/src/regression/trend-analyzer.ts +468 -0
- package/core/src/regression/types.ts +295 -0
- package/core/src/regression/vault.ts +419 -0
- package/core/src/repair/__tests__/repairer.test.ts +572 -0
- package/core/src/repair/__tests__/types.test.ts +302 -0
- package/core/src/repair/engine/__tests__/fixer.test.ts +482 -0
- package/core/src/repair/engine/__tests__/suggestion-engine.test.ts +395 -0
- package/core/src/repair/engine/fixer.ts +271 -0
- package/core/src/repair/engine/suggestion-engine.ts +234 -0
- package/core/src/repair/index.ts +53 -0
- package/core/src/repair/repairer.ts +376 -0
- package/core/src/repair/types.ts +119 -0
- package/core/src/repair/utils/__tests__/error-analyzer.test.ts +454 -0
- package/core/src/repair/utils/error-analyzer.ts +308 -0
- package/core/src/reporting/README.md +144 -0
- package/core/src/reporting/html-reporter.ts +835 -0
- package/core/src/reporting/index.ts +16 -0
- package/core/src/retry/README.md +192 -0
- package/core/src/retry/__tests__/flakiness-integration.test.ts +475 -0
- package/core/src/retry/__tests__/retry-engine.test.ts +424 -0
- package/core/src/retry/flakiness-integration.ts +267 -0
- package/core/src/retry/index.ts +48 -0
- package/core/src/retry/retry-engine.ts +368 -0
- package/core/src/retry/types.ts +208 -0
- package/core/src/retry/vault.ts +413 -0
- package/core/src/runner/__tests__/flakiness-integration.test.ts +566 -0
- package/core/src/runner/__tests__/phase3-e2e-b2bshop.test.ts +218 -0
- package/core/src/runner/__tests__/phase3-e2e-reqres.test.ts +199 -0
- package/core/src/runner/__tests__/phase3-runner.test.ts +1118 -0
- package/core/src/runner/e2e-helpers.ts +216 -0
- package/core/src/runner/phase3-runner.ts +1236 -0
- package/core/src/schemas/gherkin-report.json +122 -0
- package/core/src/secrets/__tests__/crypto.test.ts +180 -0
- package/core/src/secrets/crypto.ts +289 -0
- package/core/src/secrets/manager.ts +272 -0
- package/core/src/security/__tests__/hardening.test.ts +480 -0
- package/core/src/security/redaction-patterns-extended.ts +278 -0
- package/core/src/security/redactor.ts +326 -0
- package/core/src/self-healing/assertion-healer.ts +485 -0
- package/core/src/self-healing/engine.ts +626 -0
- package/core/src/self-healing/index.ts +33 -0
- package/core/src/self-healing/selector-healer.ts +488 -0
- package/core/src/self-healing/types.ts +193 -0
- package/core/src/serve/diagnostics-collector.ts +201 -0
- package/core/src/serve/health-checker.ts +274 -0
- package/core/src/serve/index.ts +9 -0
- package/core/src/serve/metrics-collector.ts +386 -0
- package/core/src/serve/process-manager.ts +265 -0
- package/core/src/serve/server.ts +230 -0
- package/core/src/slo/config.ts +408 -0
- package/core/src/slo/index.ts +68 -0
- package/core/src/slo/sli-calculator.ts +474 -0
- package/core/src/slo/slo-tracker.ts +481 -0
- package/core/src/slo/types.ts +408 -0
- package/core/src/slo/vault.ts +600 -0
- package/core/src/tui/__tests__/monitor.test.ts +336 -0
- package/core/src/tui/__tests__/real-world.test.ts +376 -0
- package/core/src/tui/__tests__/renderer.test.ts +201 -0
- package/core/src/tui/__tests__/types.test.ts +295 -0
- package/core/src/tui/index.ts +19 -0
- package/core/src/tui/monitor.ts +331 -0
- package/core/src/tui/renderer.ts +269 -0
- package/core/src/tui/types.ts +68 -0
- package/core/src/types/pack-v1.ts +305 -0
- package/core/src/types/pack-v2.ts +501 -0
- package/core/src/types/trust-score.ts +258 -0
- package/core/src/vault/__tests__/flakiness-vault.test.ts +562 -0
- package/core/src/vault/__tests__/vault.test.ts +259 -0
- package/core/src/vault/cas.ts +323 -0
- package/core/src/vault/index.ts +1361 -0
- package/core/src/vault/schema.sql +168 -0
- package/core/src/visual/README.md +185 -0
- package/core/src/visual/index.ts +14 -0
- package/core/src/visual/visual-regression.ts +347 -0
- package/core/src/watch/__tests__/watch-mode.test.ts +192 -0
- package/core/src/watch/index.ts +14 -0
- package/core/src/watch/watch-mode.ts +565 -0
- package/core/tsconfig.json +12 -0
- package/core/vitest.config.ts +52 -0
- package/docs/ARCHITECTURE.md +901 -0
- package/docs/AUDIT-GLOBAL-DEC2025.md +271 -0
- package/docs/BETA_TESTING.md +257 -0
- package/docs/BETA_TESTING_PLAN.md +727 -0
- package/docs/CERTIFICATION-REPORT.md +142 -0
- package/docs/COMPLETE_AUDIT_REFACTORING.md +965 -0
- package/docs/DEVELOPMENT.md +545 -0
- package/docs/DEVELOPMENT_HISTORY.md +345 -0
- package/docs/LIMITATIONS.md +176 -0
- package/docs/MIGRATION.md +303 -0
- package/docs/OPTION_3_4_EXPLORATION.md +1257 -0
- package/docs/PHASE1_PERFORMANCE.md +144 -0
- package/docs/QA360_Cloud.postman_collection.json +89 -0
- package/docs/QA360_TESTING_PHILOSOPHY.md +769 -0
- package/docs/QA_TEST_PLAN.md +727 -0
- package/docs/README.md +50 -0
- package/docs/STATUS.md +198 -0
- package/docs/STRATEGIC_STUDY_GOOSE_INTEGRATION.md +615 -0
- package/docs/USER_GUIDE.md +687 -0
- package/docs/WORK-DONE-ADAPTER-TESTS.md +136 -0
- package/docs/adapters-security.md +485 -0
- package/docs/architecture-diagram.mmd +168 -0
- package/docs/archive/ARCH-01-DAY6-BUILD-FIXES.md +396 -0
- package/docs/archive/ARCH-01-DAY6-FINAL-STATUS.md +324 -0
- package/docs/archive/ARCH-01_MCP_MERGE_ANALYSIS.md +644 -0
- package/docs/archive/ARCH-01_NEXT_STEPS.md +60 -0
- package/docs/archive/BRANCH_PROTECTION.md +183 -0
- package/docs/archive/CI_LOCKDOWN_CHECKLIST.md +222 -0
- package/docs/archive/HANDOFF_TEST-01.md +669 -0
- package/docs/archive/LEGAL_READY_PLACEHOLDERS.md +372 -0
- package/docs/archive/NODE_UPGRADE_GUIDE.md +188 -0
- package/docs/archive/PHASE1_COMPLETION.md +386 -0
- package/docs/archive/PHASE2_COMPLETION.md +404 -0
- package/docs/archive/PHASE3_AND_4_FINAL.md +360 -0
- package/docs/archive/PHASE3_COMPLETE.md +301 -0
- package/docs/archive/PHASE3_STATUS.md +255 -0
- package/docs/archive/PRE-WEEK2-AUDIT.md +364 -0
- package/docs/archive/README.md +16 -0
- package/docs/archive/SCHEMA_AJV_2020_FIX.md +245 -0
- package/docs/archive/TEST-01_AUDIT_REPORT.md +240 -0
- package/docs/archive/TEST-01_COVERAGE_PLAN.md +423 -0
- package/docs/archive/obsolete-proposals/dom-element-discovery-mode.md +250 -0
- package/docs/archive/obsolete-proposals/qa360-comprehensive-test-plan.md +1249 -0
- package/docs/archive/obsolete-proposals/qa360-quick-start-guide.md +298 -0
- package/docs/archive/obsolete-proposals/technical-plan-dom-discovery.md +870 -0
- package/docs/budgets-advanced.md +308 -0
- package/docs/examples/history-export-gc.md +285 -0
- package/docs/examples/pack-v2-complete.yaml +158 -0
- package/docs/examples/pack-v2-quickstart.yaml +24 -0
- package/docs/examples/pack-v2-ui-login.yaml +81 -0
- package/docs/examples/qa360-report.json +50 -0
- package/docs/history.md +565 -0
- package/docs/hooks.md +304 -0
- package/docs/llm-providers.md +512 -0
- package/docs/mcp-server.md +651 -0
- package/docs/mcp-tools.md +1131 -0
- package/docs/pack-v1.md +383 -0
- package/docs/pack-v2.md +558 -0
- package/docs/page-objects.md +366 -0
- package/docs/proofs.md +670 -0
- package/docs/quickstart-5min.md +257 -0
- package/docs/readiness-ci.md +654 -0
- package/docs/rfc/README.md +20 -0
- package/docs/rfc/proof-bundle-v1.md +787 -0
- package/docs/secrets.md +392 -0
- package/docs/serve.md +494 -0
- package/docs/unit-test-adapters.md +168 -0
- package/docs/vault.md +491 -0
- package/e2e/qa360-e2e.test.ts +696 -0
- package/e2e/vitest.config.ts +18 -0
- package/examples/README.md +30 -140
- package/examples/ci/docker-compose-serve.yml +375 -0
- package/examples/ci/github-actions-serve.yml +345 -0
- package/examples/ci/gitlab-ci-serve.yml +407 -0
- package/examples/datasets/README.md +101 -0
- package/examples/datasets/b2bshop.ts +155 -0
- package/examples/datasets/index.ts +57 -0
- package/examples/datasets/reqres.ts +195 -0
- package/examples/fixtures-demo/fixtures/users.yml +39 -0
- package/examples/fixtures-demo/pack.yml +71 -0
- package/examples/future-api/README.md +16 -0
- package/examples/future-api/diag.js +7 -0
- package/examples/future-api/health.js +4 -0
- package/examples/future-api/packs.js +13 -0
- package/examples/future-api/runpack.js +10 -0
- package/examples/generation/README.md +148 -0
- package/examples/generation/pack-generator-example.js +115 -0
- package/examples/generation/source-analyzer-example.js +115 -0
- package/examples/httpbin/pack.yml +59 -0
- package/examples/load-testing/mcp-load.yml +115 -0
- package/examples/load-testing/mcp-stdio.yml +95 -0
- package/examples/mcp/claude-desktop-config.json +33 -0
- package/examples/mcp/claude-desktop.json +16 -0
- package/examples/mcp/conversation-sample.md +131 -0
- package/examples/mcp/demo-60s.md +330 -0
- package/examples/mcp/sample-conversation.jsonl +21 -0
- package/examples/mcp/vscode-settings.json +22 -0
- package/examples/pack-v2-complete.yml +242 -0
- package/examples/pack-v2-examples.md +244 -0
- package/examples/pack-v2-quickstart.yml +55 -0
- package/examples/packs-business/ecommerce-api.yml +121 -0
- package/examples/packs-business/saas-dashboard-ui.yml +133 -0
- package/examples/packs-conformance/compose-multi.yml +174 -0
- package/examples/packs-conformance/full.yml +152 -0
- package/examples/packs-conformance/heavy-artifacts.yml +152 -0
- package/examples/packs-conformance/minimal.yml +71 -0
- package/examples/packs-conformance/secrets-missing.yml +97 -0
- package/examples/packs-conformance/timeouts.yml +77 -0
- package/examples/pom-demo/README.md +104 -0
- package/examples/pom-demo/pack.yml +60 -0
- package/examples/pom-demo/pages/DashboardPage.page.ts +73 -0
- package/examples/pom-demo/pages/LoginPage.page.ts +76 -0
- package/examples/proofs/e2e-playwright-proof.json +75 -0
- package/examples/proofs/httpbin-proof.json +69 -0
- package/examples/proofs/multi-adapter-proof.json +117 -0
- package/examples/proofs/test-proof.json +26 -0
- package/examples/restful-api-dev/README.md +102 -0
- package/examples/restful-api-dev/restful-api-advanced.yml +29 -0
- package/examples/restful-api-dev/restful-api-basic.yml +29 -0
- package/examples/web-lite/.github/workflows/qa360-phase3.yml +73 -0
- package/examples/web-lite/api-mock/server.js +258 -0
- package/examples/web-lite/pack.yml +71 -0
- package/examples/web-lite/services.yml +43 -0
- package/examples/web-lite/web-content/healthz +1 -0
- package/examples/web-lite/web-content/index.html +259 -0
- package/package.json +55 -45
- package/packages/mcp/CHANGELOG.md +109 -0
- package/packages/mcp/IMPLEMENTATION_SUMMARY.md +350 -0
- package/packages/mcp/LICENSE +21 -0
- package/packages/mcp/QUICK_START.md +291 -0
- package/packages/mcp/README.md +294 -0
- package/packages/mcp/TELEMETRY.md +220 -0
- package/packages/mcp/package.json +91 -0
- package/packages/mcp/scripts/generate-sbom-fallback.cjs +84 -0
- package/packages/mcp/scripts/safe-postinstall.cjs +32 -0
- package/packages/mcp/src/__tests__/contract.test.ts +902 -0
- package/packages/mcp/src/cli/cli.ts +137 -0
- package/packages/mcp/src/cli/doctor.ts +286 -0
- package/packages/mcp/src/cli/fix.ts +99 -0
- package/packages/mcp/src/cli/init.ts +233 -0
- package/packages/mcp/src/cli/postinstall.ts +14 -0
- package/packages/mcp/src/cli/reset.ts +44 -0
- package/packages/mcp/src/cli/telemetry.ts +166 -0
- package/packages/mcp/src/cli/test-dx.ts +94 -0
- package/packages/mcp/src/cli/uninstall.ts +80 -0
- package/packages/mcp/src/cli/up.ts +178 -0
- package/packages/mcp/src/index.ts +12 -0
- package/packages/mcp/src/scripts/e2e-local.ts +337 -0
- package/packages/mcp/src/scripts/verify-settings.ts +242 -0
- package/packages/mcp/src/security/audit.ts +244 -0
- package/packages/mcp/src/security/manager.ts +242 -0
- package/packages/mcp/src/server/full-server.ts +212 -0
- package/packages/mcp/src/server/minimal-server.ts +134 -0
- package/packages/mcp/src/tools/history.ts +388 -0
- package/packages/mcp/src/tools/pack.ts +449 -0
- package/packages/mcp/src/tools/registry.ts +638 -0
- package/packages/mcp/src/tools/report.ts +100 -0
- package/packages/mcp/src/tools/run.ts +268 -0
- package/packages/mcp/src/tools/secrets.ts +198 -0
- package/packages/mcp/src/tools/serve.ts +221 -0
- package/packages/mcp/src/tools/triage.ts +532 -0
- package/packages/mcp/src/tools/types.ts +26 -0
- package/packages/mcp/src/tools/vault.ts +164 -0
- package/packages/mcp/src/tools/verify.ts +166 -0
- package/packages/mcp/src/types/index.ts +311 -0
- package/packages/mcp/src/types/mcp-stubs.ts +83 -0
- package/packages/mcp/tsconfig.json +16 -0
- package/playwright.config.ts +20 -0
- package/pnpm-workspace.yaml +4 -0
- package/run-test-and-push.sh +20 -0
- package/scripts/build-proof-cli.sh +110 -0
- package/scripts/ci/check-windows-paths.js +92 -0
- package/scripts/ci/invariants.sh +124 -0
- package/scripts/ci/make-final-bundle.js +106 -0
- package/scripts/ci/mcp-run-multipack.js +305 -0
- package/scripts/ci/run-pack-suite.sh +103 -0
- package/scripts/ci/run-phase7-final.sh +190 -0
- package/scripts/ci/slo-assert.js +158 -0
- package/scripts/ci/test-fault-tolerance.sh +301 -0
- package/scripts/install-mcp.sh +66 -0
- package/scripts/mcp-smoke.mjs +27 -0
- package/scripts/smoke.sh +26 -0
- package/scripts/stress-test.js +288 -0
- package/scripts/sync-version.mjs +50 -0
- package/scripts/validate-examples.mjs +404 -0
- package/scripts/validation/simple-pack-check.sh +51 -0
- package/scripts/validation/validate-universal-pack.mjs +77 -0
- package/scripts/verify-persistence.js +127 -0
- package/test-pack.yaml +43 -0
- package/test-results/.last-run.json +4 -0
- package/test-runner.mjs +87 -0
- package/tests/artifacts.spec.js +147 -0
- package/tests/contracts.spec.js +239 -0
- package/tests/e2e/assertions.test.mjs +370 -0
- package/tests/e2e/crawler.test.mjs +451 -0
- package/tests/e2e/playwright-plus-plus.test.mjs +604 -0
- package/tests/e2e/proof-bundle.test.mjs +258 -0
- package/tests/e2e/real-world/saucedemo.test.mjs +714 -0
- package/tests/e2e/real-world/the-internet-herokuapp.test.mjs +760 -0
- package/tests/e2e/ui-actions.test.mjs +546 -0
- package/tests/gherkin.e2e.spec.ts +310 -0
- package/tests/no-console-errors.spec.js +136 -0
- package/tests/pdf.spec.ts +252 -0
- package/tests/run-pack.spec.ts +58 -0
- package/tsconfig.base.json +15 -0
- package/tsconfig.build.json +8 -0
- package/tsconfig.json +37 -0
- package/tsconfig.test.json +18 -0
- package/typedoc.json +37 -0
- package/ui/README.md +50 -0
- package/verify-proof.mjs +60 -0
- package/dist/cli-minimal.d.ts +0 -6
- package/dist/cli-minimal.js +0 -36
- package/dist/commands/ai.d.ts +0 -43
- package/dist/commands/ai.js +0 -616
- package/dist/commands/ask.d.ts +0 -94
- package/dist/commands/ask.js +0 -582
- package/dist/commands/coverage.d.ts +0 -8
- package/dist/commands/coverage.js +0 -252
- package/dist/commands/crawl.d.ts +0 -24
- package/dist/commands/crawl.js +0 -121
- package/dist/commands/doctor.d.ts +0 -54
- package/dist/commands/doctor.js +0 -513
- package/dist/commands/examples.d.ts +0 -33
- package/dist/commands/examples.js +0 -193
- package/dist/commands/explain.d.ts +0 -27
- package/dist/commands/explain.js +0 -630
- package/dist/commands/flakiness.d.ts +0 -73
- package/dist/commands/flakiness.js +0 -435
- package/dist/commands/generate.d.ts +0 -66
- package/dist/commands/generate.js +0 -438
- package/dist/commands/history.d.ts +0 -76
- package/dist/commands/history.js +0 -755
- package/dist/commands/init.d.ts +0 -106
- package/dist/commands/init.js +0 -616
- package/dist/commands/monitor.d.ts +0 -27
- package/dist/commands/monitor.js +0 -225
- package/dist/commands/ollama.d.ts +0 -40
- package/dist/commands/ollama.js +0 -301
- package/dist/commands/pack.d.ts +0 -70
- package/dist/commands/pack.js +0 -413
- package/dist/commands/regression.d.ts +0 -8
- package/dist/commands/regression.js +0 -340
- package/dist/commands/repair.d.ts +0 -26
- package/dist/commands/repair.js +0 -307
- package/dist/commands/report.d.ts +0 -62
- package/dist/commands/report.js +0 -378
- package/dist/commands/retry.d.ts +0 -43
- package/dist/commands/retry.js +0 -275
- package/dist/commands/run.d.ts +0 -41
- package/dist/commands/run.js +0 -169
- package/dist/commands/scan.d.ts +0 -5
- package/dist/commands/scan.js +0 -155
- package/dist/commands/secrets.d.ts +0 -58
- package/dist/commands/secrets.js +0 -289
- package/dist/commands/serve.d.ts +0 -13
- package/dist/commands/serve.js +0 -156
- package/dist/commands/slo.d.ts +0 -8
- package/dist/commands/slo.js +0 -327
- package/dist/commands/verify.d.ts +0 -32
- package/dist/commands/verify.js +0 -278
- package/dist/core/adapters/gitleaks-secrets.d.ts +0 -114
- package/dist/core/adapters/gitleaks-secrets.js +0 -410
- package/dist/core/adapters/k6-perf.d.ts +0 -85
- package/dist/core/adapters/k6-perf.js +0 -398
- package/dist/core/adapters/osv-deps.d.ts +0 -123
- package/dist/core/adapters/osv-deps.js +0 -372
- package/dist/core/adapters/playwright-native-adapter.d.ts +0 -121
- package/dist/core/adapters/playwright-native-adapter.js +0 -339
- package/dist/core/adapters/playwright-native-api.d.ts +0 -183
- package/dist/core/adapters/playwright-native-api.js +0 -465
- package/dist/core/adapters/playwright-ui.d.ts +0 -197
- package/dist/core/adapters/playwright-ui.js +0 -840
- package/dist/core/adapters/semgrep-sast.d.ts +0 -99
- package/dist/core/adapters/semgrep-sast.js +0 -322
- package/dist/core/adapters/zap-dast.d.ts +0 -133
- package/dist/core/adapters/zap-dast.js +0 -424
- package/dist/core/ai/anthropic-provider.d.ts +0 -50
- package/dist/core/ai/anthropic-provider.js +0 -223
- package/dist/core/ai/deepseek-provider.d.ts +0 -81
- package/dist/core/ai/deepseek-provider.js +0 -266
- package/dist/core/ai/index.d.ts +0 -60
- package/dist/core/ai/index.js +0 -18
- package/dist/core/ai/llm-client.d.ts +0 -45
- package/dist/core/ai/llm-client.js +0 -7
- package/dist/core/ai/mock-provider.d.ts +0 -49
- package/dist/core/ai/mock-provider.js +0 -121
- package/dist/core/ai/ollama-provider.d.ts +0 -78
- package/dist/core/ai/ollama-provider.js +0 -204
- package/dist/core/ai/openai-provider.d.ts +0 -48
- package/dist/core/ai/openai-provider.js +0 -200
- package/dist/core/ai/provider-factory.d.ts +0 -160
- package/dist/core/ai/provider-factory.js +0 -269
- package/dist/core/artifacts/index.d.ts +0 -6
- package/dist/core/artifacts/index.js +0 -6
- package/dist/core/artifacts/ui-artifacts.d.ts +0 -133
- package/dist/core/artifacts/ui-artifacts.js +0 -304
- package/dist/core/assertions/engine.d.ts +0 -51
- package/dist/core/assertions/engine.js +0 -530
- package/dist/core/assertions/index.d.ts +0 -11
- package/dist/core/assertions/index.js +0 -11
- package/dist/core/assertions/types.d.ts +0 -121
- package/dist/core/assertions/types.js +0 -37
- package/dist/core/auth/api-key-provider.d.ts +0 -16
- package/dist/core/auth/api-key-provider.js +0 -63
- package/dist/core/auth/aws-iam-provider.d.ts +0 -35
- package/dist/core/auth/aws-iam-provider.js +0 -177
- package/dist/core/auth/azure-ad-provider.d.ts +0 -15
- package/dist/core/auth/azure-ad-provider.js +0 -99
- package/dist/core/auth/basic-auth-provider.d.ts +0 -26
- package/dist/core/auth/basic-auth-provider.js +0 -111
- package/dist/core/auth/gcp-adc-provider.d.ts +0 -27
- package/dist/core/auth/gcp-adc-provider.js +0 -126
- package/dist/core/auth/index.d.ts +0 -238
- package/dist/core/auth/index.js +0 -82
- package/dist/core/auth/jwt-provider.d.ts +0 -19
- package/dist/core/auth/jwt-provider.js +0 -160
- package/dist/core/auth/manager.d.ts +0 -84
- package/dist/core/auth/manager.js +0 -230
- package/dist/core/auth/oauth2-provider.d.ts +0 -17
- package/dist/core/auth/oauth2-provider.js +0 -114
- package/dist/core/auth/totp-provider.d.ts +0 -31
- package/dist/core/auth/totp-provider.js +0 -134
- package/dist/core/auth/ui-login-provider.d.ts +0 -26
- package/dist/core/auth/ui-login-provider.js +0 -198
- package/dist/core/cache/index.d.ts +0 -7
- package/dist/core/cache/index.js +0 -6
- package/dist/core/cache/lru-cache.d.ts +0 -203
- package/dist/core/cache/lru-cache.js +0 -397
- package/dist/core/core/coverage/analyzer.d.ts +0 -101
- package/dist/core/core/coverage/analyzer.js +0 -415
- package/dist/core/core/coverage/collector.d.ts +0 -74
- package/dist/core/core/coverage/collector.js +0 -459
- package/dist/core/core/coverage/config.d.ts +0 -37
- package/dist/core/core/coverage/config.js +0 -156
- package/dist/core/core/coverage/index.d.ts +0 -11
- package/dist/core/core/coverage/index.js +0 -15
- package/dist/core/core/coverage/types.d.ts +0 -267
- package/dist/core/core/coverage/types.js +0 -6
- package/dist/core/core/coverage/vault.d.ts +0 -95
- package/dist/core/core/coverage/vault.js +0 -405
- package/dist/core/coverage/analyzer.d.ts +0 -101
- package/dist/core/coverage/analyzer.js +0 -415
- package/dist/core/coverage/collector.d.ts +0 -74
- package/dist/core/coverage/collector.js +0 -459
- package/dist/core/coverage/config.d.ts +0 -37
- package/dist/core/coverage/config.js +0 -156
- package/dist/core/coverage/index.d.ts +0 -11
- package/dist/core/coverage/index.js +0 -15
- package/dist/core/coverage/types.d.ts +0 -267
- package/dist/core/coverage/types.js +0 -6
- package/dist/core/coverage/vault.d.ts +0 -95
- package/dist/core/coverage/vault.js +0 -405
- package/dist/core/crawler/index.d.ts +0 -57
- package/dist/core/crawler/index.js +0 -281
- package/dist/core/crawler/journey-generator.d.ts +0 -49
- package/dist/core/crawler/journey-generator.js +0 -412
- package/dist/core/crawler/page-analyzer.d.ts +0 -88
- package/dist/core/crawler/page-analyzer.js +0 -709
- package/dist/core/crawler/selector-generator.d.ts +0 -34
- package/dist/core/crawler/selector-generator.js +0 -240
- package/dist/core/crawler/types.d.ts +0 -353
- package/dist/core/crawler/types.js +0 -6
- package/dist/core/dashboard/assets.d.ts +0 -6
- package/dist/core/dashboard/assets.js +0 -690
- package/dist/core/dashboard/index.d.ts +0 -6
- package/dist/core/dashboard/index.js +0 -5
- package/dist/core/dashboard/server.d.ts +0 -72
- package/dist/core/dashboard/server.js +0 -354
- package/dist/core/dashboard/types.d.ts +0 -70
- package/dist/core/dashboard/types.js +0 -5
- package/dist/core/discoverer/index.d.ts +0 -115
- package/dist/core/discoverer/index.js +0 -250
- package/dist/core/flakiness/index.d.ts +0 -228
- package/dist/core/flakiness/index.js +0 -384
- package/dist/core/generation/code-formatter.d.ts +0 -111
- package/dist/core/generation/code-formatter.js +0 -307
- package/dist/core/generation/code-generator.d.ts +0 -144
- package/dist/core/generation/code-generator.js +0 -293
- package/dist/core/generation/crawler-pack-generator.d.ts +0 -44
- package/dist/core/generation/crawler-pack-generator.js +0 -231
- package/dist/core/generation/generator.d.ts +0 -40
- package/dist/core/generation/generator.js +0 -76
- package/dist/core/generation/index.d.ts +0 -32
- package/dist/core/generation/index.js +0 -30
- package/dist/core/generation/pack-generator.d.ts +0 -107
- package/dist/core/generation/pack-generator.js +0 -416
- package/dist/core/generation/prompt-builder.d.ts +0 -132
- package/dist/core/generation/prompt-builder.js +0 -672
- package/dist/core/generation/source-analyzer.d.ts +0 -213
- package/dist/core/generation/source-analyzer.js +0 -657
- package/dist/core/generation/test-optimizer.d.ts +0 -117
- package/dist/core/generation/test-optimizer.js +0 -328
- package/dist/core/generation/types.d.ts +0 -214
- package/dist/core/generation/types.js +0 -4
- package/dist/core/hooks/compose.d.ts +0 -61
- package/dist/core/hooks/compose.js +0 -225
- package/dist/core/hooks/runner.d.ts +0 -68
- package/dist/core/hooks/runner.js +0 -303
- package/dist/core/index.d.ts +0 -104
- package/dist/core/index.js +0 -91
- package/dist/core/pack/migrator.d.ts +0 -51
- package/dist/core/pack/migrator.js +0 -304
- package/dist/core/pack/validator.d.ts +0 -42
- package/dist/core/pack/validator.js +0 -322
- package/dist/core/pack-v2/index.d.ts +0 -9
- package/dist/core/pack-v2/index.js +0 -8
- package/dist/core/pack-v2/loader.d.ts +0 -63
- package/dist/core/pack-v2/loader.js +0 -292
- package/dist/core/pack-v2/migrator.d.ts +0 -61
- package/dist/core/pack-v2/migrator.js +0 -480
- package/dist/core/pack-v2/validator.d.ts +0 -61
- package/dist/core/pack-v2/validator.js +0 -577
- package/dist/core/parallel/index.d.ts +0 -6
- package/dist/core/parallel/index.js +0 -6
- package/dist/core/parallel/parallel-runner.d.ts +0 -107
- package/dist/core/parallel/parallel-runner.js +0 -192
- package/dist/core/proof/bundle.d.ts +0 -137
- package/dist/core/proof/bundle.js +0 -160
- package/dist/core/proof/canonicalize.d.ts +0 -47
- package/dist/core/proof/canonicalize.js +0 -105
- package/dist/core/proof/index.d.ts +0 -13
- package/dist/core/proof/index.js +0 -18
- package/dist/core/proof/schema.d.ts +0 -217
- package/dist/core/proof/schema.js +0 -263
- package/dist/core/proof/signer.d.ts +0 -111
- package/dist/core/proof/signer.js +0 -226
- package/dist/core/proof/verifier.d.ts +0 -97
- package/dist/core/proof/verifier.js +0 -308
- package/dist/core/regression/detector.d.ts +0 -107
- package/dist/core/regression/detector.js +0 -497
- package/dist/core/regression/index.d.ts +0 -9
- package/dist/core/regression/index.js +0 -11
- package/dist/core/regression/trend-analyzer.d.ts +0 -102
- package/dist/core/regression/trend-analyzer.js +0 -345
- package/dist/core/regression/types.d.ts +0 -222
- package/dist/core/regression/types.js +0 -7
- package/dist/core/regression/vault.d.ts +0 -87
- package/dist/core/regression/vault.js +0 -289
- package/dist/core/repair/engine/fixer.d.ts +0 -24
- package/dist/core/repair/engine/fixer.js +0 -226
- package/dist/core/repair/engine/suggestion-engine.d.ts +0 -18
- package/dist/core/repair/engine/suggestion-engine.js +0 -187
- package/dist/core/repair/index.d.ts +0 -10
- package/dist/core/repair/index.js +0 -13
- package/dist/core/repair/repairer.d.ts +0 -90
- package/dist/core/repair/repairer.js +0 -284
- package/dist/core/repair/types.d.ts +0 -91
- package/dist/core/repair/types.js +0 -6
- package/dist/core/repair/utils/error-analyzer.d.ts +0 -28
- package/dist/core/repair/utils/error-analyzer.js +0 -264
- package/dist/core/reporting/html-reporter.d.ts +0 -119
- package/dist/core/reporting/html-reporter.js +0 -737
- package/dist/core/reporting/index.d.ts +0 -6
- package/dist/core/reporting/index.js +0 -6
- package/dist/core/retry/flakiness-integration.d.ts +0 -60
- package/dist/core/retry/flakiness-integration.js +0 -228
- package/dist/core/retry/index.d.ts +0 -14
- package/dist/core/retry/index.js +0 -16
- package/dist/core/retry/retry-engine.d.ts +0 -80
- package/dist/core/retry/retry-engine.js +0 -296
- package/dist/core/retry/types.d.ts +0 -178
- package/dist/core/retry/types.js +0 -52
- package/dist/core/retry/vault.d.ts +0 -77
- package/dist/core/retry/vault.js +0 -304
- package/dist/core/runner/e2e-helpers.d.ts +0 -102
- package/dist/core/runner/e2e-helpers.js +0 -153
- package/dist/core/runner/phase3-runner.d.ts +0 -200
- package/dist/core/runner/phase3-runner.js +0 -1041
- package/dist/core/secrets/crypto.d.ts +0 -75
- package/dist/core/secrets/crypto.js +0 -223
- package/dist/core/secrets/manager.d.ts +0 -76
- package/dist/core/secrets/manager.js +0 -219
- package/dist/core/security/redaction-patterns-extended.d.ts +0 -27
- package/dist/core/security/redaction-patterns-extended.js +0 -247
- package/dist/core/security/redactor.d.ts +0 -71
- package/dist/core/security/redactor.js +0 -279
- package/dist/core/self-healing/assertion-healer.d.ts +0 -97
- package/dist/core/self-healing/assertion-healer.js +0 -371
- package/dist/core/self-healing/engine.d.ts +0 -122
- package/dist/core/self-healing/engine.js +0 -538
- package/dist/core/self-healing/index.d.ts +0 -10
- package/dist/core/self-healing/index.js +0 -11
- package/dist/core/self-healing/selector-healer.d.ts +0 -103
- package/dist/core/self-healing/selector-healer.js +0 -372
- package/dist/core/self-healing/types.d.ts +0 -152
- package/dist/core/self-healing/types.js +0 -6
- package/dist/core/serve/diagnostics-collector.d.ts +0 -32
- package/dist/core/serve/diagnostics-collector.js +0 -149
- package/dist/core/serve/health-checker.d.ts +0 -44
- package/dist/core/serve/health-checker.js +0 -219
- package/dist/core/serve/index.d.ts +0 -8
- package/dist/core/serve/index.js +0 -8
- package/dist/core/serve/metrics-collector.d.ts +0 -24
- package/dist/core/serve/metrics-collector.js +0 -322
- package/dist/core/serve/process-manager.d.ts +0 -36
- package/dist/core/serve/process-manager.js +0 -213
- package/dist/core/serve/server.d.ts +0 -36
- package/dist/core/serve/server.js +0 -191
- package/dist/core/slo/config.d.ts +0 -107
- package/dist/core/slo/config.js +0 -360
- package/dist/core/slo/index.d.ts +0 -11
- package/dist/core/slo/index.js +0 -15
- package/dist/core/slo/sli-calculator.d.ts +0 -92
- package/dist/core/slo/sli-calculator.js +0 -364
- package/dist/core/slo/slo-tracker.d.ts +0 -148
- package/dist/core/slo/slo-tracker.js +0 -379
- package/dist/core/slo/types.d.ts +0 -281
- package/dist/core/slo/types.js +0 -7
- package/dist/core/slo/vault.d.ts +0 -102
- package/dist/core/slo/vault.js +0 -427
- package/dist/core/tui/index.d.ts +0 -7
- package/dist/core/tui/index.js +0 -6
- package/dist/core/tui/monitor.d.ts +0 -92
- package/dist/core/tui/monitor.js +0 -271
- package/dist/core/tui/renderer.d.ts +0 -33
- package/dist/core/tui/renderer.js +0 -218
- package/dist/core/tui/types.d.ts +0 -63
- package/dist/core/tui/types.js +0 -5
- package/dist/core/types/pack-v1.d.ts +0 -251
- package/dist/core/types/pack-v1.js +0 -5
- package/dist/core/types/pack-v2.d.ts +0 -425
- package/dist/core/types/pack-v2.js +0 -8
- package/dist/core/types/trust-score.d.ts +0 -69
- package/dist/core/types/trust-score.js +0 -191
- package/dist/core/vault/cas.d.ts +0 -90
- package/dist/core/vault/cas.js +0 -261
- package/dist/core/vault/index.d.ts +0 -326
- package/dist/core/vault/index.js +0 -1042
- package/dist/core/visual/index.d.ts +0 -6
- package/dist/core/visual/index.js +0 -6
- package/dist/core/visual/visual-regression.d.ts +0 -113
- package/dist/core/visual/visual-regression.js +0 -236
- package/dist/core/watch/index.d.ts +0 -7
- package/dist/core/watch/index.js +0 -6
- package/dist/core/watch/watch-mode.d.ts +0 -213
- package/dist/core/watch/watch-mode.js +0 -389
- package/dist/generators/index.d.ts +0 -5
- package/dist/generators/index.js +0 -5
- package/dist/generators/json-reporter.d.ts +0 -10
- package/dist/generators/json-reporter.js +0 -12
- package/dist/generators/test-generator.d.ts +0 -18
- package/dist/generators/test-generator.js +0 -78
- package/dist/index.d.ts +0 -8
- package/dist/index.js +0 -246
- package/dist/scanners/dom-scanner.d.ts +0 -52
- package/dist/scanners/dom-scanner.js +0 -296
- package/dist/scanners/index.d.ts +0 -4
- package/dist/scanners/index.js +0 -4
- package/dist/schemas/pack.schema.json +0 -236
- package/dist/types/scan.d.ts +0 -68
- package/dist/types/scan.js +0 -4
- package/dist/utils/config.d.ts +0 -5
- package/dist/utils/config.js +0 -136
- /package/{bin → cli/bin}/qa360.js +0 -0
- /package/{examples → cli/examples}/accessibility.yml +0 -0
- /package/{examples → cli/examples}/api-basic.yml +0 -0
- /package/{examples → cli/examples}/complete.yml +0 -0
- /package/{examples → cli/examples}/crawler.yml +0 -0
- /package/{examples → cli/examples}/fullstack.yml +0 -0
- /package/{examples → cli/examples}/security.yml +0 -0
- /package/{examples → cli/examples}/ui-advanced.yml +0 -0
- /package/{examples → cli/examples}/ui-basic.yml +0 -0
- /package/{dist/core → core}/schemas/pack.schema.json +0 -0
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QA360 Flakiness Detection Engine
|
|
3
|
+
*
|
|
4
|
+
* Detects and scores test flakiness using consecutive runs and pattern analysis.
|
|
5
|
+
* This is the core differentiator of QA360 - measuring test reliability.
|
|
6
|
+
*
|
|
7
|
+
* Scoring Categories:
|
|
8
|
+
* - Legendary (100): Never flaky - 100% reliable
|
|
9
|
+
* - Solid (90-99): Rarely flaky
|
|
10
|
+
* - Good (75-89): Occasionally flaky
|
|
11
|
+
* - Shaky (50-74): Often flaky - attention needed
|
|
12
|
+
* - Unstable (0-49): Very flaky - quarantine recommended
|
|
13
|
+
*
|
|
14
|
+
* @module flakiness
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { createHash } from 'crypto';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Flakiness score category
|
|
21
|
+
*/
|
|
22
|
+
export enum FlakinessCategory {
|
|
23
|
+
LEGENDARY = 'legendary', // 100
|
|
24
|
+
SOLID = 'solid', // 90-99
|
|
25
|
+
GOOD = 'good', // 75-89
|
|
26
|
+
SHAKY = 'shaky', // 50-74
|
|
27
|
+
UNSTABLE = 'unstable' // 0-49
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Flakiness category metadata
|
|
32
|
+
*/
|
|
33
|
+
export const FLAKINESS_CATEGORIES: Record<FlakinessCategory, {
|
|
34
|
+
min: number;
|
|
35
|
+
max: number;
|
|
36
|
+
label: string;
|
|
37
|
+
emoji: string;
|
|
38
|
+
color: string;
|
|
39
|
+
description: string;
|
|
40
|
+
action: string;
|
|
41
|
+
}> = {
|
|
42
|
+
[FlakinessCategory.LEGENDARY]: {
|
|
43
|
+
min: 100,
|
|
44
|
+
max: 100,
|
|
45
|
+
label: 'LEGENDARY',
|
|
46
|
+
emoji: '🟢',
|
|
47
|
+
color: '#10B981',
|
|
48
|
+
description: 'Jamais flaky - 100% fiable',
|
|
49
|
+
action: 'None - keep doing what you\'re doing'
|
|
50
|
+
},
|
|
51
|
+
[FlakinessCategory.SOLID]: {
|
|
52
|
+
min: 90,
|
|
53
|
+
max: 99,
|
|
54
|
+
label: 'SOLID',
|
|
55
|
+
emoji: '🟢',
|
|
56
|
+
color: '#34D399',
|
|
57
|
+
description: 'Rarement flaky',
|
|
58
|
+
action: 'Monitor - occasional hiccups'
|
|
59
|
+
},
|
|
60
|
+
[FlakinessCategory.GOOD]: {
|
|
61
|
+
min: 75,
|
|
62
|
+
max: 89,
|
|
63
|
+
label: 'GOOD',
|
|
64
|
+
emoji: '🟡',
|
|
65
|
+
color: '#FBBF24',
|
|
66
|
+
description: 'Occasionnellement flaky',
|
|
67
|
+
action: 'Watch - may need attention'
|
|
68
|
+
},
|
|
69
|
+
[FlakinessCategory.SHAKY]: {
|
|
70
|
+
min: 50,
|
|
71
|
+
max: 74,
|
|
72
|
+
label: 'SHAKY',
|
|
73
|
+
emoji: '🟠',
|
|
74
|
+
color: '#F97316',
|
|
75
|
+
description: 'Souvent flaky - attention requise',
|
|
76
|
+
action: 'Investigate - fix recommended'
|
|
77
|
+
},
|
|
78
|
+
[FlakinessCategory.UNSTABLE]: {
|
|
79
|
+
min: 0,
|
|
80
|
+
max: 49,
|
|
81
|
+
label: 'UNSTABLE',
|
|
82
|
+
emoji: '🔴',
|
|
83
|
+
color: '#EF4444',
|
|
84
|
+
description: 'Très flaky - quarantaine recommandée',
|
|
85
|
+
action: 'Quarantine - unblock the team'
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Test result from a single run
|
|
91
|
+
*/
|
|
92
|
+
export interface TestResult {
|
|
93
|
+
/** Test identifier (unique per test) */
|
|
94
|
+
testId: string;
|
|
95
|
+
/** Test name/title */
|
|
96
|
+
testName: string;
|
|
97
|
+
/** File path */
|
|
98
|
+
filePath: string;
|
|
99
|
+
/** Gate name */
|
|
100
|
+
gate: string;
|
|
101
|
+
/** Whether the test passed */
|
|
102
|
+
success: boolean;
|
|
103
|
+
/** Duration in milliseconds */
|
|
104
|
+
durationMs: number;
|
|
105
|
+
/** Error type if failed */
|
|
106
|
+
errorType?: string;
|
|
107
|
+
/** Error message if failed */
|
|
108
|
+
errorMessage?: string;
|
|
109
|
+
/** Timestamp of run */
|
|
110
|
+
timestamp: number;
|
|
111
|
+
/** Environment (local, ci, staging) */
|
|
112
|
+
environment: string;
|
|
113
|
+
/** Git branch */
|
|
114
|
+
branch?: string;
|
|
115
|
+
/** Commit hash */
|
|
116
|
+
commitHash?: string;
|
|
117
|
+
/** CI run ID */
|
|
118
|
+
ciRunId?: string;
|
|
119
|
+
/** Tags (team, repo, etc.) */
|
|
120
|
+
tags?: Record<string, string>;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Flakiness detection result for a single test
|
|
125
|
+
*/
|
|
126
|
+
export interface FlakinessResult {
|
|
127
|
+
/** Test identifier */
|
|
128
|
+
testId: string;
|
|
129
|
+
/** Test name */
|
|
130
|
+
testName: string;
|
|
131
|
+
/** File path */
|
|
132
|
+
filePath: string;
|
|
133
|
+
/** Gate name */
|
|
134
|
+
gate: string;
|
|
135
|
+
/** Flakiness score (0-100) */
|
|
136
|
+
score: number;
|
|
137
|
+
/** Flakiness category */
|
|
138
|
+
category: FlakinessCategory;
|
|
139
|
+
/** Total number of runs analyzed */
|
|
140
|
+
totalRuns: number;
|
|
141
|
+
/** Number of successful runs */
|
|
142
|
+
successfulRuns: number;
|
|
143
|
+
/** Average duration in ms */
|
|
144
|
+
avgDurationMs: number;
|
|
145
|
+
/** Detected pattern type (if any) */
|
|
146
|
+
patternType?: string;
|
|
147
|
+
/** Suggested fix */
|
|
148
|
+
suggestedFix?: string;
|
|
149
|
+
/** Confidence in pattern detection (0-1) */
|
|
150
|
+
confidence?: number;
|
|
151
|
+
/** First seen timestamp */
|
|
152
|
+
firstSeen?: number;
|
|
153
|
+
/** Last seen timestamp */
|
|
154
|
+
lastSeen?: number;
|
|
155
|
+
/** Current streak (consecutive passes or failures) */
|
|
156
|
+
currentStreak?: number;
|
|
157
|
+
/** Streak type */
|
|
158
|
+
streakType?: 'pass' | 'fail';
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Flakiness detection options
|
|
163
|
+
*/
|
|
164
|
+
export interface FlakinessDetectionOptions {
|
|
165
|
+
/** Minimum runs before calculating score */
|
|
166
|
+
minRuns?: number;
|
|
167
|
+
/** Number of consecutive runs for detection */
|
|
168
|
+
consecutiveRuns?: number;
|
|
169
|
+
/** Time window in days (only consider runs within this window) */
|
|
170
|
+
timeWindowDays?: number;
|
|
171
|
+
/** Enable pattern detection */
|
|
172
|
+
enablePatternDetection?: boolean;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Default flakiness detection options
|
|
177
|
+
*/
|
|
178
|
+
export const DEFAULT_FLAKINESS_OPTIONS: Required<FlakinessDetectionOptions> = {
|
|
179
|
+
minRuns: 3,
|
|
180
|
+
consecutiveRuns: 3,
|
|
181
|
+
timeWindowDays: 30,
|
|
182
|
+
enablePatternDetection: true
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Flakiness pattern types
|
|
187
|
+
*/
|
|
188
|
+
export enum FlakinessPattern {
|
|
189
|
+
TIMING = 'timing',
|
|
190
|
+
RACE_CONDITION = 'race_condition',
|
|
191
|
+
EXTERNAL_DEPENDENCY = 'external_dependency',
|
|
192
|
+
ENVIRONMENT_SPECIFIC = 'environment_specific',
|
|
193
|
+
SELECTOR_ISSUE = 'selector_issue',
|
|
194
|
+
UNKNOWN = 'unknown'
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Pattern detection result
|
|
199
|
+
*/
|
|
200
|
+
export interface PatternDetection {
|
|
201
|
+
/** Pattern type */
|
|
202
|
+
patternType: FlakinessPattern;
|
|
203
|
+
/** Pattern description */
|
|
204
|
+
description: string;
|
|
205
|
+
/** Suggested fix */
|
|
206
|
+
suggestedFix: string;
|
|
207
|
+
/** Confidence (0-1) */
|
|
208
|
+
confidence: number;
|
|
209
|
+
/** Whether auto-fix is possible */
|
|
210
|
+
autoFixPossible: boolean;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Calculate flakiness score from test results
|
|
215
|
+
* @param results Array of test results
|
|
216
|
+
* @returns Flakiness score (0-100)
|
|
217
|
+
*/
|
|
218
|
+
export function calculateFlakinessScore(results: TestResult[]): number {
|
|
219
|
+
if (results.length === 0) {
|
|
220
|
+
return 100; // No failures means 100% by default
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const successCount = results.filter(r => r.success).length;
|
|
224
|
+
const score = Math.round((successCount / results.length) * 100);
|
|
225
|
+
|
|
226
|
+
return Math.max(0, Math.min(100, score));
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Get flakiness category from score
|
|
231
|
+
* @param score Flakiness score (0-100)
|
|
232
|
+
* @returns Flakiness category
|
|
233
|
+
*/
|
|
234
|
+
export function getFlakinessCategory(score: number): FlakinessCategory {
|
|
235
|
+
if (score === 100) return FlakinessCategory.LEGENDARY;
|
|
236
|
+
if (score >= 90) return FlakinessCategory.SOLID;
|
|
237
|
+
if (score >= 75) return FlakinessCategory.GOOD;
|
|
238
|
+
if (score >= 50) return FlakinessCategory.SHAKY;
|
|
239
|
+
return FlakinessCategory.UNSTABLE;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Generate a unique test ID
|
|
244
|
+
* @param testName Test name
|
|
245
|
+
* @param filePath File path
|
|
246
|
+
* @returns Unique test ID
|
|
247
|
+
*/
|
|
248
|
+
export function generateTestId(testName: string, filePath: string): string {
|
|
249
|
+
const hash = createHash('sha256')
|
|
250
|
+
.update(`${filePath}:${testName}`)
|
|
251
|
+
.digest('hex')
|
|
252
|
+
.substring(0, 16);
|
|
253
|
+
return hash;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Analyze test results for flakiness patterns
|
|
258
|
+
* @param results Array of test results for the same test
|
|
259
|
+
* @returns Pattern detection result or undefined
|
|
260
|
+
*/
|
|
261
|
+
export function detectFlakinessPattern(results: TestResult[]): PatternDetection | undefined {
|
|
262
|
+
if (results.length < 3) {
|
|
263
|
+
return undefined;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const failures = results.filter(r => !r.success);
|
|
267
|
+
if (failures.length === 0) {
|
|
268
|
+
return undefined; // No failures to analyze
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Collect error messages as lowercase strings
|
|
272
|
+
const errorMessages = failures.map(f => (f.errorMessage || '').toLowerCase());
|
|
273
|
+
|
|
274
|
+
// Helper to check if any error contains a keyword
|
|
275
|
+
const anyErrorContains = (keywords: string[]): boolean => {
|
|
276
|
+
return errorMessages.some(err => keywords.some(kw => err.includes(kw)));
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
// Check for timing issues
|
|
280
|
+
if (anyErrorContains(['timeout', 'timed out', 'waiting for', 'element not found', 'waiting for selector'])) {
|
|
281
|
+
return {
|
|
282
|
+
patternType: FlakinessPattern.TIMING,
|
|
283
|
+
description: 'Timing issues - test is too fast for the application',
|
|
284
|
+
suggestedFix: 'Increase timeout or add explicit wait (waitForSelector, waitForLoadState)',
|
|
285
|
+
confidence: 0.85,
|
|
286
|
+
autoFixPossible: true
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Check for selector issues
|
|
291
|
+
if (anyErrorContains(['selector', 'detached', 'stale element', 'element not found'])) {
|
|
292
|
+
return {
|
|
293
|
+
patternType: FlakinessPattern.SELECTOR_ISSUE,
|
|
294
|
+
description: 'Selector issues - element not consistently found',
|
|
295
|
+
suggestedFix: 'Use data-testid selectors instead of CSS selectors for better reliability',
|
|
296
|
+
confidence: 0.80,
|
|
297
|
+
autoFixPossible: true
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Check for external dependency issues
|
|
302
|
+
if (anyErrorContains(['econnrefused', 'connection refused', 'connection reset', 'network error', 'network unreachable', 'api timeout'])) {
|
|
303
|
+
return {
|
|
304
|
+
patternType: FlakinessPattern.EXTERNAL_DEPENDENCY,
|
|
305
|
+
description: 'External dependency issues - network or service unavailable',
|
|
306
|
+
suggestedFix: 'Add retry logic with exponential backoff or mock the external dependency',
|
|
307
|
+
confidence: 0.90,
|
|
308
|
+
autoFixPossible: true
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Check for race conditions
|
|
313
|
+
if (anyErrorContains(['race condition', 'state changed', 'unexpected state', 'assertion failed'])) {
|
|
314
|
+
return {
|
|
315
|
+
patternType: FlakinessPattern.RACE_CONDITION,
|
|
316
|
+
description: 'Possible race condition - state changes unexpectedly',
|
|
317
|
+
suggestedFix: 'Add proper synchronization/locks or use explicit waits',
|
|
318
|
+
confidence: 0.70,
|
|
319
|
+
autoFixPossible: false
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Check for environment-specific issues
|
|
324
|
+
const envs = new Set(results.map(r => r.environment));
|
|
325
|
+
if (envs.size > 1) {
|
|
326
|
+
const failEnvs = new Set(failures.map(r => r.environment));
|
|
327
|
+
const passEnvs = new Set(results.filter(r => r.success).map(r => r.environment));
|
|
328
|
+
|
|
329
|
+
// Check if failures are concentrated in one environment
|
|
330
|
+
for (const env of failEnvs) {
|
|
331
|
+
if (!passEnvs.has(env)) {
|
|
332
|
+
return {
|
|
333
|
+
patternType: FlakinessPattern.ENVIRONMENT_SPECIFIC,
|
|
334
|
+
description: `Environment-specific issue - fails on ${env} only`,
|
|
335
|
+
suggestedFix: 'Check environment-specific configuration (OS, timezone, locale)',
|
|
336
|
+
confidence: 0.75,
|
|
337
|
+
autoFixPossible: false
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return {
|
|
344
|
+
patternType: FlakinessPattern.UNKNOWN,
|
|
345
|
+
description: 'Flaky behavior detected but pattern unclear',
|
|
346
|
+
suggestedFix: 'Manual investigation recommended - check logs for specific failure patterns',
|
|
347
|
+
confidence: 0.50,
|
|
348
|
+
autoFixPossible: false
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Calculate consecutive streak (passes or failures)
|
|
354
|
+
* @param results Array of test results sorted by timestamp
|
|
355
|
+
* @returns Current streak info
|
|
356
|
+
*/
|
|
357
|
+
export function calculateStreak(results: TestResult[]): {
|
|
358
|
+
currentStreak: number;
|
|
359
|
+
streakType: 'pass' | 'fail';
|
|
360
|
+
} {
|
|
361
|
+
if (results.length === 0) {
|
|
362
|
+
return { currentStreak: 0, streakType: 'pass' };
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Sort by timestamp (newest first)
|
|
366
|
+
const sorted = [...results].sort((a, b) => b.timestamp - a.timestamp);
|
|
367
|
+
|
|
368
|
+
let streak = 0;
|
|
369
|
+
let streakType: 'pass' | 'fail' = sorted[0].success ? 'pass' : 'fail';
|
|
370
|
+
|
|
371
|
+
for (const result of sorted) {
|
|
372
|
+
if (result.success === (streakType === 'pass')) {
|
|
373
|
+
streak++;
|
|
374
|
+
} else {
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
return { currentStreak: streak, streakType };
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Format flakiness score for display
|
|
384
|
+
* @param score Flakiness score (0-100)
|
|
385
|
+
* @returns Formatted string with emoji
|
|
386
|
+
*/
|
|
387
|
+
export function formatFlakinessScore(score: number): string {
|
|
388
|
+
const category = getFlakinessCategory(score);
|
|
389
|
+
const meta = FLAKINESS_CATEGORIES[category];
|
|
390
|
+
return `${meta.emoji} ${category.toUpperCase()} (${score}%)`;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Flakiness Detection Engine
|
|
395
|
+
*
|
|
396
|
+
* Main class for detecting and scoring test flakiness
|
|
397
|
+
*/
|
|
398
|
+
export class FlakinessDetector {
|
|
399
|
+
private options: Required<FlakinessDetectionOptions>;
|
|
400
|
+
|
|
401
|
+
constructor(options: FlakinessDetectionOptions = {}) {
|
|
402
|
+
this.options = { ...DEFAULT_FLAKINESS_OPTIONS, ...options };
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Analyze a single test's flakiness from its run history
|
|
407
|
+
* @param testId Test identifier
|
|
408
|
+
* @param results Array of test results (must be from the same test)
|
|
409
|
+
* @returns Flakiness result
|
|
410
|
+
*/
|
|
411
|
+
analyzeTest(testId: string, results: TestResult[]): FlakinessResult {
|
|
412
|
+
// Filter by time window
|
|
413
|
+
const timeWindow = this.options.timeWindowDays * 24 * 60 * 60 * 1000;
|
|
414
|
+
const now = Date.now();
|
|
415
|
+
const cutoff = now - timeWindow;
|
|
416
|
+
|
|
417
|
+
const filteredResults = results.filter(r => r.timestamp >= cutoff);
|
|
418
|
+
|
|
419
|
+
// Need minimum runs to calculate score
|
|
420
|
+
if (filteredResults.length < this.options.minRuns) {
|
|
421
|
+
return {
|
|
422
|
+
testId,
|
|
423
|
+
testName: results[0]?.testName || 'Unknown',
|
|
424
|
+
filePath: results[0]?.filePath || 'Unknown',
|
|
425
|
+
gate: results[0]?.gate || 'Unknown',
|
|
426
|
+
score: 100, // Default to 100 if not enough data
|
|
427
|
+
category: FlakinessCategory.LEGENDARY,
|
|
428
|
+
totalRuns: filteredResults.length,
|
|
429
|
+
successfulRuns: filteredResults.filter(r => r.success).length,
|
|
430
|
+
avgDurationMs: this.averageDuration(filteredResults)
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// Calculate score
|
|
435
|
+
const score = calculateFlakinessScore(filteredResults);
|
|
436
|
+
const category = getFlakinessCategory(score);
|
|
437
|
+
|
|
438
|
+
// Calculate streak
|
|
439
|
+
const { currentStreak, streakType } = calculateStreak(filteredResults);
|
|
440
|
+
|
|
441
|
+
// Detect patterns if enabled
|
|
442
|
+
let patternType: string | undefined;
|
|
443
|
+
let suggestedFix: string | undefined;
|
|
444
|
+
let confidence: number | undefined;
|
|
445
|
+
|
|
446
|
+
if (this.options.enablePatternDetection) {
|
|
447
|
+
const pattern = detectFlakinessPattern(filteredResults);
|
|
448
|
+
if (pattern) {
|
|
449
|
+
patternType = pattern.patternType;
|
|
450
|
+
suggestedFix = pattern.suggestedFix;
|
|
451
|
+
confidence = pattern.confidence;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
return {
|
|
456
|
+
testId,
|
|
457
|
+
testName: results[0].testName,
|
|
458
|
+
filePath: results[0].filePath,
|
|
459
|
+
gate: results[0].gate,
|
|
460
|
+
score,
|
|
461
|
+
category,
|
|
462
|
+
totalRuns: filteredResults.length,
|
|
463
|
+
successfulRuns: filteredResults.filter(r => r.success).length,
|
|
464
|
+
avgDurationMs: this.averageDuration(filteredResults),
|
|
465
|
+
patternType,
|
|
466
|
+
suggestedFix,
|
|
467
|
+
confidence,
|
|
468
|
+
firstSeen: Math.min(...filteredResults.map(r => r.timestamp)),
|
|
469
|
+
lastSeen: Math.max(...filteredResults.map(r => r.timestamp)),
|
|
470
|
+
currentStreak,
|
|
471
|
+
streakType
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Analyze multiple tests and return flakiness results
|
|
477
|
+
* @param testResults Map of testId to array of results
|
|
478
|
+
* @returns Array of flakiness results
|
|
479
|
+
*/
|
|
480
|
+
analyzeAll(testResults: Map<string, TestResult[]>): FlakinessResult[] {
|
|
481
|
+
const flakinessResults: FlakinessResult[] = [];
|
|
482
|
+
|
|
483
|
+
for (const [testId, testRuns] of testResults.entries()) {
|
|
484
|
+
if (testRuns.length > 0) {
|
|
485
|
+
flakinessResults.push(this.analyzeTest(testId, testRuns));
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// Sort by score (lowest first) - most flaky first
|
|
490
|
+
flakinessResults.sort((a, b) => a.score - b.score);
|
|
491
|
+
|
|
492
|
+
return flakinessResults;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Check if a test should be quarantined based on flakiness
|
|
497
|
+
* @param result Flakiness result
|
|
498
|
+
* @returns Whether to quarantine
|
|
499
|
+
*/
|
|
500
|
+
shouldQuarantine(result: FlakinessResult): boolean {
|
|
501
|
+
// Quarantine if:
|
|
502
|
+
// 1. Score is below 50 (Unstable)
|
|
503
|
+
// 2. Score is below 75 (Shaky) AND has more than 5 runs
|
|
504
|
+
return (
|
|
505
|
+
result.category === FlakinessCategory.UNSTABLE ||
|
|
506
|
+
(result.category === FlakinessCategory.SHAKY && result.totalRuns >= 5)
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Get quarantine recommendation message
|
|
512
|
+
* @param result Flakiness result
|
|
513
|
+
* @returns Recommendation message
|
|
514
|
+
*/
|
|
515
|
+
getQuarantineRecommendation(result: FlakinessResult): string {
|
|
516
|
+
if (!this.shouldQuarantine(result)) {
|
|
517
|
+
return `Test is ${FLAKINESS_CATEGORIES[result.category].emoji} ${result.category} - no quarantine needed`;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
return [
|
|
521
|
+
`❌ Test "${result.testName}" is ${FLAKINESS_CATEGORIES[result.category].emoji} ${FLAKINESS_CATEGORIES[result.category].label} (${result.score}% flaky)`,
|
|
522
|
+
` Passed ${result.successfulRuns}/${result.totalRuns} times`,
|
|
523
|
+
result.suggestedFix ? ` 💡 Suggested: ${result.suggestedFix}` : '',
|
|
524
|
+
` 📋 Action: ${FLAKINESS_CATEGORIES[result.category].action}`
|
|
525
|
+
].filter(Boolean).join('\n');
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Calculate average duration
|
|
530
|
+
*/
|
|
531
|
+
private averageDuration(results: TestResult[]): number {
|
|
532
|
+
if (results.length === 0) return 0;
|
|
533
|
+
const total = results.reduce((sum, r) => sum + r.durationMs, 0);
|
|
534
|
+
return Math.round(total / results.length);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Formatter Unit Tests
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
6
|
+
import { CodeFormatter } from '../code-formatter.js';
|
|
7
|
+
|
|
8
|
+
describe('CodeFormatter', () => {
|
|
9
|
+
let formatter: CodeFormatter;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
formatter = new CodeFormatter();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
describe('formatTypeScript', () => {
|
|
16
|
+
it('should format TypeScript code', () => {
|
|
17
|
+
const code = `import{foo}from'./foo';const x=foo();`;
|
|
18
|
+
const result = formatter.formatTypeScript(code);
|
|
19
|
+
|
|
20
|
+
expect(result).toContain('import');
|
|
21
|
+
expect(result).toContain('from');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should normalize quotes to single', () => {
|
|
25
|
+
const code = 'const x = "hello";';
|
|
26
|
+
const result = formatter.formatTypeScript(code);
|
|
27
|
+
|
|
28
|
+
// Should have single quotes
|
|
29
|
+
expect(result).toContain("'");
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should remove trailing whitespace', () => {
|
|
33
|
+
const code = `const x = 1; \nconst y = 2;`;
|
|
34
|
+
const result = formatter.formatTypeScript(code);
|
|
35
|
+
|
|
36
|
+
expect(result).toContain('const x = 1;\nconst y = 2;');
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe('formatJavaScript', () => {
|
|
41
|
+
it('should format JavaScript code', () => {
|
|
42
|
+
const code = `const x=1;`;
|
|
43
|
+
const result = formatter.formatJavaScript(code);
|
|
44
|
+
|
|
45
|
+
expect(result).toBeTruthy();
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('formatGo', () => {
|
|
50
|
+
it('should normalize Go indentation to tabs', () => {
|
|
51
|
+
const code = `func main() {\n fmt.Println("hello")\n}`;
|
|
52
|
+
const result = formatter.formatGo(code);
|
|
53
|
+
|
|
54
|
+
// Go uses tabs
|
|
55
|
+
expect(result).toContain('\tfmt.Println');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should ensure file ends with newline', () => {
|
|
59
|
+
const code = 'package main';
|
|
60
|
+
const result = formatter.formatGo(code);
|
|
61
|
+
|
|
62
|
+
// Check for trailing newline
|
|
63
|
+
expect(result.slice(-1)).toBe('\n');
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe('formatPython', () => {
|
|
68
|
+
it('should normalize Python indentation to 4 spaces', () => {
|
|
69
|
+
const code = `def test():\n print('hello')`;
|
|
70
|
+
const result = formatter.formatPython(code);
|
|
71
|
+
|
|
72
|
+
expect(result).toContain(' print');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should ensure file ends with newline', () => {
|
|
76
|
+
const code = 'def test(): pass';
|
|
77
|
+
const result = formatter.formatPython(code);
|
|
78
|
+
|
|
79
|
+
expect(result.slice(-1)).toBe('\n');
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe('validate', () => {
|
|
84
|
+
it('should detect unbalanced braces', () => {
|
|
85
|
+
const code = 'function test() { return true;';
|
|
86
|
+
const result = formatter.validate(code, 'typescript');
|
|
87
|
+
|
|
88
|
+
expect(result.errors.length).toBeGreaterThan(0);
|
|
89
|
+
expect(result.errors[0]).toContain('braces');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should detect unbalanced parentheses', () => {
|
|
93
|
+
const code = 'const x = (1 + 2;';
|
|
94
|
+
const result = formatter.validate(code, 'typescript');
|
|
95
|
+
|
|
96
|
+
expect(result.errors.length).toBeGreaterThan(0);
|
|
97
|
+
expect(result.errors[0]).toContain('parentheses');
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('should detect empty code', () => {
|
|
101
|
+
const result = formatter.validate('', 'typescript');
|
|
102
|
+
|
|
103
|
+
expect(result.errors).toContain('Code is empty');
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should warn about console.log', () => {
|
|
107
|
+
const code = `
|
|
108
|
+
console.log('test');
|
|
109
|
+
console.log('test2');
|
|
110
|
+
console.log('test3');
|
|
111
|
+
`;
|
|
112
|
+
const result = formatter.validate(code, 'typescript');
|
|
113
|
+
|
|
114
|
+
expect(result.warnings.length).toBeGreaterThan(0);
|
|
115
|
+
expect(result.warnings[0]).toContain('console.log');
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('should warn about any type', () => {
|
|
119
|
+
const code = 'const x: any = 1;';
|
|
120
|
+
const result = formatter.validate(code, 'typescript');
|
|
121
|
+
|
|
122
|
+
expect(result.warnings.length).toBeGreaterThan(0);
|
|
123
|
+
expect(result.warnings[0]).toContain('any');
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('should return no errors for valid code', () => {
|
|
127
|
+
const code = `
|
|
128
|
+
import { test } from 'vitest';
|
|
129
|
+
|
|
130
|
+
test('example', () => {
|
|
131
|
+
expect(1 + 1).toBe(2);
|
|
132
|
+
});
|
|
133
|
+
`;
|
|
134
|
+
const result = formatter.validate(code, 'typescript');
|
|
135
|
+
|
|
136
|
+
expect(result.errors).toHaveLength(0);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
describe('configuration', () => {
|
|
141
|
+
it('should use custom indent size', () => {
|
|
142
|
+
const formatter = new CodeFormatter({ indentSize: 4 });
|
|
143
|
+
const code = 'const x = 1;';
|
|
144
|
+
const result = formatter.format(code, 'typescript');
|
|
145
|
+
|
|
146
|
+
expect(result).toBeTruthy();
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('should use double quotes when configured', () => {
|
|
150
|
+
const formatter = new CodeFormatter({ quotes: 'double' });
|
|
151
|
+
const code = "const x = 'hello';";
|
|
152
|
+
const result = formatter.formatTypeScript(code);
|
|
153
|
+
|
|
154
|
+
// With double quotes preference, should have more double quotes
|
|
155
|
+
expect(result).toContain('"');
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('should respect sortImports option', () => {
|
|
159
|
+
const noSortFormatter = new CodeFormatter({ sortImports: false });
|
|
160
|
+
const code = `
|
|
161
|
+
import { c } from './c';
|
|
162
|
+
import { a } from './a';
|
|
163
|
+
`;
|
|
164
|
+
const result = noSortFormatter.formatTypeScript(code);
|
|
165
|
+
|
|
166
|
+
// Should not reorder when sort is disabled
|
|
167
|
+
expect(result).toBeTruthy();
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
});
|