playwright-intelligence-engine 0.0.0-stage → 2.0.1
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/LICENSE +191 -0
- package/README.md +229 -3
- package/bin/pw-intel.js +37 -0
- package/dist/authoring/author.d.ts +83 -0
- package/dist/authoring/author.d.ts.map +1 -0
- package/dist/authoring/generation-contract.d.ts +90 -0
- package/dist/authoring/generation-contract.d.ts.map +1 -0
- package/dist/authoring/hybrid-author.d.ts +6 -0
- package/dist/authoring/hybrid-author.d.ts.map +1 -0
- package/dist/authoring/index.d.ts +7 -0
- package/dist/authoring/index.d.ts.map +1 -0
- package/dist/authoring/llm-author.d.ts +28 -0
- package/dist/authoring/llm-author.d.ts.map +1 -0
- package/dist/authoring/naming/index.d.ts +4 -0
- package/dist/authoring/naming/index.d.ts.map +1 -0
- package/dist/authoring/naming/name-plan.d.ts +45 -0
- package/dist/authoring/naming/name-plan.d.ts.map +1 -0
- package/dist/authoring/naming/name-planner.d.ts +25 -0
- package/dist/authoring/naming/name-planner.d.ts.map +1 -0
- package/dist/authoring/naming/naming-linter.d.ts +20 -0
- package/dist/authoring/naming/naming-linter.d.ts.map +1 -0
- package/dist/authoring/template-author.d.ts +6 -0
- package/dist/authoring/template-author.d.ts.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/collectors/collector-interface.d.ts +7 -0
- package/dist/collectors/collector-interface.d.ts.map +1 -0
- package/dist/collectors/environment-collector.d.ts +12 -0
- package/dist/collectors/environment-collector.d.ts.map +1 -0
- package/dist/collectors/error-collector.d.ts +18 -0
- package/dist/collectors/error-collector.d.ts.map +1 -0
- package/dist/collectors/git-diff-collector.d.ts +20 -0
- package/dist/collectors/git-diff-collector.d.ts.map +1 -0
- package/dist/collectors/live-browser-collector.d.ts +45 -0
- package/dist/collectors/live-browser-collector.d.ts.map +1 -0
- package/dist/collectors/network-collector.d.ts +28 -0
- package/dist/collectors/network-collector.d.ts.map +1 -0
- package/dist/collectors/static-ast-collector.d.ts +32 -0
- package/dist/collectors/static-ast-collector.d.ts.map +1 -0
- package/dist/collectors/trace-collector.d.ts +12 -0
- package/dist/collectors/trace-collector.d.ts.map +1 -0
- package/dist/config/project-config.d.ts +33 -0
- package/dist/config/project-config.d.ts.map +1 -0
- package/dist/core/errors/engine-errors.d.ts +34 -0
- package/dist/core/errors/engine-errors.d.ts.map +1 -0
- package/dist/core/types/diagnostic-context.d.ts +151 -0
- package/dist/core/types/diagnostic-context.d.ts.map +1 -0
- package/dist/core/types/repair-evidence.d.ts +56 -0
- package/dist/core/types/repair-evidence.d.ts.map +1 -0
- package/dist/core/version.d.ts +13 -0
- package/dist/core/version.d.ts.map +1 -0
- package/dist/diagnostics/diagnostic-contract.d.ts +52 -0
- package/dist/diagnostics/diagnostic-contract.d.ts.map +1 -0
- package/dist/diagnostics/diagnostic-report.d.ts +11 -0
- package/dist/diagnostics/diagnostic-report.d.ts.map +1 -0
- package/dist/diagnostics/evidence-correlator.d.ts +22 -0
- package/dist/diagnostics/evidence-correlator.d.ts.map +1 -0
- package/dist/diagnostics/external-failure-evidence.d.ts +18 -0
- package/dist/diagnostics/external-failure-evidence.d.ts.map +1 -0
- package/dist/diagnostics/failure-category.d.ts +4 -0
- package/dist/diagnostics/failure-category.d.ts.map +1 -0
- package/dist/diagnostics/failure-classifier.d.ts +58 -0
- package/dist/diagnostics/failure-classifier.d.ts.map +1 -0
- package/dist/evaluation/evaluation-scorecard.d.ts +72 -0
- package/dist/evaluation/evaluation-scorecard.d.ts.map +1 -0
- package/dist/evaluation/repository-inspector.d.ts +21 -0
- package/dist/evaluation/repository-inspector.d.ts.map +1 -0
- package/dist/evaluation/repository-runner.d.ts +24 -0
- package/dist/evaluation/repository-runner.d.ts.map +1 -0
- package/dist/evidence/evidence-model.d.ts +88 -0
- package/dist/evidence/evidence-model.d.ts.map +1 -0
- package/dist/evidence/evidence-normalizer.d.ts +19 -0
- package/dist/evidence/evidence-normalizer.d.ts.map +1 -0
- package/dist/evidence/evidence-redactor.d.ts +37 -0
- package/dist/evidence/evidence-redactor.d.ts.map +1 -0
- package/dist/framework/config-adapter.d.ts +28 -0
- package/dist/framework/config-adapter.d.ts.map +1 -0
- package/dist/gate/index.d.ts +21 -0
- package/dist/gate/index.d.ts.map +1 -0
- package/dist/gate/oracle.d.ts +26 -0
- package/dist/gate/oracle.d.ts.map +1 -0
- package/dist/gate/quality.d.ts +27 -0
- package/dist/gate/quality.d.ts.map +1 -0
- package/dist/gate/safety.d.ts +28 -0
- package/dist/gate/safety.d.ts.map +1 -0
- package/dist/generator/architecture-generator.d.ts +55 -0
- package/dist/generator/architecture-generator.d.ts.map +1 -0
- package/dist/generator/assertion-quality-gate.d.ts +18 -0
- package/dist/generator/assertion-quality-gate.d.ts.map +1 -0
- package/dist/generator/candidate-writer.d.ts +34 -0
- package/dist/generator/candidate-writer.d.ts.map +1 -0
- package/dist/generator/test-generator.d.ts +26 -0
- package/dist/generator/test-generator.d.ts.map +1 -0
- package/dist/governance/audit-log.d.ts +23 -0
- package/dist/governance/audit-log.d.ts.map +1 -0
- package/dist/governance/governance-policy.d.ts +24 -0
- package/dist/governance/governance-policy.d.ts.map +1 -0
- package/dist/governance/team-dashboard.d.ts +51 -0
- package/dist/governance/team-dashboard.d.ts.map +1 -0
- package/dist/governance/workflow-audit.d.ts +13 -0
- package/dist/governance/workflow-audit.d.ts.map +1 -0
- package/dist/index.d.ts +90 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20318 -0
- package/dist/integrations/ci-summary.d.ts +14 -0
- package/dist/integrations/ci-summary.d.ts.map +1 -0
- package/dist/integrations/playwright-report-adapter.d.ts +22 -0
- package/dist/integrations/playwright-report-adapter.d.ts.map +1 -0
- package/dist/integrations/quality-gate.d.ts +35 -0
- package/dist/integrations/quality-gate.d.ts.map +1 -0
- package/dist/integrations/sarif-report.d.ts +48 -0
- package/dist/integrations/sarif-report.d.ts.map +1 -0
- package/dist/intelligence/autonomous-repair-workflow.d.ts +31 -0
- package/dist/intelligence/autonomous-repair-workflow.d.ts.map +1 -0
- package/dist/intelligence/business-intent.d.ts +58 -0
- package/dist/intelligence/business-intent.d.ts.map +1 -0
- package/dist/intelligence/evidence-bundle.d.ts +364 -0
- package/dist/intelligence/evidence-bundle.d.ts.map +1 -0
- package/dist/intelligence/failure-clustering.d.ts +38 -0
- package/dist/intelligence/failure-clustering.d.ts.map +1 -0
- package/dist/intelligence/generation-agent.d.ts +120 -0
- package/dist/intelligence/generation-agent.d.ts.map +1 -0
- package/dist/intelligence/generation-verifier.d.ts +151 -0
- package/dist/intelligence/generation-verifier.d.ts.map +1 -0
- package/dist/intelligence/llm-proposal.d.ts +377 -0
- package/dist/intelligence/llm-proposal.d.ts.map +1 -0
- package/dist/intelligence/locator-disambiguation-engine.d.ts +38 -0
- package/dist/intelligence/locator-disambiguation-engine.d.ts.map +1 -0
- package/dist/intelligence/model-contract.d.ts +86 -0
- package/dist/intelligence/model-contract.d.ts.map +1 -0
- package/dist/intelligence/model-provider.d.ts +75 -0
- package/dist/intelligence/model-provider.d.ts.map +1 -0
- package/dist/intelligence/project-intelligence.d.ts +22 -0
- package/dist/intelligence/project-intelligence.d.ts.map +1 -0
- package/dist/intelligence/repair-agent.d.ts +46 -0
- package/dist/intelligence/repair-agent.d.ts.map +1 -0
- package/dist/intelligence/repository-profile.d.ts +131 -0
- package/dist/intelligence/repository-profile.d.ts.map +1 -0
- package/dist/intelligence/suite-intelligence.d.ts +59 -0
- package/dist/intelligence/suite-intelligence.d.ts.map +1 -0
- package/dist/intelligence/test-intelligence.d.ts +44 -0
- package/dist/intelligence/test-intelligence.d.ts.map +1 -0
- package/dist/intelligence/trace-proposal-workflow.d.ts +30 -0
- package/dist/intelligence/trace-proposal-workflow.d.ts.map +1 -0
- package/dist/intelligence/verified-llm-repair-workflow.d.ts +21 -0
- package/dist/intelligence/verified-llm-repair-workflow.d.ts.map +1 -0
- package/dist/intelligence/workflow-planner.d.ts +278 -0
- package/dist/intelligence/workflow-planner.d.ts.map +1 -0
- package/dist/mcp/server.d.ts +32 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/memory/stability-ledger.d.ts +46 -0
- package/dist/memory/stability-ledger.d.ts.map +1 -0
- package/dist/perception/app-model.d.ts +55 -0
- package/dist/perception/app-model.d.ts.map +1 -0
- package/dist/perception/crawler.d.ts +18 -0
- package/dist/perception/crawler.d.ts.map +1 -0
- package/dist/perception/index.d.ts +3 -0
- package/dist/perception/index.d.ts.map +1 -0
- package/dist/repair/approval-service.d.ts +139 -0
- package/dist/repair/approval-service.d.ts.map +1 -0
- package/dist/repair/assertion-hasher.d.ts +62 -0
- package/dist/repair/assertion-hasher.d.ts.map +1 -0
- package/dist/repair/ast-patcher.d.ts +36 -0
- package/dist/repair/ast-patcher.d.ts.map +1 -0
- package/dist/repair/browser-operation-executor.d.ts +27 -0
- package/dist/repair/browser-operation-executor.d.ts.map +1 -0
- package/dist/repair/diff-allowlist.d.ts +74 -0
- package/dist/repair/diff-allowlist.d.ts.map +1 -0
- package/dist/repair/intent-validator.d.ts +157 -0
- package/dist/repair/intent-validator.d.ts.map +1 -0
- package/dist/repair/repair-operations.d.ts +40 -0
- package/dist/repair/repair-operations.d.ts.map +1 -0
- package/dist/repair/repair-planner.d.ts +98 -0
- package/dist/repair/repair-planner.d.ts.map +1 -0
- package/dist/repair/repair-workflow.d.ts +42 -0
- package/dist/repair/repair-workflow.d.ts.map +1 -0
- package/dist/repair/safe-operation-compiler.d.ts +15 -0
- package/dist/repair/safe-operation-compiler.d.ts.map +1 -0
- package/dist/repair/source-mapper.d.ts +19 -0
- package/dist/repair/source-mapper.d.ts.map +1 -0
- package/dist/repair/statement-patcher.d.ts +75 -0
- package/dist/repair/statement-patcher.d.ts.map +1 -0
- package/dist/repair/verification-gates.d.ts +25 -0
- package/dist/repair/verification-gates.d.ts.map +1 -0
- package/dist/repair/workflow-plan.d.ts +35 -0
- package/dist/repair/workflow-plan.d.ts.map +1 -0
- package/dist/repair/workspace-promoter.d.ts +43 -0
- package/dist/repair/workspace-promoter.d.ts.map +1 -0
- package/dist/reproduce/diagnostic-rerunner.d.ts +40 -0
- package/dist/reproduce/diagnostic-rerunner.d.ts.map +1 -0
- package/dist/reproduce/direct-browser-investigator.d.ts +41 -0
- package/dist/reproduce/direct-browser-investigator.d.ts.map +1 -0
- package/dist/reproduce/interactive-workflow-runner.d.ts +43 -0
- package/dist/reproduce/interactive-workflow-runner.d.ts.map +1 -0
- package/dist/sandbox/dependency-strategy.d.ts +45 -0
- package/dist/sandbox/dependency-strategy.d.ts.map +1 -0
- package/dist/sandbox/execution-runner.d.ts +81 -0
- package/dist/sandbox/execution-runner.d.ts.map +1 -0
- package/dist/sandbox/worktree-manager.d.ts +51 -0
- package/dist/sandbox/worktree-manager.d.ts.map +1 -0
- package/dist/selector/abstention-policy.d.ts +34 -0
- package/dist/selector/abstention-policy.d.ts.map +1 -0
- package/dist/selector/candidate-extractor.d.ts +71 -0
- package/dist/selector/candidate-extractor.d.ts.map +1 -0
- package/dist/selector/live-locator-verifier.d.ts +28 -0
- package/dist/selector/live-locator-verifier.d.ts.map +1 -0
- package/dist/selector/repair-candidate-ranker.d.ts +10 -0
- package/dist/selector/repair-candidate-ranker.d.ts.map +1 -0
- package/dist/selector/selector-scorer.d.ts +43 -0
- package/dist/selector/selector-scorer.d.ts.map +1 -0
- package/dist/trace/adapters/adapter-registry.d.ts +18 -0
- package/dist/trace/adapters/adapter-registry.d.ts.map +1 -0
- package/dist/trace/adapters/trace-adapter.d.ts +21 -0
- package/dist/trace/adapters/trace-adapter.d.ts.map +1 -0
- package/dist/trace/adapters/unknown-adapter.d.ts +10 -0
- package/dist/trace/adapters/unknown-adapter.d.ts.map +1 -0
- package/dist/trace/adapters/v10-adapter.d.ts +10 -0
- package/dist/trace/adapters/v10-adapter.d.ts.map +1 -0
- package/dist/trace/adapters/v4-adapter.d.ts +11 -0
- package/dist/trace/adapters/v4-adapter.d.ts.map +1 -0
- package/dist/trace/adapters/v8-adapter.d.ts +10 -0
- package/dist/trace/adapters/v8-adapter.d.ts.map +1 -0
- package/dist/trace/adapters/v9-adapter.d.ts +10 -0
- package/dist/trace/adapters/v9-adapter.d.ts.map +1 -0
- package/dist/trace/archive-reader.d.ts +44 -0
- package/dist/trace/archive-reader.d.ts.map +1 -0
- package/dist/trace/snapshot-resolver.d.ts +55 -0
- package/dist/trace/snapshot-resolver.d.ts.map +1 -0
- package/dist/trace/trace-parser.d.ts +50 -0
- package/dist/trace/trace-parser.d.ts.map +1 -0
- package/dist/trace/version-detector.d.ts +20 -0
- package/dist/trace/version-detector.d.ts.map +1 -0
- package/package.json +76 -6
- package/skills/README.md +20 -0
- package/skills/pie-failure-investigation/SKILL.md +16 -0
- package/skills/pie-quality-engineer/SKILL.md +66 -0
- package/skills/pie-release-readiness/SKILL.md +22 -0
- package/skills/pie-repair-review/SKILL.md +21 -0
- package/skills/pie-trace-to-repair/SKILL.md +35 -0
- package/src/authoring/author.ts +81 -0
- package/src/authoring/generation-contract.ts +283 -0
- package/src/authoring/hybrid-author.ts +115 -0
- package/src/authoring/index.ts +7 -0
- package/src/authoring/llm-author.ts +282 -0
- package/src/authoring/naming/index.ts +4 -0
- package/src/authoring/naming/name-plan.ts +28 -0
- package/src/authoring/naming/name-planner.ts +339 -0
- package/src/authoring/naming/naming-linter.ts +292 -0
- package/src/authoring/template-author.ts +39 -0
- package/src/cli/index.ts +1172 -0
- package/src/collectors/collector-interface.ts +8 -0
- package/src/collectors/environment-collector.ts +103 -0
- package/src/collectors/error-collector.ts +177 -0
- package/src/collectors/git-diff-collector.ts +190 -0
- package/src/collectors/live-browser-collector.ts +412 -0
- package/src/collectors/network-collector.ts +90 -0
- package/src/collectors/static-ast-collector.ts +226 -0
- package/src/collectors/trace-collector.ts +66 -0
- package/src/config/project-config.ts +114 -0
- package/src/core/errors/engine-errors.ts +90 -0
- package/src/core/types/diagnostic-context.ts +94 -0
- package/src/core/types/repair-evidence.ts +45 -0
- package/src/core/version.ts +25 -0
- package/src/diagnostics/diagnostic-contract.ts +79 -0
- package/src/diagnostics/diagnostic-report.ts +204 -0
- package/src/diagnostics/evidence-correlator.ts +117 -0
- package/src/diagnostics/external-failure-evidence.ts +72 -0
- package/src/diagnostics/failure-category.ts +40 -0
- package/src/diagnostics/failure-classifier.ts +701 -0
- package/src/evaluation/evaluation-scorecard.ts +198 -0
- package/src/evaluation/repository-inspector.ts +143 -0
- package/src/evaluation/repository-runner.ts +197 -0
- package/src/evidence/evidence-model.ts +76 -0
- package/src/evidence/evidence-normalizer.ts +322 -0
- package/src/evidence/evidence-redactor.ts +218 -0
- package/src/framework/config-adapter.ts +131 -0
- package/src/gate/index.ts +43 -0
- package/src/gate/oracle.ts +69 -0
- package/src/gate/quality.ts +101 -0
- package/src/gate/safety.ts +94 -0
- package/src/generator/architecture-generator.ts +582 -0
- package/src/generator/assertion-quality-gate.ts +88 -0
- package/src/generator/candidate-writer.ts +288 -0
- package/src/generator/test-generator.ts +52 -0
- package/src/governance/audit-log.ts +115 -0
- package/src/governance/governance-policy.ts +72 -0
- package/src/governance/team-dashboard.ts +189 -0
- package/src/governance/workflow-audit.ts +72 -0
- package/src/index.ts +107 -0
- package/src/integrations/ci-summary.ts +37 -0
- package/src/integrations/playwright-report-adapter.ts +173 -0
- package/src/integrations/quality-gate.ts +95 -0
- package/src/integrations/sarif-report.ts +110 -0
- package/src/intelligence/autonomous-repair-workflow.ts +139 -0
- package/src/intelligence/business-intent.ts +163 -0
- package/src/intelligence/evidence-bundle.ts +300 -0
- package/src/intelligence/failure-clustering.ts +134 -0
- package/src/intelligence/generation-agent.ts +561 -0
- package/src/intelligence/generation-verifier.ts +1115 -0
- package/src/intelligence/llm-proposal.ts +519 -0
- package/src/intelligence/locator-disambiguation-engine.ts +331 -0
- package/src/intelligence/model-contract.ts +205 -0
- package/src/intelligence/model-provider.ts +348 -0
- package/src/intelligence/project-intelligence.ts +140 -0
- package/src/intelligence/repair-agent.ts +297 -0
- package/src/intelligence/repository-profile.ts +796 -0
- package/src/intelligence/suite-intelligence.ts +305 -0
- package/src/intelligence/test-intelligence.ts +136 -0
- package/src/intelligence/trace-proposal-workflow.ts +318 -0
- package/src/intelligence/verified-llm-repair-workflow.ts +48 -0
- package/src/intelligence/workflow-planner.ts +966 -0
- package/src/mcp/server.ts +970 -0
- package/src/memory/stability-ledger.ts +243 -0
- package/src/perception/app-model.ts +32 -0
- package/src/perception/crawler.ts +263 -0
- package/src/perception/index.ts +3 -0
- package/src/repair/approval-service.ts +541 -0
- package/src/repair/assertion-hasher.ts +386 -0
- package/src/repair/ast-patcher.ts +223 -0
- package/src/repair/browser-operation-executor.ts +263 -0
- package/src/repair/diff-allowlist.ts +612 -0
- package/src/repair/intent-validator.ts +761 -0
- package/src/repair/repair-operations.ts +65 -0
- package/src/repair/repair-planner.ts +467 -0
- package/src/repair/repair-workflow.ts +241 -0
- package/src/repair/safe-operation-compiler.ts +68 -0
- package/src/repair/source-mapper.ts +156 -0
- package/src/repair/statement-patcher.ts +544 -0
- package/src/repair/verification-gates.ts +46 -0
- package/src/repair/workflow-plan.ts +59 -0
- package/src/repair/workspace-promoter.ts +313 -0
- package/src/reproduce/diagnostic-rerunner.ts +287 -0
- package/src/reproduce/direct-browser-investigator.ts +208 -0
- package/src/reproduce/interactive-workflow-runner.ts +828 -0
- package/src/sandbox/dependency-strategy.ts +215 -0
- package/src/sandbox/execution-runner.ts +408 -0
- package/src/sandbox/worktree-manager.ts +287 -0
- package/src/selector/abstention-policy.ts +175 -0
- package/src/selector/candidate-extractor.ts +343 -0
- package/src/selector/live-locator-verifier.ts +139 -0
- package/src/selector/repair-candidate-ranker.ts +92 -0
- package/src/selector/selector-scorer.ts +344 -0
- package/src/trace/adapters/adapter-registry.ts +49 -0
- package/src/trace/adapters/trace-adapter.ts +28 -0
- package/src/trace/adapters/unknown-adapter.ts +50 -0
- package/src/trace/adapters/v10-adapter.ts +39 -0
- package/src/trace/adapters/v4-adapter.ts +31 -0
- package/src/trace/adapters/v8-adapter.ts +42 -0
- package/src/trace/adapters/v9-adapter.ts +39 -0
- package/src/trace/archive-reader.ts +246 -0
- package/src/trace/snapshot-resolver.ts +308 -0
- package/src/trace/trace-parser.ts +467 -0
- package/src/trace/version-detector.ts +81 -0
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DiagnosticContext,
|
|
3
|
+
FailedAction,
|
|
4
|
+
NetworkEvent,
|
|
5
|
+
ConsoleEvent,
|
|
6
|
+
} from '../core/types/diagnostic-context.js';
|
|
7
|
+
import { VersionDetector } from './version-detector.js';
|
|
8
|
+
import { SnapshotResolver, ResolvedElement } from './snapshot-resolver.js';
|
|
9
|
+
|
|
10
|
+
export interface RawTraceEvent {
|
|
11
|
+
type: string;
|
|
12
|
+
callId?: string;
|
|
13
|
+
apiName?: string;
|
|
14
|
+
method?: string;
|
|
15
|
+
title?: string;
|
|
16
|
+
params?: Record<string, any>;
|
|
17
|
+
error?: any;
|
|
18
|
+
stack?: Array<{ file: string; line: number; column?: number }>;
|
|
19
|
+
wallTime?: number;
|
|
20
|
+
startTime?: number;
|
|
21
|
+
endTime?: number;
|
|
22
|
+
log?: string[];
|
|
23
|
+
message?: string;
|
|
24
|
+
snapshot?: any;
|
|
25
|
+
[key: string]: any;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface ParsedTraceStream {
|
|
29
|
+
actions: Map<string, FailedAction>;
|
|
30
|
+
failedAction?: FailedAction | undefined;
|
|
31
|
+
consoleEvents: ConsoleEvent[];
|
|
32
|
+
rawSnapshots?: any[];
|
|
33
|
+
latestResolvedDom?: ResolvedElement | null;
|
|
34
|
+
mainFrameDom?: ResolvedElement | null;
|
|
35
|
+
latestChildFrameDom?: ResolvedElement | null;
|
|
36
|
+
domByCallId?: Map<string, ResolvedElement>;
|
|
37
|
+
domByFrameId?: Map<string, ResolvedElement>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function stripAnsi(value: string): string {
|
|
41
|
+
return value.replace(/\u001b\[[0-?]*[ -/]*[@-~]/g, '');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function inferActionDetailsFromError(errorMessage: string | undefined): { action?: string; selector?: string } {
|
|
45
|
+
if (!errorMessage) return {};
|
|
46
|
+
const text = stripAnsi(errorMessage);
|
|
47
|
+
const waitingMatch = text.match(/waiting for\s+([^\r\n]+)/i);
|
|
48
|
+
const waitingTarget = waitingMatch?.[1]?.trim();
|
|
49
|
+
const selector = waitingTarget && /^(?:locator|getBy|frameLocator)\(/i.test(waitingTarget)
|
|
50
|
+
? waitingTarget
|
|
51
|
+
: undefined;
|
|
52
|
+
|
|
53
|
+
// The common Playwright form is "locator.click: ...". Keep the method
|
|
54
|
+
// separate from the human-readable parent test.step title so the classifier
|
|
55
|
+
// evaluates actionability evidence in the correct order.
|
|
56
|
+
const locatorAction = text.match(/\blocator\.([a-zA-Z]+):/i)?.[1];
|
|
57
|
+
const result: { action?: string; selector?: string } = {};
|
|
58
|
+
if (locatorAction) result.action = locatorAction.toLowerCase();
|
|
59
|
+
if (!result.action && /expect\s+failed|expect\s*\(|assert(?:ion)?\s+failed/i.test(text)) {
|
|
60
|
+
result.action = 'expect';
|
|
61
|
+
}
|
|
62
|
+
if (selector) result.selector = selector;
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export class TraceParser {
|
|
67
|
+
private static selectFailedAction(candidates: FailedAction[]): FailedAction | undefined {
|
|
68
|
+
if (candidates.length === 0) return undefined;
|
|
69
|
+
const score = (candidate: FailedAction): number => {
|
|
70
|
+
const action = candidate.action.toLowerCase();
|
|
71
|
+
const message = candidate.errorMessage ?? '';
|
|
72
|
+
let value = 0;
|
|
73
|
+
if (candidate.selector) value += 4;
|
|
74
|
+
if (message.length > 40) value += 1;
|
|
75
|
+
if (/(click|fill|press|check|select|goto|navigate|expect|locator)/i.test(action)) value += 2;
|
|
76
|
+
if (/(fixture|hook|worker cleanup|beforeeach|aftereach)/i.test(action)) value -= 2;
|
|
77
|
+
return value;
|
|
78
|
+
};
|
|
79
|
+
return [...candidates].sort((left, right) => {
|
|
80
|
+
return score(right) - score(left) || (right.timestamp ?? 0) - (left.timestamp ?? 0) || left.callId.localeCompare(right.callId);
|
|
81
|
+
})[0];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Parses the raw lines of a .trace JSONL stream into structured actions, events, and DOM snapshots.
|
|
86
|
+
*/
|
|
87
|
+
public static parseTraceLines(lines: string[]): ParsedTraceStream {
|
|
88
|
+
const actionsByCallId = new Map<string, Partial<FailedAction> & { beforeEvent?: RawTraceEvent }>();
|
|
89
|
+
const consoleEvents: ConsoleEvent[] = [];
|
|
90
|
+
const logsByCallId = new Map<string, string[]>();
|
|
91
|
+
const rawSnapshots: any[] = [];
|
|
92
|
+
const domByCallId = new Map<string, ResolvedElement>();
|
|
93
|
+
const domByFrameId = new Map<string, ResolvedElement>();
|
|
94
|
+
let mainFrameId: string | null = null;
|
|
95
|
+
let mainFrameDom: ResolvedElement | null = null;
|
|
96
|
+
let latestChildFrameDom: ResolvedElement | null = null;
|
|
97
|
+
let latestResolvedDom: ResolvedElement | null = null;
|
|
98
|
+
const failedActionCandidates: FailedAction[] = [];
|
|
99
|
+
|
|
100
|
+
for (const rawLine of lines) {
|
|
101
|
+
const line = rawLine.trim();
|
|
102
|
+
if (!line) continue;
|
|
103
|
+
|
|
104
|
+
let event: RawTraceEvent;
|
|
105
|
+
try {
|
|
106
|
+
event = JSON.parse(line);
|
|
107
|
+
} catch {
|
|
108
|
+
continue; // Skip malformed JSONL records
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Handle 'log' event
|
|
112
|
+
if (event.type === 'log' && event.callId && typeof event.message === 'string') {
|
|
113
|
+
let logs = logsByCallId.get(event.callId);
|
|
114
|
+
if (!logs) {
|
|
115
|
+
logs = [];
|
|
116
|
+
logsByCallId.set(event.callId, logs);
|
|
117
|
+
}
|
|
118
|
+
logs.push(event.message);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Handle 'frame-snapshot' event
|
|
122
|
+
if (event.type === 'frame-snapshot' && event.snapshot) {
|
|
123
|
+
rawSnapshots.push(event.snapshot);
|
|
124
|
+
const snapIndex = rawSnapshots.length - 1;
|
|
125
|
+
const snapContent = event.snapshot.html ?? event.snapshot.node;
|
|
126
|
+
const resolved = SnapshotResolver.resolveDifferentialNode(snapContent, snapIndex, rawSnapshots);
|
|
127
|
+
if (resolved && typeof resolved === 'object' && 'tag' in resolved) {
|
|
128
|
+
const resolvedEl = resolved as ResolvedElement;
|
|
129
|
+
const frameId = event.snapshot.frameId ?? event.frameId;
|
|
130
|
+
const isExplicitMainFrame = event.snapshot.isMainFrame === true || event.isMainFrame === true;
|
|
131
|
+
const isExplicitChildFrame = event.snapshot.isMainFrame === false || event.isMainFrame === false;
|
|
132
|
+
|
|
133
|
+
if (frameId) {
|
|
134
|
+
domByFrameId.set(frameId, resolvedEl);
|
|
135
|
+
if (isExplicitMainFrame || (!mainFrameId && !isExplicitChildFrame)) {
|
|
136
|
+
mainFrameId = frameId;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (event.snapshot.callId) {
|
|
141
|
+
domByCallId.set(event.snapshot.callId, resolvedEl);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const isMain = isExplicitMainFrame || (frameId && frameId === mainFrameId) || (!frameId && !isExplicitChildFrame);
|
|
145
|
+
|
|
146
|
+
if (isMain) {
|
|
147
|
+
mainFrameDom = resolvedEl;
|
|
148
|
+
latestResolvedDom = resolvedEl;
|
|
149
|
+
} else {
|
|
150
|
+
latestChildFrameDom = resolvedEl;
|
|
151
|
+
// Child iframe snapshot: preserve mainFrameDom, update latestResolvedDom only if mainFrameDom not set
|
|
152
|
+
if (!mainFrameDom) {
|
|
153
|
+
latestResolvedDom = resolvedEl;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Handle 'before' event (action initiation in Playwright trace)
|
|
160
|
+
if (event.type === 'before' && event.callId) {
|
|
161
|
+
const callId = event.callId;
|
|
162
|
+
let selector =
|
|
163
|
+
event.params?.['selector'] ??
|
|
164
|
+
event.params?.['locator'] ??
|
|
165
|
+
event.subtitle ??
|
|
166
|
+
(typeof event.apiName === 'string' && event.apiName.includes('locator(')
|
|
167
|
+
? event.apiName
|
|
168
|
+
: undefined);
|
|
169
|
+
|
|
170
|
+
if (!selector && event.params?.['expression']) {
|
|
171
|
+
selector = event.params['selector'] ?? event.params['expression'];
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const sourceFrame = event.stack?.[0];
|
|
175
|
+
const actionName = event.apiName ?? event.title ?? event.method ?? 'unknown';
|
|
176
|
+
|
|
177
|
+
actionsByCallId.set(callId, {
|
|
178
|
+
callId,
|
|
179
|
+
action: actionName,
|
|
180
|
+
selector,
|
|
181
|
+
sourceFile: sourceFrame?.file,
|
|
182
|
+
line: sourceFrame?.line,
|
|
183
|
+
column: sourceFrame?.column,
|
|
184
|
+
durationMs: 0,
|
|
185
|
+
timestamp: event.wallTime ?? event.startTime,
|
|
186
|
+
beforeEvent: event,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Handle 'after' event (action termination, contains error if failed)
|
|
191
|
+
if (event.type === 'after' && event.callId) {
|
|
192
|
+
const existing = actionsByCallId.get(event.callId);
|
|
193
|
+
const hasError = Boolean(event.error);
|
|
194
|
+
|
|
195
|
+
let errorMessage: string | undefined;
|
|
196
|
+
let errorStack: string | undefined;
|
|
197
|
+
|
|
198
|
+
if (event.error) {
|
|
199
|
+
if (typeof event.error === 'string') {
|
|
200
|
+
errorMessage = event.error;
|
|
201
|
+
} else if (event.error.error?.message) {
|
|
202
|
+
errorMessage = event.error.error.message;
|
|
203
|
+
errorStack = event.error.error.stack;
|
|
204
|
+
} else if (event.error.message) {
|
|
205
|
+
errorMessage = event.error.message;
|
|
206
|
+
errorStack = event.error.stack;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const childActions = [...actionsByCallId.values()]
|
|
211
|
+
.filter((item) => item.beforeEvent?.parentId === event.callId)
|
|
212
|
+
.sort((left, right) => (right.beforeEvent?.startTime ?? 0) - (left.beforeEvent?.startTime ?? 0));
|
|
213
|
+
const childAction = childActions.find((item) => /click|fill|press|check|select/i.test(item.action ?? '')) ?? childActions[childActions.length - 1];
|
|
214
|
+
const childLogs = childAction?.callId ? logsByCallId.get(childAction.callId) ?? [] : [];
|
|
215
|
+
const logs = [...(logsByCallId.get(event.callId) ?? []), ...childLogs];
|
|
216
|
+
const inferred = inferActionDetailsFromError(errorMessage);
|
|
217
|
+
|
|
218
|
+
// Enrich errorMessage if vague like "Expect failed"
|
|
219
|
+
if ((!errorMessage || errorMessage.toLowerCase().includes('expect failed')) && logs.length > 0) {
|
|
220
|
+
const timeoutOrWaiting = logs.find(
|
|
221
|
+
(l) => l.includes('waiting for locator') || l.includes('resolved to') || l.includes('timeout')
|
|
222
|
+
);
|
|
223
|
+
if (timeoutOrWaiting) {
|
|
224
|
+
errorMessage = errorMessage ? `${errorMessage}: ${timeoutOrWaiting}` : timeoutOrWaiting;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// If selector was not in params, extract from logs
|
|
229
|
+
let finalSelector = existing?.selector;
|
|
230
|
+
if (!finalSelector) {
|
|
231
|
+
for (const l of logs) {
|
|
232
|
+
const m = l.match(/locator\('([^']+)'\)/i);
|
|
233
|
+
if (m) {
|
|
234
|
+
finalSelector = m[1];
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const durationMs =
|
|
241
|
+
existing?.beforeEvent?.wallTime && event.endTime
|
|
242
|
+
? event.endTime - existing.beforeEvent.wallTime
|
|
243
|
+
: undefined;
|
|
244
|
+
|
|
245
|
+
const completedAction: FailedAction = {
|
|
246
|
+
callId: event.callId,
|
|
247
|
+
action: inferred.action ?? childAction?.action ?? existing?.action ?? event.apiName ?? 'unknown',
|
|
248
|
+
selector: finalSelector ?? inferred.selector ?? childAction?.selector,
|
|
249
|
+
sourceFile: existing?.sourceFile,
|
|
250
|
+
line: existing?.line,
|
|
251
|
+
column: existing?.column,
|
|
252
|
+
errorMessage,
|
|
253
|
+
errorStack,
|
|
254
|
+
durationMs,
|
|
255
|
+
timestamp: existing?.timestamp ?? event.endTime,
|
|
256
|
+
logs,
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
actionsByCallId.set(event.callId, completedAction);
|
|
260
|
+
|
|
261
|
+
if (hasError) failedActionCandidates.push(completedAction);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Handle consolidated 'action' event style
|
|
265
|
+
if (event.type === 'action' && event.callId) {
|
|
266
|
+
const hasError = Boolean(event.error);
|
|
267
|
+
const action: FailedAction = {
|
|
268
|
+
callId: event.callId,
|
|
269
|
+
action: event.action ?? event.apiName ?? 'unknown',
|
|
270
|
+
selector: event.params?.['selector'] ?? event.selector,
|
|
271
|
+
sourceFile: event.stack?.[0]?.file ?? event.sourceFile,
|
|
272
|
+
line: event.stack?.[0]?.line ?? event.line,
|
|
273
|
+
column: event.stack?.[0]?.column,
|
|
274
|
+
errorMessage: typeof event.error === 'string' ? event.error : event.error?.message,
|
|
275
|
+
errorStack: event.error?.stack,
|
|
276
|
+
timestamp: event.wallTime ?? event.startTime,
|
|
277
|
+
};
|
|
278
|
+
actionsByCallId.set(event.callId, action);
|
|
279
|
+
if (hasError) failedActionCandidates.push(action);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Some trace producers emit a standalone error record rather than
|
|
283
|
+
// attaching the error to an `after` or consolidated `action` event.
|
|
284
|
+
// Preserve it as a candidate so diagnosis does not silently fall back
|
|
285
|
+
// to an unrelated fixture action or an empty unknown action.
|
|
286
|
+
if (event.type === 'error') {
|
|
287
|
+
const callId = event.callId ?? `error@${failedActionCandidates.length}`;
|
|
288
|
+
const existing = actionsByCallId.get(callId);
|
|
289
|
+
const rawError = typeof event.error === 'string' ? event.error : event.error?.message ?? event.message;
|
|
290
|
+
const standalone: FailedAction = {
|
|
291
|
+
callId,
|
|
292
|
+
action: existing?.action ?? event.apiName ?? event.title ?? 'unknown',
|
|
293
|
+
selector: existing?.selector,
|
|
294
|
+
sourceFile: existing?.sourceFile ?? event.stack?.[0]?.file,
|
|
295
|
+
line: existing?.line ?? event.stack?.[0]?.line,
|
|
296
|
+
column: existing?.column ?? event.stack?.[0]?.column,
|
|
297
|
+
errorMessage: rawError,
|
|
298
|
+
errorStack: typeof event.error === 'object' ? event.error?.stack : undefined,
|
|
299
|
+
timestamp: existing?.timestamp ?? event.wallTime ?? event.startTime,
|
|
300
|
+
logs: logsByCallId.get(callId) ?? [],
|
|
301
|
+
};
|
|
302
|
+
if (standalone.errorMessage) {
|
|
303
|
+
actionsByCallId.set(callId, standalone);
|
|
304
|
+
failedActionCandidates.push(standalone);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Handle console and pageError events
|
|
309
|
+
if (event.type === 'event' && (event.method === 'console' || event.method === 'pageError')) {
|
|
310
|
+
const consoleParams = event.params ?? {};
|
|
311
|
+
consoleEvents.push({
|
|
312
|
+
type: event.method === 'pageError' ? 'error' : (consoleParams['type'] ?? 'log'),
|
|
313
|
+
text: consoleParams['text'] ?? JSON.stringify(consoleParams),
|
|
314
|
+
timestamp: event.wallTime ?? Date.now(),
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const validActions = new Map<string, FailedAction>();
|
|
320
|
+
for (const [id, item] of actionsByCallId.entries()) {
|
|
321
|
+
validActions.set(id, {
|
|
322
|
+
callId: id,
|
|
323
|
+
action: item.action ?? 'unknown',
|
|
324
|
+
selector: item.selector,
|
|
325
|
+
sourceFile: item.sourceFile,
|
|
326
|
+
line: item.line,
|
|
327
|
+
column: item.column,
|
|
328
|
+
errorMessage: item.errorMessage,
|
|
329
|
+
errorStack: item.errorStack,
|
|
330
|
+
durationMs: item.durationMs,
|
|
331
|
+
timestamp: item.timestamp,
|
|
332
|
+
logs: (item as any).logs,
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return {
|
|
337
|
+
actions: validActions,
|
|
338
|
+
failedAction: TraceParser.selectFailedAction(failedActionCandidates),
|
|
339
|
+
consoleEvents,
|
|
340
|
+
rawSnapshots,
|
|
341
|
+
latestResolvedDom,
|
|
342
|
+
mainFrameDom,
|
|
343
|
+
latestChildFrameDom,
|
|
344
|
+
domByCallId,
|
|
345
|
+
domByFrameId,
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Parses raw lines of a .network JSONL stream into structured NetworkEvents.
|
|
351
|
+
*/
|
|
352
|
+
public static parseNetworkLines(lines: string[]): NetworkEvent[] {
|
|
353
|
+
const networkEvents: NetworkEvent[] = [];
|
|
354
|
+
|
|
355
|
+
for (const rawLine of lines) {
|
|
356
|
+
const line = rawLine.trim();
|
|
357
|
+
if (!line) continue;
|
|
358
|
+
|
|
359
|
+
try {
|
|
360
|
+
const event = JSON.parse(line);
|
|
361
|
+
// Playwright network events can be request, response, or resource-snapshot
|
|
362
|
+
if (event.type === 'resource-snapshot') {
|
|
363
|
+
const req = event.snapshot?.request;
|
|
364
|
+
const res = event.snapshot?.response;
|
|
365
|
+
if (req && res) {
|
|
366
|
+
const rawTime =
|
|
367
|
+
event.snapshot?._monotonicTime ??
|
|
368
|
+
event.snapshot?.monotonicTime ??
|
|
369
|
+
event.snapshot?.wallTime ??
|
|
370
|
+
(event.snapshot?.startedDateTime ? new Date(event.snapshot.startedDateTime).getTime() : Date.now());
|
|
371
|
+
|
|
372
|
+
networkEvents.push({
|
|
373
|
+
url: req.url ?? 'unknown',
|
|
374
|
+
method: req.method ?? 'GET',
|
|
375
|
+
status: res.status ?? 0,
|
|
376
|
+
statusText: res.statusText,
|
|
377
|
+
timestamp: rawTime,
|
|
378
|
+
durationMs: event.snapshot?.time,
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
} else if (event.type === 'response' || event.response) {
|
|
382
|
+
const res = event.response ?? event;
|
|
383
|
+
networkEvents.push({
|
|
384
|
+
url: res.url ?? event.url ?? 'unknown',
|
|
385
|
+
method: event.method ?? 'GET',
|
|
386
|
+
status: res.status ?? 0,
|
|
387
|
+
statusText: res.statusText,
|
|
388
|
+
timestamp: event.wallTime ?? Date.now(),
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
} catch {
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
return networkEvents;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Assembles a normalized DiagnosticContext from raw trace lines and network lines.
|
|
401
|
+
*/
|
|
402
|
+
public static assembleDiagnosticContext(
|
|
403
|
+
traceLines: string[],
|
|
404
|
+
networkLines: string[]
|
|
405
|
+
): DiagnosticContext {
|
|
406
|
+
const versionInfo = VersionDetector.detectFromLines(traceLines);
|
|
407
|
+
VersionDetector.assertSupported(versionInfo);
|
|
408
|
+
|
|
409
|
+
const { failedAction, consoleEvents, domByCallId, latestResolvedDom, mainFrameDom, latestChildFrameDom } = TraceParser.parseTraceLines(traceLines);
|
|
410
|
+
const networkEvents = TraceParser.parseNetworkLines(networkLines);
|
|
411
|
+
|
|
412
|
+
const fallbackFailedAction: FailedAction = failedAction ?? {
|
|
413
|
+
callId: 'unknown',
|
|
414
|
+
action: 'unknown',
|
|
415
|
+
errorMessage: 'No explicit action failure recorded in trace',
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
const snapshots: { before?: string; action?: string; after?: string } = {};
|
|
419
|
+
|
|
420
|
+
// Recover DOM snapshot from modern differential stream or latest known frame DOM.
|
|
421
|
+
// Prioritize call-specific DOM, then root/main frame DOM (unless selector specifically targeted an iframe), then child frame DOM, then fallback.
|
|
422
|
+
const isTargetingIframe = Boolean(
|
|
423
|
+
fallbackFailedAction.selector &&
|
|
424
|
+
/frameLocator|iframe|frame\[/i.test(fallbackFailedAction.selector)
|
|
425
|
+
);
|
|
426
|
+
|
|
427
|
+
const targetDom: ResolvedElement | undefined =
|
|
428
|
+
(fallbackFailedAction.callId && domByCallId?.get(fallbackFailedAction.callId)) ||
|
|
429
|
+
(isTargetingIframe
|
|
430
|
+
? (latestChildFrameDom || latestResolvedDom)
|
|
431
|
+
: (mainFrameDom || latestResolvedDom)) ||
|
|
432
|
+
undefined;
|
|
433
|
+
|
|
434
|
+
if (targetDom) {
|
|
435
|
+
const htmlStr = SnapshotResolver.toHtml(targetDom);
|
|
436
|
+
snapshots.before = htmlStr;
|
|
437
|
+
snapshots.action = htmlStr;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const hasSnapshots = Boolean(
|
|
441
|
+
(snapshots.action && snapshots.action.trim().length > 0) ||
|
|
442
|
+
(snapshots.before && snapshots.before.trim().length > 0) ||
|
|
443
|
+
(snapshots.after && snapshots.after.trim().length > 0)
|
|
444
|
+
);
|
|
445
|
+
|
|
446
|
+
const context: DiagnosticContext = {
|
|
447
|
+
playwrightVersion: versionInfo.playwrightVersion ?? 'unknown',
|
|
448
|
+
traceFormatVersion: versionInfo.traceFormatVersion,
|
|
449
|
+
failedAction: fallbackFailedAction,
|
|
450
|
+
snapshots,
|
|
451
|
+
networkEvents,
|
|
452
|
+
consoleEvents,
|
|
453
|
+
evidenceCompleteness: {
|
|
454
|
+
domAvailable: hasSnapshots,
|
|
455
|
+
networkAvailable: networkEvents.length > 0,
|
|
456
|
+
sourceAvailable: Boolean(fallbackFailedAction.sourceFile),
|
|
457
|
+
},
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
if (targetDom) {
|
|
461
|
+
(context as any).domRoot = targetDom;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
return context;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { UnsupportedTraceVersionError } from '../core/errors/engine-errors.js';
|
|
2
|
+
|
|
3
|
+
export interface TraceVersionInfo {
|
|
4
|
+
traceFormatVersion: number;
|
|
5
|
+
playwrightVersion?: string;
|
|
6
|
+
isSupported: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class VersionDetector {
|
|
10
|
+
// Known supported Playwright trace format versions
|
|
11
|
+
// Playwright 1.32-era archives use v4; v1.38-v1.40 uses v5/6;
|
|
12
|
+
// v1.41-v1.50 uses v7/8/9; v1.60+ uses v10.
|
|
13
|
+
public static readonly SUPPORTED_FORMAT_VERSIONS = [4, 5, 6, 7, 8, 9, 10];
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Detects the trace format version from raw JSONL event lines or an archive entry.
|
|
17
|
+
* Scans the first N events looking for a 'version' event or metadata object.
|
|
18
|
+
* If no explicit version is found, returns version 0 (unknown/unsupported).
|
|
19
|
+
*/
|
|
20
|
+
public static detectFromLines(lines: string[]): TraceVersionInfo {
|
|
21
|
+
let traceFormatVersion = 0; // Unknown by default
|
|
22
|
+
let playwrightVersion: string | undefined;
|
|
23
|
+
let foundExplicitVersion = false;
|
|
24
|
+
|
|
25
|
+
for (let i = 0; i < Math.min(lines.length, 50); i++) {
|
|
26
|
+
const line = lines[i]?.trim();
|
|
27
|
+
if (!line) continue;
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const event = JSON.parse(line);
|
|
31
|
+
|
|
32
|
+
// Check for { "type": "version", "version": 6 }
|
|
33
|
+
if (event.type === 'version' && typeof event.version === 'number') {
|
|
34
|
+
traceFormatVersion = event.version;
|
|
35
|
+
foundExplicitVersion = true;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Check for version embedded in context or metadata events
|
|
39
|
+
if (event.type === 'context-options' || event.type === 'metadata') {
|
|
40
|
+
if (typeof event.playwrightVersion === 'string') {
|
|
41
|
+
playwrightVersion = event.playwrightVersion;
|
|
42
|
+
}
|
|
43
|
+
if (typeof event.version === 'number') {
|
|
44
|
+
traceFormatVersion = event.version;
|
|
45
|
+
foundExplicitVersion = true;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Break early if we found both
|
|
50
|
+
if (foundExplicitVersion && playwrightVersion) {
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
} catch {
|
|
54
|
+
// Skip malformed lines
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const isSupported = foundExplicitVersion && VersionDetector.SUPPORTED_FORMAT_VERSIONS.includes(traceFormatVersion);
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
traceFormatVersion,
|
|
63
|
+
playwrightVersion: playwrightVersion ?? 'unknown',
|
|
64
|
+
isSupported,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Asserts that a detected trace version is supported by the engine.
|
|
70
|
+
* Throws UnsupportedTraceVersionError if not.
|
|
71
|
+
*/
|
|
72
|
+
public static assertSupported(versionInfo: TraceVersionInfo): void {
|
|
73
|
+
if (!versionInfo.isSupported) {
|
|
74
|
+
throw new UnsupportedTraceVersionError(
|
|
75
|
+
versionInfo.traceFormatVersion,
|
|
76
|
+
`Trace format version ${versionInfo.traceFormatVersion} is not supported. Supported versions: ${VersionDetector.SUPPORTED_FORMAT_VERSIONS.join(', ')}`
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|