@midscene/core 1.12.10-beta-20260920031616.0 → 1.13.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/dist/es/agent/agent.mjs +103 -6
- package/dist/es/agent/agent.mjs.map +1 -1
- package/dist/es/agent/index.mjs +4 -3
- package/dist/es/agent/tasks.mjs +2 -2
- package/dist/es/agent/tasks.mjs.map +1 -1
- package/dist/es/agent/test-runner-nodes.mjs +291 -40
- package/dist/es/agent/test-runner-nodes.mjs.map +1 -1
- package/dist/es/agent/utils.mjs +1 -1
- package/dist/es/device/index.mjs +15 -2
- package/dist/es/device/index.mjs.map +1 -1
- package/dist/es/dump/html-utils.mjs +37 -4
- package/dist/es/dump/html-utils.mjs.map +1 -1
- package/dist/es/dump/screenshot-store.mjs +8 -1
- package/dist/es/dump/screenshot-store.mjs.map +1 -1
- package/dist/es/report-cli.mjs +9 -4
- package/dist/es/report-cli.mjs.map +1 -1
- package/dist/es/report-generator.mjs +117 -4
- package/dist/es/report-generator.mjs.map +1 -1
- package/dist/es/report-html-template.mjs +1 -1
- package/dist/es/report.mjs +190 -41
- package/dist/es/report.mjs.map +1 -1
- package/dist/es/test-run-report.mjs.map +1 -1
- package/dist/es/test-runner/engine/case-runner.mjs +52 -0
- package/dist/es/test-runner/engine/case-runner.mjs.map +1 -0
- package/dist/es/test-runner/engine/document-runtime.mjs +273 -0
- package/dist/es/test-runner/engine/document-runtime.mjs.map +1 -0
- package/dist/es/test-runner/engine/execute-step.mjs +177 -0
- package/dist/es/test-runner/engine/execute-step.mjs.map +1 -0
- package/dist/es/test-runner/engine/execution-failure.mjs +39 -0
- package/dist/es/test-runner/engine/execution-failure.mjs.map +1 -0
- package/dist/es/test-runner/engine/index.mjs +12 -0
- package/dist/es/test-runner/engine/project-runtime.mjs +142 -0
- package/dist/es/test-runner/engine/project-runtime.mjs.map +1 -0
- package/dist/es/test-runner/engine/registry.mjs +61 -0
- package/dist/es/test-runner/engine/registry.mjs.map +1 -0
- package/dist/es/test-runner/engine/resource-operations.mjs +211 -0
- package/dist/es/test-runner/engine/resource-operations.mjs.map +1 -0
- package/dist/es/test-runner/engine/run-collected-case.mjs +193 -0
- package/dist/es/test-runner/engine/run-collected-case.mjs.map +1 -0
- package/dist/es/test-runner/engine/run-workflow-document.mjs +155 -0
- package/dist/es/test-runner/engine/run-workflow-document.mjs.map +1 -0
- package/dist/es/test-runner/engine/scheduler.mjs +27 -0
- package/dist/es/test-runner/engine/scheduler.mjs.map +1 -0
- package/dist/es/test-runner/engine/scope-teardown.mjs +16 -0
- package/dist/es/test-runner/engine/scope-teardown.mjs.map +1 -0
- package/dist/es/test-runner/engine/types.mjs +0 -0
- package/dist/es/test-runner/errors.mjs +201 -0
- package/dist/es/test-runner/errors.mjs.map +1 -0
- package/dist/es/test-runner/execution-record.mjs +83 -0
- package/dist/es/test-runner/execution-record.mjs.map +1 -0
- package/dist/es/test-runner/index.mjs +12 -0
- package/dist/es/test-runner/node/define-node.mjs +44 -0
- package/dist/es/test-runner/node/define-node.mjs.map +1 -0
- package/dist/es/test-runner/node/index.mjs +2 -0
- package/dist/es/test-runner/node/types.mjs +0 -0
- package/dist/es/test-runner/parser/document-format.mjs +21 -0
- package/dist/es/test-runner/parser/document-format.mjs.map +1 -0
- package/dist/es/test-runner/parser/normalize.mjs +87 -0
- package/dist/es/test-runner/parser/normalize.mjs.map +1 -0
- package/dist/es/test-runner/parser/types.mjs +0 -0
- package/dist/es/test-runner/project.mjs +0 -0
- package/dist/es/test-runner/reporting/agent-report.mjs +23 -0
- package/dist/es/test-runner/reporting/agent-report.mjs.map +1 -0
- package/dist/es/test-runner/reporting/execution-record.mjs +73 -0
- package/dist/es/test-runner/reporting/execution-record.mjs.map +1 -0
- package/dist/es/test-runner/reporting/merge-report.mjs +231 -0
- package/dist/es/test-runner/reporting/merge-report.mjs.map +1 -0
- package/dist/es/test-runner/reporting/sanitize.mjs +162 -0
- package/dist/es/test-runner/reporting/sanitize.mjs.map +1 -0
- package/dist/es/test-runner/reporting/test-run-report.mjs +327 -0
- package/dist/es/test-runner/reporting/test-run-report.mjs.map +1 -0
- package/dist/es/test-runner/reporting/types.mjs +0 -0
- package/dist/es/utils.mjs +1 -1
- package/dist/es/yaml/execution-context.node.mjs +6 -0
- package/dist/es/yaml/execution-context.node.mjs.map +1 -0
- package/dist/es/yaml/execution-context.stub.mjs +8 -0
- package/dist/es/yaml/execution-context.stub.mjs.map +1 -0
- package/dist/es/yaml/execution-session.mjs +90 -0
- package/dist/es/yaml/execution-session.mjs.map +1 -0
- package/dist/es/yaml/index.mjs +2 -1
- package/dist/es/yaml/legacy-yaml-execution-record.mjs +47 -0
- package/dist/es/yaml/legacy-yaml-execution-record.mjs.map +1 -0
- package/dist/es/yaml/legacy-yaml-report.mjs +52 -0
- package/dist/es/yaml/legacy-yaml-report.mjs.map +1 -0
- package/dist/es/yaml/legacy-yaml-runtime.mjs +119 -0
- package/dist/es/yaml/legacy-yaml-runtime.mjs.map +1 -0
- package/dist/es/yaml/player-state.mjs +15 -0
- package/dist/es/yaml/player-state.mjs.map +1 -0
- package/dist/es/yaml/player.mjs +214 -348
- package/dist/es/yaml/player.mjs.map +1 -1
- package/dist/es/yaml/report-policy.mjs +7 -0
- package/dist/es/yaml/report-policy.mjs.map +1 -0
- package/dist/es/yaml/test-runner-compat.mjs +301 -0
- package/dist/es/yaml/test-runner-compat.mjs.map +1 -0
- package/dist/es/yaml/test-runner-nodes.mjs +147 -0
- package/dist/es/yaml/test-runner-nodes.mjs.map +1 -0
- package/dist/es/yaml/utils.mjs +12 -1
- package/dist/es/yaml/utils.mjs.map +1 -1
- package/dist/es/yaml-runtime.mjs +7 -0
- package/dist/es/yaml.mjs.map +1 -1
- package/dist/lib/agent/agent.js +103 -6
- package/dist/lib/agent/agent.js.map +1 -1
- package/dist/lib/agent/index.js +37 -3
- package/dist/lib/agent/tasks.js +2 -2
- package/dist/lib/agent/tasks.js.map +1 -1
- package/dist/lib/agent/test-runner-nodes.js +329 -45
- package/dist/lib/agent/test-runner-nodes.js.map +1 -1
- package/dist/lib/agent/utils.js +1 -1
- package/dist/lib/device/index.js +15 -2
- package/dist/lib/device/index.js.map +1 -1
- package/dist/lib/dump/html-utils.js +43 -4
- package/dist/lib/dump/html-utils.js.map +1 -1
- package/dist/lib/dump/screenshot-store.js +8 -1
- package/dist/lib/dump/screenshot-store.js.map +1 -1
- package/dist/lib/report-cli.js +8 -3
- package/dist/lib/report-cli.js.map +1 -1
- package/dist/lib/report-generator.js +114 -1
- package/dist/lib/report-generator.js.map +1 -1
- package/dist/lib/report-html-template.js +1 -1
- package/dist/lib/report.js +187 -38
- package/dist/lib/report.js.map +1 -1
- package/dist/lib/test-run-report.js.map +1 -1
- package/dist/lib/test-runner/engine/case-runner.js +89 -0
- package/dist/lib/test-runner/engine/case-runner.js.map +1 -0
- package/dist/lib/test-runner/engine/document-runtime.js +307 -0
- package/dist/lib/test-runner/engine/document-runtime.js.map +1 -0
- package/dist/lib/test-runner/engine/execute-step.js +211 -0
- package/dist/lib/test-runner/engine/execute-step.js.map +1 -0
- package/dist/lib/test-runner/engine/execution-failure.js +79 -0
- package/dist/lib/test-runner/engine/execution-failure.js.map +1 -0
- package/dist/lib/test-runner/engine/index.js +137 -0
- package/dist/lib/test-runner/engine/index.js.map +1 -0
- package/dist/lib/test-runner/engine/project-runtime.js +176 -0
- package/dist/lib/test-runner/engine/project-runtime.js.map +1 -0
- package/dist/lib/test-runner/engine/registry.js +95 -0
- package/dist/lib/test-runner/engine/registry.js.map +1 -0
- package/dist/lib/test-runner/engine/resource-operations.js +272 -0
- package/dist/lib/test-runner/engine/resource-operations.js.map +1 -0
- package/dist/lib/test-runner/engine/run-collected-case.js +227 -0
- package/dist/lib/test-runner/engine/run-collected-case.js.map +1 -0
- package/dist/lib/test-runner/engine/run-workflow-document.js +189 -0
- package/dist/lib/test-runner/engine/run-workflow-document.js.map +1 -0
- package/dist/lib/test-runner/engine/scheduler.js +64 -0
- package/dist/lib/test-runner/engine/scheduler.js.map +1 -0
- package/dist/lib/test-runner/engine/scope-teardown.js +50 -0
- package/dist/lib/test-runner/engine/scope-teardown.js.map +1 -0
- package/dist/lib/test-runner/engine/types.js +20 -0
- package/dist/lib/test-runner/engine/types.js.map +1 -0
- package/dist/lib/test-runner/errors.js +283 -0
- package/dist/lib/test-runner/errors.js.map +1 -0
- package/dist/lib/test-runner/execution-record.js +123 -0
- package/dist/lib/test-runner/execution-record.js.map +1 -0
- package/dist/lib/test-runner/index.js +137 -0
- package/dist/lib/test-runner/index.js.map +1 -0
- package/dist/lib/test-runner/node/define-node.js +78 -0
- package/dist/lib/test-runner/node/define-node.js.map +1 -0
- package/dist/lib/test-runner/node/index.js +67 -0
- package/dist/lib/test-runner/node/index.js.map +1 -0
- package/dist/lib/test-runner/node/types.js +20 -0
- package/dist/lib/test-runner/node/types.js.map +1 -0
- package/dist/lib/test-runner/parser/document-format.js +58 -0
- package/dist/lib/test-runner/parser/document-format.js.map +1 -0
- package/dist/lib/test-runner/parser/normalize.js +124 -0
- package/dist/lib/test-runner/parser/normalize.js.map +1 -0
- package/dist/lib/test-runner/parser/types.js +20 -0
- package/dist/lib/test-runner/parser/types.js.map +1 -0
- package/dist/lib/test-runner/project.js +20 -0
- package/dist/lib/test-runner/project.js.map +1 -0
- package/dist/lib/test-runner/reporting/agent-report.js +57 -0
- package/dist/lib/test-runner/reporting/agent-report.js.map +1 -0
- package/dist/lib/test-runner/reporting/execution-record.js +107 -0
- package/dist/lib/test-runner/reporting/execution-record.js.map +1 -0
- package/dist/lib/test-runner/reporting/merge-report.js +265 -0
- package/dist/lib/test-runner/reporting/merge-report.js.map +1 -0
- package/dist/lib/test-runner/reporting/sanitize.js +202 -0
- package/dist/lib/test-runner/reporting/sanitize.js.map +1 -0
- package/dist/lib/test-runner/reporting/test-run-report.js +364 -0
- package/dist/lib/test-runner/reporting/test-run-report.js.map +1 -0
- package/dist/lib/test-runner/reporting/types.js +20 -0
- package/dist/lib/test-runner/reporting/types.js.map +1 -0
- package/dist/lib/utils.js +1 -1
- package/dist/lib/yaml/execution-context.node.js +43 -0
- package/dist/lib/yaml/execution-context.node.js.map +1 -0
- package/dist/lib/yaml/execution-context.stub.js +45 -0
- package/dist/lib/yaml/execution-context.stub.js.map +1 -0
- package/dist/lib/yaml/execution-session.js +136 -0
- package/dist/lib/yaml/execution-session.js.map +1 -0
- package/dist/lib/yaml/index.js +49 -7
- package/dist/lib/yaml/legacy-yaml-execution-record.js +81 -0
- package/dist/lib/yaml/legacy-yaml-execution-record.js.map +1 -0
- package/dist/lib/yaml/legacy-yaml-report.js +86 -0
- package/dist/lib/yaml/legacy-yaml-report.js.map +1 -0
- package/dist/lib/yaml/legacy-yaml-runtime.js +156 -0
- package/dist/lib/yaml/legacy-yaml-runtime.js.map +1 -0
- package/dist/lib/yaml/player-state.js +52 -0
- package/dist/lib/yaml/player-state.js.map +1 -0
- package/dist/lib/yaml/player.js +213 -347
- package/dist/lib/yaml/player.js.map +1 -1
- package/dist/lib/yaml/report-policy.js +41 -0
- package/dist/lib/yaml/report-policy.js.map +1 -0
- package/dist/lib/yaml/test-runner-compat.js +344 -0
- package/dist/lib/yaml/test-runner-compat.js.map +1 -0
- package/dist/lib/yaml/test-runner-nodes.js +184 -0
- package/dist/lib/yaml/test-runner-nodes.js.map +1 -0
- package/dist/lib/yaml/utils.js +18 -1
- package/dist/lib/yaml/utils.js.map +1 -1
- package/dist/lib/yaml-runtime.js +67 -0
- package/dist/lib/yaml-runtime.js.map +1 -0
- package/dist/lib/yaml.js.map +1 -1
- package/dist/types/agent/agent.d.ts +14 -1
- package/dist/types/agent/agent.d.ts.map +1 -1
- package/dist/types/agent/index.d.ts +4 -3
- package/dist/types/agent/index.d.ts.map +1 -1
- package/dist/types/agent/tasks.d.ts +1 -1
- package/dist/types/agent/tasks.d.ts.map +1 -1
- package/dist/types/agent/test-runner-nodes.d.ts +226 -0
- package/dist/types/agent/test-runner-nodes.d.ts.map +1 -1
- package/dist/types/device/index.d.ts +1 -1
- package/dist/types/device/index.d.ts.map +1 -1
- package/dist/types/dump/html-utils.d.ts +4 -0
- package/dist/types/dump/html-utils.d.ts.map +1 -1
- package/dist/types/dump/screenshot-store.d.ts +2 -1
- package/dist/types/dump/screenshot-store.d.ts.map +1 -1
- package/dist/types/report-cli.d.ts.map +1 -1
- package/dist/types/report-generator.d.ts +10 -0
- package/dist/types/report-generator.d.ts.map +1 -1
- package/dist/types/report.d.ts +3 -1
- package/dist/types/report.d.ts.map +1 -1
- package/dist/types/test-run-report.d.ts +18 -2
- package/dist/types/test-run-report.d.ts.map +1 -1
- package/dist/types/test-runner/engine/case-runner.d.ts +13 -0
- package/dist/types/test-runner/engine/case-runner.d.ts.map +1 -0
- package/dist/types/test-runner/engine/document-runtime.d.ts +4 -0
- package/dist/types/test-runner/engine/document-runtime.d.ts.map +1 -0
- package/dist/types/test-runner/engine/execute-step.d.ts +17 -0
- package/dist/types/test-runner/engine/execute-step.d.ts.map +1 -0
- package/dist/types/test-runner/engine/execution-failure.d.ts +13 -0
- package/dist/types/test-runner/engine/execution-failure.d.ts.map +1 -0
- package/dist/types/test-runner/engine/index.d.ts +13 -0
- package/dist/types/test-runner/engine/index.d.ts.map +1 -0
- package/dist/types/test-runner/engine/project-runtime.d.ts +3 -0
- package/dist/types/test-runner/engine/project-runtime.d.ts.map +1 -0
- package/dist/types/test-runner/engine/registry.d.ts +12 -0
- package/dist/types/test-runner/engine/registry.d.ts.map +1 -0
- package/dist/types/test-runner/engine/resource-operations.d.ts +32 -0
- package/dist/types/test-runner/engine/resource-operations.d.ts.map +1 -0
- package/dist/types/test-runner/engine/run-collected-case.d.ts +4 -0
- package/dist/types/test-runner/engine/run-collected-case.d.ts.map +1 -0
- package/dist/types/test-runner/engine/run-workflow-document.d.ts +4 -0
- package/dist/types/test-runner/engine/run-workflow-document.d.ts.map +1 -0
- package/dist/types/test-runner/engine/scheduler.d.ts +12 -0
- package/dist/types/test-runner/engine/scheduler.d.ts.map +1 -0
- package/dist/types/test-runner/engine/scope-teardown.d.ts +3 -0
- package/dist/types/test-runner/engine/scope-teardown.d.ts.map +1 -0
- package/dist/types/test-runner/engine/types.d.ts +226 -0
- package/dist/types/test-runner/engine/types.d.ts.map +1 -0
- package/dist/types/test-runner/errors.d.ts +79 -0
- package/dist/types/test-runner/errors.d.ts.map +1 -0
- package/dist/types/test-runner/execution-record.d.ts +43 -0
- package/dist/types/test-runner/execution-record.d.ts.map +1 -0
- package/dist/types/test-runner/index.d.ts +20 -0
- package/dist/types/test-runner/index.d.ts.map +1 -0
- package/dist/types/test-runner/node/define-node.d.ts +4 -0
- package/dist/types/test-runner/node/define-node.d.ts.map +1 -0
- package/dist/types/test-runner/node/index.d.ts +3 -0
- package/dist/types/test-runner/node/index.d.ts.map +1 -0
- package/dist/types/test-runner/node/types.d.ts +66 -0
- package/dist/types/test-runner/node/types.d.ts.map +1 -0
- package/dist/types/test-runner/parser/document-format.d.ts +8 -0
- package/dist/types/test-runner/parser/document-format.d.ts.map +1 -0
- package/dist/types/test-runner/parser/normalize.d.ts +9 -0
- package/dist/types/test-runner/parser/normalize.d.ts.map +1 -0
- package/dist/types/test-runner/parser/types.d.ts +69 -0
- package/dist/types/test-runner/parser/types.d.ts.map +1 -0
- package/dist/types/test-runner/project.d.ts +75 -0
- package/dist/types/test-runner/project.d.ts.map +1 -0
- package/dist/types/test-runner/reporting/agent-report.d.ts +9 -0
- package/dist/types/test-runner/reporting/agent-report.d.ts.map +1 -0
- package/dist/types/test-runner/reporting/execution-record.d.ts +9 -0
- package/dist/types/test-runner/reporting/execution-record.d.ts.map +1 -0
- package/dist/types/test-runner/reporting/merge-report.d.ts +15 -0
- package/dist/types/test-runner/reporting/merge-report.d.ts.map +1 -0
- package/dist/types/test-runner/reporting/sanitize.d.ts +6 -0
- package/dist/types/test-runner/reporting/sanitize.d.ts.map +1 -0
- package/dist/types/test-runner/reporting/test-run-report.d.ts +5 -0
- package/dist/types/test-runner/reporting/test-run-report.d.ts.map +1 -0
- package/dist/types/test-runner/reporting/types.d.ts +34 -0
- package/dist/types/test-runner/reporting/types.d.ts.map +1 -0
- package/dist/types/yaml/execution-context.node.d.ts +4 -0
- package/dist/types/yaml/execution-context.node.d.ts.map +1 -0
- package/dist/types/yaml/execution-context.stub.d.ts +6 -0
- package/dist/types/yaml/execution-context.stub.d.ts.map +1 -0
- package/dist/types/yaml/execution-session.d.ts +17 -0
- package/dist/types/yaml/execution-session.d.ts.map +1 -0
- package/dist/types/yaml/index.d.ts +1 -1
- package/dist/types/yaml/index.d.ts.map +1 -1
- package/dist/types/yaml/legacy-yaml-execution-record.d.ts +24 -0
- package/dist/types/yaml/legacy-yaml-execution-record.d.ts.map +1 -0
- package/dist/types/yaml/legacy-yaml-report.d.ts +19 -0
- package/dist/types/yaml/legacy-yaml-report.d.ts.map +1 -0
- package/dist/types/yaml/legacy-yaml-runtime.d.ts +23 -0
- package/dist/types/yaml/legacy-yaml-runtime.d.ts.map +1 -0
- package/dist/types/yaml/player-state.d.ts +11 -0
- package/dist/types/yaml/player-state.d.ts.map +1 -0
- package/dist/types/yaml/player.d.ts +11 -3
- package/dist/types/yaml/player.d.ts.map +1 -1
- package/dist/types/yaml/report-policy.d.ts +4 -0
- package/dist/types/yaml/report-policy.d.ts.map +1 -0
- package/dist/types/yaml/test-runner-compat.d.ts +17 -0
- package/dist/types/yaml/test-runner-compat.d.ts.map +1 -0
- package/dist/types/yaml/test-runner-nodes.d.ts +6 -0
- package/dist/types/yaml/test-runner-nodes.d.ts.map +1 -0
- package/dist/types/yaml/utils.d.ts +9 -0
- package/dist/types/yaml/utils.d.ts.map +1 -1
- package/dist/types/yaml-runtime.d.ts +13 -0
- package/dist/types/yaml-runtime.d.ts.map +1 -0
- package/dist/types/yaml.d.ts +25 -7
- package/dist/types/yaml.d.ts.map +1 -1
- package/package.json +28 -2
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { getDebug } from "@midscene/shared/logger";
|
|
2
|
+
import { uuid } from "@midscene/shared/utils";
|
|
3
|
+
import { NodeScopeTeardownError, WorkflowLifecycleError } from "../errors.mjs";
|
|
4
|
+
import { executeStep } from "./execute-step.mjs";
|
|
5
|
+
import { WorkflowExecutionFailure, asExecutionError } from "./execution-failure.mjs";
|
|
6
|
+
import { ResourceCleanupDeferredError, cleanupScopeResources, createResourceScope } from "./resource-operations.mjs";
|
|
7
|
+
import { reportPathsFromTeardown } from "./scope-teardown.mjs";
|
|
8
|
+
async function runCollectedCase(collectedCase, options) {
|
|
9
|
+
const phases = {
|
|
10
|
+
beforeEach: options.beforeEach ?? [],
|
|
11
|
+
steps: collectedCase.definition.steps,
|
|
12
|
+
afterEach: options.afterEach ?? []
|
|
13
|
+
};
|
|
14
|
+
const nodes = {
|
|
15
|
+
beforeEach: phases.beforeEach.map((step)=>options.resolveNode(step.node)),
|
|
16
|
+
steps: phases.steps.map((step)=>options.resolveNode(step.node)),
|
|
17
|
+
afterEach: phases.afterEach.map((step)=>options.resolveNode(step.node))
|
|
18
|
+
};
|
|
19
|
+
const resourceScope = createResourceScope(options.signal);
|
|
20
|
+
const scopeSignal = resourceScope.signal;
|
|
21
|
+
const runId = options.createRunId?.() ?? uuid();
|
|
22
|
+
const startedAt = new Date();
|
|
23
|
+
const beforeEach = [];
|
|
24
|
+
const steps = [];
|
|
25
|
+
const afterEach = [];
|
|
26
|
+
const teardownStack = [];
|
|
27
|
+
let acceptingTeardowns = true;
|
|
28
|
+
const onTeardown = (node, teardown)=>{
|
|
29
|
+
if (!acceptingTeardowns) throw new WorkflowLifecycleError('Node teardown can only be registered while a case attempt is running.', {
|
|
30
|
+
runId,
|
|
31
|
+
node
|
|
32
|
+
});
|
|
33
|
+
if ('function' != typeof teardown) throw new WorkflowLifecycleError('Node onTeardown() requires a teardown function.', {
|
|
34
|
+
runId,
|
|
35
|
+
node
|
|
36
|
+
});
|
|
37
|
+
teardownStack.push({
|
|
38
|
+
registrationIndex: teardownStack.length,
|
|
39
|
+
node,
|
|
40
|
+
teardown
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
const runPhase = async (phase, results, signal = scopeSignal)=>{
|
|
44
|
+
for (const [stepIndex, step] of phases[phase].entries()){
|
|
45
|
+
const caseContext = {
|
|
46
|
+
caseId: collectedCase.caseId,
|
|
47
|
+
runId,
|
|
48
|
+
projectName: options.projectName ?? collectedCase.projectId,
|
|
49
|
+
attemptIndex: options.attemptIndex ?? 0,
|
|
50
|
+
name: collectedCase.definition.name,
|
|
51
|
+
sourcePath: collectedCase.sourcePath,
|
|
52
|
+
caseIndex: collectedCase.caseIndex,
|
|
53
|
+
phase,
|
|
54
|
+
stepIndex
|
|
55
|
+
};
|
|
56
|
+
const stepInfo = {
|
|
57
|
+
scope: 'case',
|
|
58
|
+
node: step.node,
|
|
59
|
+
stepCount: phases[phase].length,
|
|
60
|
+
case: caseContext
|
|
61
|
+
};
|
|
62
|
+
await options.onStepStart?.(stepInfo);
|
|
63
|
+
const result = await executeStep(step, nodes[phase][stepIndex], {
|
|
64
|
+
scope: 'case',
|
|
65
|
+
case: caseContext
|
|
66
|
+
}, options.context, {
|
|
67
|
+
signal,
|
|
68
|
+
defaultTimeoutMs: options.defaultTimeoutMs,
|
|
69
|
+
onTeardown
|
|
70
|
+
});
|
|
71
|
+
results.push(result);
|
|
72
|
+
await options.onStepResult?.(stepInfo, result);
|
|
73
|
+
if ('failed' === result.status && !result.continuedAfterError) break;
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const executionErrors = [];
|
|
77
|
+
try {
|
|
78
|
+
await runPhase('beforeEach', beforeEach);
|
|
79
|
+
if (!beforeEach.some((step)=>'failed' === step.status)) await runPhase('steps', steps);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
executionErrors.push(error);
|
|
82
|
+
}
|
|
83
|
+
const teardownErrors = [];
|
|
84
|
+
const reportPaths = new Set();
|
|
85
|
+
const reportSources = [];
|
|
86
|
+
const cleanupExecutionErrors = [];
|
|
87
|
+
let deferredCleanup = false;
|
|
88
|
+
const cleanup = async ()=>{
|
|
89
|
+
const priorTeardownErrors = teardownErrors.length;
|
|
90
|
+
acceptingTeardowns = false;
|
|
91
|
+
for (const { registrationIndex, node, teardown } of teardownStack.reverse())try {
|
|
92
|
+
const released = await teardown();
|
|
93
|
+
reportSources.push(...released?.reportSources ?? []);
|
|
94
|
+
for (const path of reportPathsFromTeardown(released))reportPaths.add(path);
|
|
95
|
+
} catch (error) {
|
|
96
|
+
teardownErrors.push(new NodeScopeTeardownError(error, {
|
|
97
|
+
scope: 'case',
|
|
98
|
+
scopeId: runId,
|
|
99
|
+
node,
|
|
100
|
+
registrationIndex
|
|
101
|
+
}));
|
|
102
|
+
}
|
|
103
|
+
if (deferredCleanup) {
|
|
104
|
+
const errors = [
|
|
105
|
+
...cleanupExecutionErrors,
|
|
106
|
+
...teardownErrors.slice(priorTeardownErrors)
|
|
107
|
+
];
|
|
108
|
+
if (errors.length) throw new AggregateError(errors, 'Deferred Case cleanup failed');
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
try {
|
|
112
|
+
if (phases.afterEach.length || teardownStack.length) await cleanupScopeResources(scopeSignal, cleanup, {
|
|
113
|
+
beforeCleanup: async (cleanupSignal)=>{
|
|
114
|
+
try {
|
|
115
|
+
await runPhase('afterEach', afterEach, cleanupSignal);
|
|
116
|
+
} catch (error) {
|
|
117
|
+
executionErrors.push(error);
|
|
118
|
+
cleanupExecutionErrors.push(error);
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
onDeferredError: (error)=>getDebug('runner:cleanup', {
|
|
122
|
+
console: true
|
|
123
|
+
})(`Deferred Case cleanup failed: ${String(error)}`)
|
|
124
|
+
});
|
|
125
|
+
else acceptingTeardowns = false;
|
|
126
|
+
} catch (error) {
|
|
127
|
+
deferredCleanup = error instanceof ResourceCleanupDeferredError;
|
|
128
|
+
if (!deferredCleanup) acceptingTeardowns = false;
|
|
129
|
+
teardownErrors.push(new NodeScopeTeardownError(error, {
|
|
130
|
+
scope: 'case',
|
|
131
|
+
scopeId: runId,
|
|
132
|
+
node: 'resource-drain',
|
|
133
|
+
registrationIndex: -1
|
|
134
|
+
}));
|
|
135
|
+
}
|
|
136
|
+
const endedAt = new Date();
|
|
137
|
+
const result = {
|
|
138
|
+
caseId: collectedCase.caseId,
|
|
139
|
+
runId,
|
|
140
|
+
projectName: options.projectName ?? collectedCase.projectId,
|
|
141
|
+
attemptIndex: options.attemptIndex ?? 0,
|
|
142
|
+
name: collectedCase.definition.name,
|
|
143
|
+
sourcePath: collectedCase.sourcePath,
|
|
144
|
+
caseIndex: collectedCase.caseIndex,
|
|
145
|
+
status: executionErrors.length > 0 || beforeEach.some((step)=>'failed' === step.status) || steps.some((step)=>'failed' === step.status) || afterEach.some((step)=>'failed' === step.status) || teardownErrors.length > 0 ? 'failed' : 'success',
|
|
146
|
+
beforeEach: [
|
|
147
|
+
...beforeEach
|
|
148
|
+
],
|
|
149
|
+
steps: [
|
|
150
|
+
...steps
|
|
151
|
+
],
|
|
152
|
+
afterEach: [
|
|
153
|
+
...afterEach
|
|
154
|
+
],
|
|
155
|
+
...executionErrors.length ? {
|
|
156
|
+
executionErrors: executionErrors.map(asExecutionError)
|
|
157
|
+
} : {},
|
|
158
|
+
...teardownErrors.length > 0 ? {
|
|
159
|
+
teardownErrors: [
|
|
160
|
+
...teardownErrors
|
|
161
|
+
]
|
|
162
|
+
} : {},
|
|
163
|
+
...reportPaths.size > 0 ? {
|
|
164
|
+
reportPaths: [
|
|
165
|
+
...reportPaths
|
|
166
|
+
]
|
|
167
|
+
} : {},
|
|
168
|
+
...reportSources.length ? {
|
|
169
|
+
reportSources: [
|
|
170
|
+
...reportSources
|
|
171
|
+
]
|
|
172
|
+
} : {},
|
|
173
|
+
...options.reportScopeId ? {
|
|
174
|
+
reportScopeId: options.reportScopeId
|
|
175
|
+
} : {},
|
|
176
|
+
startedAt: startedAt.toISOString(),
|
|
177
|
+
endedAt: endedAt.toISOString(),
|
|
178
|
+
durationMs: Math.max(0, endedAt.getTime() - startedAt.getTime())
|
|
179
|
+
};
|
|
180
|
+
try {
|
|
181
|
+
await options.onResult?.(result);
|
|
182
|
+
} catch (error) {
|
|
183
|
+
executionErrors.push(error);
|
|
184
|
+
result.status = 'failed';
|
|
185
|
+
result.executionErrors = executionErrors.map(asExecutionError);
|
|
186
|
+
}
|
|
187
|
+
resourceScope.dispose();
|
|
188
|
+
if (executionErrors.length) throw new WorkflowExecutionFailure(result, executionErrors);
|
|
189
|
+
return result;
|
|
190
|
+
}
|
|
191
|
+
export { runCollectedCase };
|
|
192
|
+
|
|
193
|
+
//# sourceMappingURL=run-collected-case.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-runner/engine/run-collected-case.mjs","sources":["../../../../src/test-runner/engine/run-collected-case.ts"],"sourcesContent":["import { getDebug } from '@midscene/shared/logger';\nimport { uuid as randomUUID } from '@midscene/shared/utils';\nimport { NodeScopeTeardownError, WorkflowLifecycleError } from '../errors';\nimport type { CollectedCase, NormalizedStep } from '../parser/types';\nimport { executeStep } from './execute-step';\nimport {\n WorkflowExecutionFailure,\n asExecutionError,\n} from './execution-failure';\nimport {\n ResourceCleanupDeferredError,\n cleanupScopeResources,\n createResourceScope,\n} from './resource-operations';\nimport { reportPathsFromTeardown } from './scope-teardown';\nimport type {\n CaseNodePhase,\n CaseRunResult,\n NodeCaseContext,\n NodeScopeTeardown,\n RunCollectedCaseOptions,\n StepRunResult,\n} from './types';\n\nexport async function runCollectedCase<TContext = undefined>(\n collectedCase: CollectedCase,\n options: RunCollectedCaseOptions<TContext>,\n): Promise<CaseRunResult> {\n const phases: Record<CaseNodePhase, readonly NormalizedStep[]> = {\n beforeEach: options.beforeEach ?? [],\n steps: collectedCase.definition.steps,\n afterEach: options.afterEach ?? [],\n };\n const nodes = {\n beforeEach: phases.beforeEach.map((step) => options.resolveNode(step.node)),\n steps: phases.steps.map((step) => options.resolveNode(step.node)),\n afterEach: phases.afterEach.map((step) => options.resolveNode(step.node)),\n };\n const resourceScope = createResourceScope(options.signal);\n const scopeSignal = resourceScope.signal;\n const runId = options.createRunId?.() ?? randomUUID();\n const startedAt = new Date();\n const beforeEach: StepRunResult[] = [];\n const steps: StepRunResult[] = [];\n const afterEach: StepRunResult[] = [];\n const teardownStack: Array<{\n registrationIndex: number;\n node: string;\n teardown: NodeScopeTeardown;\n }> = [];\n let acceptingTeardowns = true;\n\n const onTeardown = (node: string, teardown: NodeScopeTeardown): void => {\n if (!acceptingTeardowns) {\n throw new WorkflowLifecycleError(\n 'Node teardown can only be registered while a case attempt is running.',\n { runId, node },\n );\n }\n if (typeof teardown !== 'function') {\n throw new WorkflowLifecycleError(\n 'Node onTeardown() requires a teardown function.',\n { runId, node },\n );\n }\n teardownStack.push({\n registrationIndex: teardownStack.length,\n node,\n teardown,\n });\n };\n\n const runPhase = async (\n phase: CaseNodePhase,\n results: StepRunResult[],\n signal = scopeSignal,\n ): Promise<void> => {\n for (const [stepIndex, step] of phases[phase].entries()) {\n const caseContext: NodeCaseContext = {\n caseId: collectedCase.caseId,\n runId,\n projectName: options.projectName ?? collectedCase.projectId,\n attemptIndex: options.attemptIndex ?? 0,\n name: collectedCase.definition.name,\n sourcePath: collectedCase.sourcePath,\n caseIndex: collectedCase.caseIndex,\n phase,\n stepIndex,\n };\n const stepInfo = {\n scope: 'case' as const,\n node: step.node,\n stepCount: phases[phase].length,\n case: caseContext,\n };\n await options.onStepStart?.(stepInfo);\n const result = await executeStep(\n step,\n nodes[phase][stepIndex],\n { scope: 'case', case: caseContext },\n options.context as TContext,\n {\n signal,\n defaultTimeoutMs: options.defaultTimeoutMs,\n onTeardown,\n },\n );\n results.push(result);\n await options.onStepResult?.(stepInfo, result);\n if (result.status === 'failed' && !result.continuedAfterError) break;\n }\n };\n\n const executionErrors: unknown[] = [];\n try {\n await runPhase('beforeEach', beforeEach);\n if (!beforeEach.some((step) => step.status === 'failed')) {\n await runPhase('steps', steps);\n }\n } catch (error) {\n executionErrors.push(error);\n }\n const teardownErrors: NodeScopeTeardownError[] = [];\n const reportPaths = new Set<string>();\n const reportSources: import('./types').WorkflowReportSource[] = [];\n const cleanupExecutionErrors: unknown[] = [];\n let deferredCleanup = false;\n const cleanup = async () => {\n const priorTeardownErrors = teardownErrors.length;\n acceptingTeardowns = false;\n for (const {\n registrationIndex,\n node,\n teardown,\n } of teardownStack.reverse()) {\n try {\n const released = await teardown();\n reportSources.push(...(released?.reportSources ?? []));\n for (const path of reportPathsFromTeardown(released)) {\n reportPaths.add(path);\n }\n } catch (error) {\n teardownErrors.push(\n new NodeScopeTeardownError(error, {\n scope: 'case',\n scopeId: runId,\n node,\n registrationIndex,\n }),\n );\n }\n }\n if (deferredCleanup) {\n const errors = [\n ...cleanupExecutionErrors,\n ...teardownErrors.slice(priorTeardownErrors),\n ];\n if (errors.length)\n throw new AggregateError(errors, 'Deferred Case cleanup failed');\n }\n };\n try {\n if (phases.afterEach.length || teardownStack.length)\n await cleanupScopeResources(scopeSignal, cleanup, {\n beforeCleanup: async (cleanupSignal) => {\n try {\n await runPhase('afterEach', afterEach, cleanupSignal);\n } catch (error) {\n executionErrors.push(error);\n cleanupExecutionErrors.push(error);\n }\n },\n onDeferredError: (error) =>\n getDebug('runner:cleanup', { console: true })(\n `Deferred Case cleanup failed: ${String(error)}`,\n ),\n });\n else acceptingTeardowns = false;\n } catch (error) {\n deferredCleanup = error instanceof ResourceCleanupDeferredError;\n if (!deferredCleanup) acceptingTeardowns = false;\n teardownErrors.push(\n new NodeScopeTeardownError(error, {\n scope: 'case',\n scopeId: runId,\n node: 'resource-drain',\n registrationIndex: -1,\n }),\n );\n }\n const endedAt = new Date();\n const result: CaseRunResult = {\n caseId: collectedCase.caseId,\n runId,\n projectName: options.projectName ?? collectedCase.projectId,\n attemptIndex: options.attemptIndex ?? 0,\n name: collectedCase.definition.name,\n sourcePath: collectedCase.sourcePath,\n caseIndex: collectedCase.caseIndex,\n status:\n executionErrors.length > 0 ||\n beforeEach.some((step) => step.status === 'failed') ||\n steps.some((step) => step.status === 'failed') ||\n afterEach.some((step) => step.status === 'failed') ||\n teardownErrors.length > 0\n ? 'failed'\n : 'success',\n beforeEach: [...beforeEach],\n steps: [...steps],\n afterEach: [...afterEach],\n ...(executionErrors.length\n ? { executionErrors: executionErrors.map(asExecutionError) }\n : {}),\n ...(teardownErrors.length > 0\n ? { teardownErrors: [...teardownErrors] }\n : {}),\n ...(reportPaths.size > 0 ? { reportPaths: [...reportPaths] } : {}),\n ...(reportSources.length ? { reportSources: [...reportSources] } : {}),\n ...(options.reportScopeId ? { reportScopeId: options.reportScopeId } : {}),\n startedAt: startedAt.toISOString(),\n endedAt: endedAt.toISOString(),\n durationMs: Math.max(0, endedAt.getTime() - startedAt.getTime()),\n };\n\n try {\n await options.onResult?.(result);\n } catch (error) {\n executionErrors.push(error);\n result.status = 'failed';\n result.executionErrors = executionErrors.map(asExecutionError);\n }\n resourceScope.dispose();\n if (executionErrors.length)\n throw new WorkflowExecutionFailure(result, executionErrors);\n return result;\n}\n"],"names":["runCollectedCase","collectedCase","options","phases","nodes","step","resourceScope","createResourceScope","scopeSignal","runId","randomUUID","startedAt","Date","beforeEach","steps","afterEach","teardownStack","acceptingTeardowns","onTeardown","node","teardown","WorkflowLifecycleError","runPhase","phase","results","signal","stepIndex","caseContext","stepInfo","result","executeStep","executionErrors","error","teardownErrors","reportPaths","Set","reportSources","cleanupExecutionErrors","deferredCleanup","cleanup","priorTeardownErrors","registrationIndex","released","path","reportPathsFromTeardown","NodeScopeTeardownError","errors","AggregateError","cleanupScopeResources","cleanupSignal","getDebug","String","ResourceCleanupDeferredError","endedAt","asExecutionError","Math","WorkflowExecutionFailure"],"mappings":";;;;;;;AAwBO,eAAeA,iBACpBC,aAA4B,EAC5BC,OAA0C;IAE1C,MAAMC,SAA2D;QAC/D,YAAYD,QAAQ,UAAU,IAAI,EAAE;QACpC,OAAOD,cAAc,UAAU,CAAC,KAAK;QACrC,WAAWC,QAAQ,SAAS,IAAI,EAAE;IACpC;IACA,MAAME,QAAQ;QACZ,YAAYD,OAAO,UAAU,CAAC,GAAG,CAAC,CAACE,OAASH,QAAQ,WAAW,CAACG,KAAK,IAAI;QACzE,OAAOF,OAAO,KAAK,CAAC,GAAG,CAAC,CAACE,OAASH,QAAQ,WAAW,CAACG,KAAK,IAAI;QAC/D,WAAWF,OAAO,SAAS,CAAC,GAAG,CAAC,CAACE,OAASH,QAAQ,WAAW,CAACG,KAAK,IAAI;IACzE;IACA,MAAMC,gBAAgBC,oBAAoBL,QAAQ,MAAM;IACxD,MAAMM,cAAcF,cAAc,MAAM;IACxC,MAAMG,QAAQP,QAAQ,WAAW,QAAQQ;IACzC,MAAMC,YAAY,IAAIC;IACtB,MAAMC,aAA8B,EAAE;IACtC,MAAMC,QAAyB,EAAE;IACjC,MAAMC,YAA6B,EAAE;IACrC,MAAMC,gBAID,EAAE;IACP,IAAIC,qBAAqB;IAEzB,MAAMC,aAAa,CAACC,MAAcC;QAChC,IAAI,CAACH,oBACH,MAAM,IAAII,uBACR,yEACA;YAAEZ;YAAOU;QAAK;QAGlB,IAAI,AAAoB,cAApB,OAAOC,UACT,MAAM,IAAIC,uBACR,mDACA;YAAEZ;YAAOU;QAAK;QAGlBH,cAAc,IAAI,CAAC;YACjB,mBAAmBA,cAAc,MAAM;YACvCG;YACAC;QACF;IACF;IAEA,MAAME,WAAW,OACfC,OACAC,SACAC,SAASjB,WAAW;QAEpB,KAAK,MAAM,CAACkB,WAAWrB,KAAK,IAAIF,MAAM,CAACoB,MAAM,CAAC,OAAO,GAAI;YACvD,MAAMI,cAA+B;gBACnC,QAAQ1B,cAAc,MAAM;gBAC5BQ;gBACA,aAAaP,QAAQ,WAAW,IAAID,cAAc,SAAS;gBAC3D,cAAcC,QAAQ,YAAY,IAAI;gBACtC,MAAMD,cAAc,UAAU,CAAC,IAAI;gBACnC,YAAYA,cAAc,UAAU;gBACpC,WAAWA,cAAc,SAAS;gBAClCsB;gBACAG;YACF;YACA,MAAME,WAAW;gBACf,OAAO;gBACP,MAAMvB,KAAK,IAAI;gBACf,WAAWF,MAAM,CAACoB,MAAM,CAAC,MAAM;gBAC/B,MAAMI;YACR;YACA,MAAMzB,QAAQ,WAAW,GAAG0B;YAC5B,MAAMC,SAAS,MAAMC,YACnBzB,MACAD,KAAK,CAACmB,MAAM,CAACG,UAAU,EACvB;gBAAE,OAAO;gBAAQ,MAAMC;YAAY,GACnCzB,QAAQ,OAAO,EACf;gBACEuB;gBACA,kBAAkBvB,QAAQ,gBAAgB;gBAC1CgB;YACF;YAEFM,QAAQ,IAAI,CAACK;YACb,MAAM3B,QAAQ,YAAY,GAAG0B,UAAUC;YACvC,IAAIA,AAAkB,aAAlBA,OAAO,MAAM,IAAiB,CAACA,OAAO,mBAAmB,EAAE;QACjE;IACF;IAEA,MAAME,kBAA6B,EAAE;IACrC,IAAI;QACF,MAAMT,SAAS,cAAcT;QAC7B,IAAI,CAACA,WAAW,IAAI,CAAC,CAACR,OAASA,AAAgB,aAAhBA,KAAK,MAAM,GACxC,MAAMiB,SAAS,SAASR;IAE5B,EAAE,OAAOkB,OAAO;QACdD,gBAAgB,IAAI,CAACC;IACvB;IACA,MAAMC,iBAA2C,EAAE;IACnD,MAAMC,cAAc,IAAIC;IACxB,MAAMC,gBAA0D,EAAE;IAClE,MAAMC,yBAAoC,EAAE;IAC5C,IAAIC,kBAAkB;IACtB,MAAMC,UAAU;QACd,MAAMC,sBAAsBP,eAAe,MAAM;QACjDhB,qBAAqB;QACrB,KAAK,MAAM,EACTwB,iBAAiB,EACjBtB,IAAI,EACJC,QAAQ,EACT,IAAIJ,cAAc,OAAO,GACxB,IAAI;YACF,MAAM0B,WAAW,MAAMtB;YACvBgB,cAAc,IAAI,IAAKM,UAAU,iBAAiB,EAAE;YACpD,KAAK,MAAMC,QAAQC,wBAAwBF,UACzCR,YAAY,GAAG,CAACS;QAEpB,EAAE,OAAOX,OAAO;YACdC,eAAe,IAAI,CACjB,IAAIY,uBAAuBb,OAAO;gBAChC,OAAO;gBACP,SAASvB;gBACTU;gBACAsB;YACF;QAEJ;QAEF,IAAIH,iBAAiB;YACnB,MAAMQ,SAAS;mBACVT;mBACAJ,eAAe,KAAK,CAACO;aACzB;YACD,IAAIM,OAAO,MAAM,EACf,MAAM,IAAIC,eAAeD,QAAQ;QACrC;IACF;IACA,IAAI;QACF,IAAI3C,OAAO,SAAS,CAAC,MAAM,IAAIa,cAAc,MAAM,EACjD,MAAMgC,sBAAsBxC,aAAa+B,SAAS;YAChD,eAAe,OAAOU;gBACpB,IAAI;oBACF,MAAM3B,SAAS,aAAaP,WAAWkC;gBACzC,EAAE,OAAOjB,OAAO;oBACdD,gBAAgB,IAAI,CAACC;oBACrBK,uBAAuB,IAAI,CAACL;gBAC9B;YACF;YACA,iBAAiB,CAACA,QAChBkB,SAAS,kBAAkB;oBAAE,SAAS;gBAAK,GACzC,CAAC,8BAA8B,EAAEC,OAAOnB,QAAQ;QAEtD;aACGf,qBAAqB;IAC5B,EAAE,OAAOe,OAAO;QACdM,kBAAkBN,iBAAiBoB;QACnC,IAAI,CAACd,iBAAiBrB,qBAAqB;QAC3CgB,eAAe,IAAI,CACjB,IAAIY,uBAAuBb,OAAO;YAChC,OAAO;YACP,SAASvB;YACT,MAAM;YACN,mBAAmB;QACrB;IAEJ;IACA,MAAM4C,UAAU,IAAIzC;IACpB,MAAMiB,SAAwB;QAC5B,QAAQ5B,cAAc,MAAM;QAC5BQ;QACA,aAAaP,QAAQ,WAAW,IAAID,cAAc,SAAS;QAC3D,cAAcC,QAAQ,YAAY,IAAI;QACtC,MAAMD,cAAc,UAAU,CAAC,IAAI;QACnC,YAAYA,cAAc,UAAU;QACpC,WAAWA,cAAc,SAAS;QAClC,QACE8B,gBAAgB,MAAM,GAAG,KACzBlB,WAAW,IAAI,CAAC,CAACR,OAASA,AAAgB,aAAhBA,KAAK,MAAM,KACrCS,MAAM,IAAI,CAAC,CAACT,OAASA,AAAgB,aAAhBA,KAAK,MAAM,KAChCU,UAAU,IAAI,CAAC,CAACV,OAASA,AAAgB,aAAhBA,KAAK,MAAM,KACpC4B,eAAe,MAAM,GAAG,IACpB,WACA;QACN,YAAY;eAAIpB;SAAW;QAC3B,OAAO;eAAIC;SAAM;QACjB,WAAW;eAAIC;SAAU;QACzB,GAAIgB,gBAAgB,MAAM,GACtB;YAAE,iBAAiBA,gBAAgB,GAAG,CAACuB;QAAkB,IACzD,CAAC,CAAC;QACN,GAAIrB,eAAe,MAAM,GAAG,IACxB;YAAE,gBAAgB;mBAAIA;aAAe;QAAC,IACtC,CAAC,CAAC;QACN,GAAIC,YAAY,IAAI,GAAG,IAAI;YAAE,aAAa;mBAAIA;aAAY;QAAC,IAAI,CAAC,CAAC;QACjE,GAAIE,cAAc,MAAM,GAAG;YAAE,eAAe;mBAAIA;aAAc;QAAC,IAAI,CAAC,CAAC;QACrE,GAAIlC,QAAQ,aAAa,GAAG;YAAE,eAAeA,QAAQ,aAAa;QAAC,IAAI,CAAC,CAAC;QACzE,WAAWS,UAAU,WAAW;QAChC,SAAS0C,QAAQ,WAAW;QAC5B,YAAYE,KAAK,GAAG,CAAC,GAAGF,QAAQ,OAAO,KAAK1C,UAAU,OAAO;IAC/D;IAEA,IAAI;QACF,MAAMT,QAAQ,QAAQ,GAAG2B;IAC3B,EAAE,OAAOG,OAAO;QACdD,gBAAgB,IAAI,CAACC;QACrBH,OAAO,MAAM,GAAG;QAChBA,OAAO,eAAe,GAAGE,gBAAgB,GAAG,CAACuB;IAC/C;IACAhD,cAAc,OAAO;IACrB,IAAIyB,gBAAgB,MAAM,EACxB,MAAM,IAAIyB,yBAAyB3B,QAAQE;IAC7C,OAAOF;AACT"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { createDocumentRuntime } from "./document-runtime.mjs";
|
|
2
|
+
import { WorkflowExecutionFailure, asExecutionError } from "./execution-failure.mjs";
|
|
3
|
+
import { runCollectedCase } from "./run-collected-case.mjs";
|
|
4
|
+
const asNotRun = (collectedCase, projectName, reason)=>({
|
|
5
|
+
caseId: collectedCase.caseId,
|
|
6
|
+
projectName,
|
|
7
|
+
name: collectedCase.definition.name,
|
|
8
|
+
sourcePath: collectedCase.sourcePath,
|
|
9
|
+
caseIndex: collectedCase.caseIndex,
|
|
10
|
+
...collectedCase.definition.onFailure ? {
|
|
11
|
+
onFailure: collectedCase.definition.onFailure
|
|
12
|
+
} : {},
|
|
13
|
+
status: 'not-run',
|
|
14
|
+
notRunReason: reason
|
|
15
|
+
});
|
|
16
|
+
async function runWorkflowDocument(document, options) {
|
|
17
|
+
const signal = options.signal ?? new AbortController().signal;
|
|
18
|
+
const createDocumentRunId = options.createDocumentRunId;
|
|
19
|
+
const createCaseRunId = options.createCaseRunId;
|
|
20
|
+
const projectName = options.project?.name ?? document.projectId;
|
|
21
|
+
const retry = options.retry ?? options.project?.retry ?? 0;
|
|
22
|
+
if (!Number.isInteger(retry) || retry < 0) throw new TypeError('Workflow document retry must be a non-negative integer.');
|
|
23
|
+
const runtime = createDocumentRuntime(document, {
|
|
24
|
+
documentSetup: options.documentSetup,
|
|
25
|
+
documentAttemptIndex: options.documentAttemptIndex,
|
|
26
|
+
resolveNode: options.resolveNode,
|
|
27
|
+
project: options.project,
|
|
28
|
+
projectContext: options.projectContext,
|
|
29
|
+
signal,
|
|
30
|
+
defaultTimeoutMs: options.defaultTimeoutMs,
|
|
31
|
+
onStepStart: options.onStepStart,
|
|
32
|
+
onStepResult: options.onStepResult,
|
|
33
|
+
onResult: async (result)=>{
|
|
34
|
+
await options.documentSetup?.onDocumentResult?.(result, runtime.context);
|
|
35
|
+
await options.onDocumentResult?.(result);
|
|
36
|
+
},
|
|
37
|
+
createDocumentRunId: createDocumentRunId ? ()=>createDocumentRunId(document) : void 0
|
|
38
|
+
});
|
|
39
|
+
const cases = [];
|
|
40
|
+
let runtimeStarted = false;
|
|
41
|
+
let documentResult;
|
|
42
|
+
const executionErrors = [];
|
|
43
|
+
let fatalError = false;
|
|
44
|
+
let stoppedByCase = false;
|
|
45
|
+
try {
|
|
46
|
+
runtimeStarted = true;
|
|
47
|
+
const startedDocument = await runtime.start();
|
|
48
|
+
if (runtime.canRunCases) for (const collectedCase of document.cases){
|
|
49
|
+
if (stoppedByCase || fatalError || signal.aborted || options.shouldStop?.()) {
|
|
50
|
+
const outcome = asNotRun(collectedCase, projectName, signal.aborted ? options.stopReason?.() ?? 'interrupted' : fatalError ? 'fatal-error' : stoppedByCase ? 'bail' : options.stopReason?.() ?? 'interrupted');
|
|
51
|
+
cases.push(outcome);
|
|
52
|
+
await options.onCaseOutcome?.(outcome);
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
await options.onCaseStart?.(collectedCase);
|
|
56
|
+
const attempts = [];
|
|
57
|
+
for(let attemptIndex = 0; attemptIndex <= retry; attemptIndex += 1){
|
|
58
|
+
let attemptFailure;
|
|
59
|
+
const run = await runCollectedCase(collectedCase, {
|
|
60
|
+
resolveNode: options.resolveNode,
|
|
61
|
+
beforeEach: document.lifecycle.beforeEach,
|
|
62
|
+
afterEach: document.lifecycle.afterEach,
|
|
63
|
+
context: runtime.context,
|
|
64
|
+
projectName,
|
|
65
|
+
attemptIndex,
|
|
66
|
+
signal: runtime.signal,
|
|
67
|
+
defaultTimeoutMs: options.defaultTimeoutMs,
|
|
68
|
+
onStepStart: options.onStepStart,
|
|
69
|
+
onStepResult: options.onStepResult,
|
|
70
|
+
onResult: options.onCaseResult,
|
|
71
|
+
reportScopeId: options.resolveCaseReportScopeId?.(collectedCase, attemptIndex, startedDocument.documentRunId),
|
|
72
|
+
createRunId: createCaseRunId ? ()=>createCaseRunId(collectedCase, attemptIndex) : void 0
|
|
73
|
+
}).catch((error)=>{
|
|
74
|
+
if (!(error instanceof WorkflowExecutionFailure)) throw error;
|
|
75
|
+
attemptFailure = error;
|
|
76
|
+
return attemptFailure.result;
|
|
77
|
+
});
|
|
78
|
+
attempts.push(run);
|
|
79
|
+
if (attemptFailure) {
|
|
80
|
+
cases.push({
|
|
81
|
+
caseId: collectedCase.caseId,
|
|
82
|
+
projectName,
|
|
83
|
+
name: collectedCase.definition.name,
|
|
84
|
+
sourcePath: collectedCase.sourcePath,
|
|
85
|
+
caseIndex: collectedCase.caseIndex,
|
|
86
|
+
...collectedCase.definition.onFailure ? {
|
|
87
|
+
onFailure: collectedCase.definition.onFailure
|
|
88
|
+
} : {},
|
|
89
|
+
status: 'failed',
|
|
90
|
+
run,
|
|
91
|
+
attempts
|
|
92
|
+
});
|
|
93
|
+
throw attemptFailure;
|
|
94
|
+
}
|
|
95
|
+
fatalError = options.isFatalError?.(run) ?? false;
|
|
96
|
+
if ('success' === run.status || !!run.teardownErrors?.length || fatalError || signal.aborted || options.shouldStop?.()) break;
|
|
97
|
+
}
|
|
98
|
+
const run = attempts.at(-1);
|
|
99
|
+
const outcome = {
|
|
100
|
+
caseId: collectedCase.caseId,
|
|
101
|
+
projectName,
|
|
102
|
+
name: collectedCase.definition.name,
|
|
103
|
+
sourcePath: collectedCase.sourcePath,
|
|
104
|
+
caseIndex: collectedCase.caseIndex,
|
|
105
|
+
...collectedCase.definition.onFailure ? {
|
|
106
|
+
onFailure: collectedCase.definition.onFailure
|
|
107
|
+
} : {},
|
|
108
|
+
status: run.status,
|
|
109
|
+
run,
|
|
110
|
+
attempts
|
|
111
|
+
};
|
|
112
|
+
cases.push(outcome);
|
|
113
|
+
stoppedByCase = 'failed' === outcome.status && 'stop-document' === collectedCase.definition.onFailure;
|
|
114
|
+
await options.onCaseOutcome?.(outcome);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
const reason = signal.aborted ? options.stopReason?.() ?? 'interrupted' : 'document-start-failed';
|
|
118
|
+
cases.push(...document.cases.map((collectedCase)=>asNotRun(collectedCase, projectName, reason)));
|
|
119
|
+
}
|
|
120
|
+
} catch (error) {
|
|
121
|
+
executionErrors.push(...error instanceof WorkflowExecutionFailure ? error.errors : [
|
|
122
|
+
error
|
|
123
|
+
]);
|
|
124
|
+
} finally{
|
|
125
|
+
if (runtimeStarted) try {
|
|
126
|
+
documentResult = await runtime.finish();
|
|
127
|
+
} catch (error) {
|
|
128
|
+
if (error instanceof WorkflowExecutionFailure) {
|
|
129
|
+
documentResult = error.result;
|
|
130
|
+
for (const failure of error.errors)if (!executionErrors.includes(failure)) executionErrors.push(failure);
|
|
131
|
+
} else executionErrors.push(error);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (!documentResult) {
|
|
135
|
+
if (executionErrors.length) throw new AggregateError(executionErrors, 'Workflow execution did not produce a document result.');
|
|
136
|
+
throw new Error(`Workflow document "${document.sourcePath}" did not produce a result.`);
|
|
137
|
+
}
|
|
138
|
+
if (executionErrors.length) {
|
|
139
|
+
const completed = new Set(cases.map((outcome)=>outcome.caseId));
|
|
140
|
+
cases.push(...document.cases.filter((item)=>!completed.has(item.caseId)).map((item)=>asNotRun(item, projectName, 'interrupted')));
|
|
141
|
+
documentResult.status = 'failed';
|
|
142
|
+
documentResult.executionErrors = executionErrors.map(asExecutionError);
|
|
143
|
+
throw new WorkflowExecutionFailure({
|
|
144
|
+
document: documentResult,
|
|
145
|
+
cases
|
|
146
|
+
}, executionErrors);
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
document: documentResult,
|
|
150
|
+
cases
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
export { runWorkflowDocument };
|
|
154
|
+
|
|
155
|
+
//# sourceMappingURL=run-workflow-document.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-runner/engine/run-workflow-document.mjs","sources":["../../../../src/test-runner/engine/run-workflow-document.ts"],"sourcesContent":["import type { CollectedCase, CollectedWorkflowDocument } from '../parser/types';\nimport { createDocumentRuntime } from './document-runtime';\nimport {\n WorkflowExecutionFailure,\n asExecutionError,\n} from './execution-failure';\nimport { runCollectedCase } from './run-collected-case';\nimport type {\n CaseRunOutcome,\n CaseRunResult,\n RunWorkflowDocumentOptions,\n WorkflowDocumentExecutionResult,\n WorkflowDocumentRunResult,\n} from './types';\n\nconst asNotRun = (\n collectedCase: CollectedCase,\n projectName: string,\n reason: NonNullable<CaseRunOutcome['notRunReason']>,\n): CaseRunOutcome => ({\n caseId: collectedCase.caseId,\n projectName,\n name: collectedCase.definition.name,\n sourcePath: collectedCase.sourcePath,\n caseIndex: collectedCase.caseIndex,\n ...(collectedCase.definition.onFailure\n ? { onFailure: collectedCase.definition.onFailure }\n : {}),\n status: 'not-run',\n notRunReason: reason,\n});\n\nexport async function runWorkflowDocument<TContext = undefined>(\n document: CollectedWorkflowDocument,\n options: RunWorkflowDocumentOptions<TContext>,\n): Promise<WorkflowDocumentExecutionResult> {\n const signal = options.signal ?? new AbortController().signal;\n const createDocumentRunId = options.createDocumentRunId;\n const createCaseRunId = options.createCaseRunId;\n const projectName = options.project?.name ?? document.projectId;\n const retry = options.retry ?? options.project?.retry ?? 0;\n if (!Number.isInteger(retry) || retry < 0) {\n throw new TypeError(\n 'Workflow document retry must be a non-negative integer.',\n );\n }\n const runtime = createDocumentRuntime(document, {\n documentSetup: options.documentSetup,\n documentAttemptIndex: options.documentAttemptIndex,\n resolveNode: options.resolveNode,\n project: options.project,\n projectContext: options.projectContext,\n signal,\n defaultTimeoutMs: options.defaultTimeoutMs,\n onStepStart: options.onStepStart,\n onStepResult: options.onStepResult,\n onResult: async (result) => {\n await options.documentSetup?.onDocumentResult?.(result, runtime.context);\n await options.onDocumentResult?.(result);\n },\n createDocumentRunId: createDocumentRunId\n ? () => createDocumentRunId(document)\n : undefined,\n });\n const cases: CaseRunOutcome[] = [];\n let runtimeStarted = false;\n let documentResult: WorkflowDocumentRunResult | undefined;\n const executionErrors: unknown[] = [];\n let fatalError = false;\n let stoppedByCase = false;\n\n try {\n runtimeStarted = true;\n const startedDocument = await runtime.start();\n\n if (!runtime.canRunCases) {\n const reason = signal.aborted\n ? (options.stopReason?.() ?? 'interrupted')\n : 'document-start-failed';\n cases.push(\n ...document.cases.map((collectedCase) =>\n asNotRun(collectedCase, projectName, reason),\n ),\n );\n } else {\n for (const collectedCase of document.cases) {\n if (\n stoppedByCase ||\n fatalError ||\n signal.aborted ||\n options.shouldStop?.()\n ) {\n const outcome = asNotRun(\n collectedCase,\n projectName,\n signal.aborted\n ? (options.stopReason?.() ?? 'interrupted')\n : fatalError\n ? 'fatal-error'\n : stoppedByCase\n ? 'bail'\n : (options.stopReason?.() ?? 'interrupted'),\n );\n cases.push(outcome);\n await options.onCaseOutcome?.(outcome);\n continue;\n }\n\n await options.onCaseStart?.(collectedCase);\n const attempts = [];\n for (let attemptIndex = 0; attemptIndex <= retry; attemptIndex += 1) {\n let attemptFailure:\n | WorkflowExecutionFailure<CaseRunResult>\n | undefined;\n const run = await runCollectedCase(collectedCase, {\n resolveNode: options.resolveNode,\n beforeEach: document.lifecycle.beforeEach,\n afterEach: document.lifecycle.afterEach,\n context: runtime.context,\n projectName,\n attemptIndex,\n signal: runtime.signal,\n defaultTimeoutMs: options.defaultTimeoutMs,\n onStepStart: options.onStepStart,\n onStepResult: options.onStepResult,\n onResult: options.onCaseResult,\n reportScopeId: options.resolveCaseReportScopeId?.(\n collectedCase,\n attemptIndex,\n startedDocument.documentRunId,\n ),\n createRunId: createCaseRunId\n ? () => createCaseRunId(collectedCase, attemptIndex)\n : undefined,\n }).catch((error: unknown) => {\n if (!(error instanceof WorkflowExecutionFailure)) throw error;\n attemptFailure = error as WorkflowExecutionFailure<CaseRunResult>;\n return attemptFailure.result;\n });\n attempts.push(run);\n if (attemptFailure) {\n cases.push({\n caseId: collectedCase.caseId,\n projectName,\n name: collectedCase.definition.name,\n sourcePath: collectedCase.sourcePath,\n caseIndex: collectedCase.caseIndex,\n ...(collectedCase.definition.onFailure\n ? { onFailure: collectedCase.definition.onFailure }\n : {}),\n status: 'failed',\n run,\n attempts,\n });\n throw attemptFailure;\n }\n fatalError = options.isFatalError?.(run) ?? false;\n if (\n run.status === 'success' ||\n // Retrying cannot repair cleanup/report publication and would\n // replay actions that may already have completed successfully.\n !!run.teardownErrors?.length ||\n fatalError ||\n signal.aborted ||\n options.shouldStop?.()\n )\n break;\n }\n const run = attempts.at(-1)!;\n const outcome: CaseRunOutcome = {\n caseId: collectedCase.caseId,\n projectName,\n name: collectedCase.definition.name,\n sourcePath: collectedCase.sourcePath,\n caseIndex: collectedCase.caseIndex,\n ...(collectedCase.definition.onFailure\n ? { onFailure: collectedCase.definition.onFailure }\n : {}),\n status: run.status,\n run,\n attempts,\n };\n cases.push(outcome);\n stoppedByCase =\n outcome.status === 'failed' &&\n collectedCase.definition.onFailure === 'stop-document';\n await options.onCaseOutcome?.(outcome);\n }\n }\n } catch (error) {\n executionErrors.push(\n ...(error instanceof WorkflowExecutionFailure ? error.errors : [error]),\n );\n } finally {\n if (runtimeStarted) {\n try {\n documentResult = await runtime.finish();\n } catch (error) {\n if (error instanceof WorkflowExecutionFailure) {\n documentResult = error.result as WorkflowDocumentRunResult;\n for (const failure of error.errors)\n if (!executionErrors.includes(failure))\n executionErrors.push(failure);\n } else executionErrors.push(error);\n }\n }\n }\n\n if (!documentResult) {\n if (executionErrors.length)\n throw new AggregateError(\n executionErrors,\n 'Workflow execution did not produce a document result.',\n );\n throw new Error(\n `Workflow document \"${document.sourcePath}\" did not produce a result.`,\n );\n }\n if (executionErrors.length) {\n const completed = new Set(cases.map((outcome) => outcome.caseId));\n cases.push(\n ...document.cases\n .filter((item) => !completed.has(item.caseId))\n .map((item) => asNotRun(item, projectName, 'interrupted')),\n );\n documentResult.status = 'failed';\n documentResult.executionErrors = executionErrors.map(asExecutionError);\n throw new WorkflowExecutionFailure(\n { document: documentResult, cases },\n executionErrors,\n );\n }\n return { document: documentResult, cases };\n}\n"],"names":["asNotRun","collectedCase","projectName","reason","runWorkflowDocument","document","options","signal","AbortController","createDocumentRunId","createCaseRunId","retry","Number","TypeError","runtime","createDocumentRuntime","result","undefined","cases","runtimeStarted","documentResult","executionErrors","fatalError","stoppedByCase","startedDocument","outcome","attempts","attemptIndex","attemptFailure","run","runCollectedCase","error","WorkflowExecutionFailure","failure","AggregateError","Error","completed","Set","item","asExecutionError"],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
async function runDocumentAttempts(options, run) {
|
|
2
|
+
for(let attemptIndex = 0; attemptIndex <= options.retry; attemptIndex++){
|
|
3
|
+
if (options.signal.aborted || options.shouldStop()) return;
|
|
4
|
+
const status = await run(attemptIndex);
|
|
5
|
+
if ('failed' !== status) return;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
async function runConcurrentJobs(items, options, run) {
|
|
9
|
+
let next = 0;
|
|
10
|
+
const worker = async ()=>{
|
|
11
|
+
while(next < items.length && !options.shouldStop()){
|
|
12
|
+
const index = next++;
|
|
13
|
+
await run(items[index], index);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const workers = await Promise.allSettled(Array.from({
|
|
17
|
+
length: Math.min(options.concurrency, items.length)
|
|
18
|
+
}, worker));
|
|
19
|
+
const errors = workers.flatMap((result)=>'rejected' === result.status ? [
|
|
20
|
+
result.reason
|
|
21
|
+
] : []);
|
|
22
|
+
if (1 === errors.length) throw errors[0];
|
|
23
|
+
if (errors.length) throw new AggregateError(errors, 'Document scheduling failed');
|
|
24
|
+
}
|
|
25
|
+
export { runConcurrentJobs, runDocumentAttempts };
|
|
26
|
+
|
|
27
|
+
//# sourceMappingURL=scheduler.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-runner/engine/scheduler.mjs","sources":["../../../../src/test-runner/engine/scheduler.ts"],"sourcesContent":["/** A rejected attempt is an infrastructure failure and is never replayed. */\nexport async function runDocumentAttempts(\n options: { retry: number; signal: AbortSignal; shouldStop(): boolean },\n run: (attemptIndex: number) => Promise<'success' | 'failed' | undefined>,\n): Promise<void> {\n for (let attemptIndex = 0; attemptIndex <= options.retry; attemptIndex++) {\n if (options.signal.aborted || options.shouldStop()) return;\n const status = await run(attemptIndex);\n if (status !== 'failed') return;\n }\n}\n\n/** Ordered admission, bounded concurrency, results in invocation order. */\nexport async function runConcurrentJobs<T>(\n items: readonly T[],\n options: { concurrency: number; shouldStop(): boolean },\n run: (item: T, index: number) => Promise<void>,\n): Promise<void> {\n let next = 0;\n const worker = async () => {\n while (next < items.length && !options.shouldStop()) {\n const index = next++;\n await run(items[index], index);\n }\n };\n const workers = await Promise.allSettled(\n Array.from({ length: Math.min(options.concurrency, items.length) }, worker),\n );\n const errors = workers.flatMap((result) =>\n result.status === 'rejected' ? [result.reason] : [],\n );\n if (errors.length === 1) throw errors[0];\n if (errors.length)\n throw new AggregateError(errors, 'Document scheduling failed');\n}\n"],"names":["runDocumentAttempts","options","run","attemptIndex","status","runConcurrentJobs","items","next","worker","index","workers","Promise","Array","Math","errors","result","AggregateError"],"mappings":"AACO,eAAeA,oBACpBC,OAAsE,EACtEC,GAAwE;IAExE,IAAK,IAAIC,eAAe,GAAGA,gBAAgBF,QAAQ,KAAK,EAAEE,eAAgB;QACxE,IAAIF,QAAQ,MAAM,CAAC,OAAO,IAAIA,QAAQ,UAAU,IAAI;QACpD,MAAMG,SAAS,MAAMF,IAAIC;QACzB,IAAIC,AAAW,aAAXA,QAAqB;IAC3B;AACF;AAGO,eAAeC,kBACpBC,KAAmB,EACnBL,OAAuD,EACvDC,GAA8C;IAE9C,IAAIK,OAAO;IACX,MAAMC,SAAS;QACb,MAAOD,OAAOD,MAAM,MAAM,IAAI,CAACL,QAAQ,UAAU,GAAI;YACnD,MAAMQ,QAAQF;YACd,MAAML,IAAII,KAAK,CAACG,MAAM,EAAEA;QAC1B;IACF;IACA,MAAMC,UAAU,MAAMC,QAAQ,UAAU,CACtCC,MAAM,IAAI,CAAC;QAAE,QAAQC,KAAK,GAAG,CAACZ,QAAQ,WAAW,EAAEK,MAAM,MAAM;IAAE,GAAGE;IAEtE,MAAMM,SAASJ,QAAQ,OAAO,CAAC,CAACK,SAC9BA,AAAkB,eAAlBA,OAAO,MAAM,GAAkB;YAACA,OAAO,MAAM;SAAC,GAAG,EAAE;IAErD,IAAID,AAAkB,MAAlBA,OAAO,MAAM,EAAQ,MAAMA,MAAM,CAAC,EAAE;IACxC,IAAIA,OAAO,MAAM,EACf,MAAM,IAAIE,eAAeF,QAAQ;AACrC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { isAbsolute } from "node:path";
|
|
2
|
+
const reportPathsFromTeardown = (result)=>{
|
|
3
|
+
if (void 0 === result) return [];
|
|
4
|
+
if ('object' != typeof result || null === result || Array.isArray(result)) throw new TypeError('Node teardown result must be an object or undefined.');
|
|
5
|
+
const paths = result.reportPaths;
|
|
6
|
+
if (void 0 === paths) return [];
|
|
7
|
+
if (!Array.isArray(paths)) throw new TypeError('Node teardown reportPaths must be an array.');
|
|
8
|
+
return paths.map((path, index)=>{
|
|
9
|
+
if ('string' != typeof path || 0 === path.trim().length) throw new TypeError(`Node teardown reportPaths[${index}] must be a non-empty string.`);
|
|
10
|
+
if (!isAbsolute(path)) throw new TypeError(`Node teardown reportPaths[${index}] must be an absolute path.`);
|
|
11
|
+
return path;
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
export { reportPathsFromTeardown };
|
|
15
|
+
|
|
16
|
+
//# sourceMappingURL=scope-teardown.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-runner/engine/scope-teardown.mjs","sources":["../../../../src/test-runner/engine/scope-teardown.ts"],"sourcesContent":["import { isAbsolute } from 'node:path';\nimport type { NodeScopeTeardownResult } from './types';\n\nexport const reportPathsFromTeardown = (\n // biome-ignore lint/suspicious/noConfusingVoidType: this consumes the intentional void teardown return.\n result: NodeScopeTeardownResult | void,\n): readonly string[] => {\n if (result === undefined) return [];\n if (typeof result !== 'object' || result === null || Array.isArray(result)) {\n throw new TypeError('Node teardown result must be an object or undefined.');\n }\n const paths = result.reportPaths;\n if (paths === undefined) return [];\n if (!Array.isArray(paths)) {\n throw new TypeError('Node teardown reportPaths must be an array.');\n }\n return paths.map((path, index) => {\n if (typeof path !== 'string' || path.trim().length === 0) {\n throw new TypeError(\n `Node teardown reportPaths[${index}] must be a non-empty string.`,\n );\n }\n if (!isAbsolute(path)) {\n throw new TypeError(\n `Node teardown reportPaths[${index}] must be an absolute path.`,\n );\n }\n return path;\n });\n};\n"],"names":["reportPathsFromTeardown","result","undefined","Array","TypeError","paths","path","index","isAbsolute"],"mappings":";AAGO,MAAMA,0BAA0B,CAErCC;IAEA,IAAIA,AAAWC,WAAXD,QAAsB,OAAO,EAAE;IACnC,IAAI,AAAkB,YAAlB,OAAOA,UAAuBA,AAAW,SAAXA,UAAmBE,MAAM,OAAO,CAACF,SACjE,MAAM,IAAIG,UAAU;IAEtB,MAAMC,QAAQJ,OAAO,WAAW;IAChC,IAAII,AAAUH,WAAVG,OAAqB,OAAO,EAAE;IAClC,IAAI,CAACF,MAAM,OAAO,CAACE,QACjB,MAAM,IAAID,UAAU;IAEtB,OAAOC,MAAM,GAAG,CAAC,CAACC,MAAMC;QACtB,IAAI,AAAgB,YAAhB,OAAOD,QAAqBA,AAAuB,MAAvBA,KAAK,IAAI,GAAG,MAAM,EAChD,MAAM,IAAIF,UACR,CAAC,0BAA0B,EAAEG,MAAM,6BAA6B,CAAC;QAGrE,IAAI,CAACC,WAAWF,OACd,MAAM,IAAIF,UACR,CAAC,0BAA0B,EAAEG,MAAM,2BAA2B,CAAC;QAGnE,OAAOD;IACT;AACF"}
|
|
File without changes
|