@heal-dev/heal-playwright-tracer 1.0.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/LICENSE +661 -0
- package/README.md +245 -0
- package/dist/application/babel-playwright-tracer-plugin/index.d.ts +16 -0
- package/dist/application/babel-playwright-tracer-plugin/index.js +111 -0
- package/dist/application/heal-config/index.d.ts +8 -0
- package/dist/application/heal-config/index.js +22 -0
- package/dist/application/heal-config/registry.d.ts +37 -0
- package/dist/application/heal-config/registry.js +64 -0
- package/dist/application/heal-config/types.d.ts +73 -0
- package/dist/application/heal-config/types.js +7 -0
- package/dist/application/playwright-fixture/index.d.ts +14 -0
- package/dist/application/playwright-fixture/index.js +234 -0
- package/dist/application/trace-event-recorder-runtime/index.d.ts +15 -0
- package/dist/application/trace-event-recorder-runtime/index.js +68 -0
- package/dist/domain/code-hook-injector/service/meta-fields/enclosing-scope-labeler.d.ts +12 -0
- package/dist/domain/code-hook-injector/service/meta-fields/enclosing-scope-labeler.js +53 -0
- package/dist/domain/code-hook-injector/service/meta-fields/leading-comment-extractor.d.ts +14 -0
- package/dist/domain/code-hook-injector/service/meta-fields/leading-comment-extractor.js +20 -0
- package/dist/domain/code-hook-injector/service/meta-fields/relative-file-path.d.ts +6 -0
- package/dist/domain/code-hook-injector/service/meta-fields/relative-file-path.js +57 -0
- package/dist/domain/code-hook-injector/service/meta-fields/source-snippet-extractor.d.ts +12 -0
- package/dist/domain/code-hook-injector/service/meta-fields/source-snippet-extractor.js +28 -0
- package/dist/domain/code-hook-injector/service/playwright-import-rewriter.d.ts +10 -0
- package/dist/domain/code-hook-injector/service/playwright-import-rewriter.js +21 -0
- package/dist/domain/code-hook-injector/service/statement-analysis/cjs-artifact-detector.d.ts +14 -0
- package/dist/domain/code-hook-injector/service/statement-analysis/cjs-artifact-detector.js +30 -0
- package/dist/domain/code-hook-injector/service/statement-analysis/for-head-declaration-detector.d.ts +10 -0
- package/dist/domain/code-hook-injector/service/statement-analysis/for-head-declaration-detector.js +18 -0
- package/dist/domain/code-hook-injector/service/statement-analysis/leaf-statement-classifier.d.ts +15 -0
- package/dist/domain/code-hook-injector/service/statement-analysis/leaf-statement-classifier.js +66 -0
- package/dist/domain/code-hook-injector/service/statement-analysis/non-wrappable-statement.d.ts +11 -0
- package/dist/domain/code-hook-injector/service/statement-analysis/non-wrappable-statement.js +20 -0
- package/dist/domain/code-hook-injector/service/trace-hook/enter-meta-literal.d.ts +20 -0
- package/dist/domain/code-hook-injector/service/trace-hook/enter-meta-literal.js +34 -0
- package/dist/domain/code-hook-injector/service/trace-hook/global-trace-call.d.ts +10 -0
- package/dist/domain/code-hook-injector/service/trace-hook/global-trace-call.js +16 -0
- package/dist/domain/code-hook-injector/service/trace-hook/try-finally-wrapper.d.ts +18 -0
- package/dist/domain/code-hook-injector/service/trace-hook/try-finally-wrapper.js +44 -0
- package/dist/domain/code-hook-injector/service/trace-hook/variable-declaration-hoister.d.ts +20 -0
- package/dist/domain/code-hook-injector/service/trace-hook/variable-declaration-hoister.js +27 -0
- package/dist/domain/code-hook-injector/service/traced-file-matcher.d.ts +10 -0
- package/dist/domain/code-hook-injector/service/traced-file-matcher.js +26 -0
- package/dist/domain/trace-event-recorder/model/enter-meta.d.ts +24 -0
- package/dist/domain/trace-event-recorder/model/enter-meta.js +7 -0
- package/dist/domain/trace-event-recorder/model/global-names.d.ts +8 -0
- package/dist/domain/trace-event-recorder/model/global-names.js +20 -0
- package/dist/domain/trace-event-recorder/model/serialized-error.d.ts +16 -0
- package/dist/domain/trace-event-recorder/model/serialized-error.js +7 -0
- package/dist/domain/trace-event-recorder/model/statement-trace-schema.d.ts +171 -0
- package/dist/domain/trace-event-recorder/model/statement-trace-schema.js +33 -0
- package/dist/domain/trace-event-recorder/model/trace-schema.d.ts +114 -0
- package/dist/domain/trace-event-recorder/model/trace-schema.js +16 -0
- package/dist/domain/trace-event-recorder/port/clock.d.ts +9 -0
- package/dist/domain/trace-event-recorder/port/clock.js +7 -0
- package/dist/domain/trace-event-recorder/port/heal-trace-exporter.d.ts +11 -0
- package/dist/domain/trace-event-recorder/port/heal-trace-exporter.js +7 -0
- package/dist/domain/trace-event-recorder/port/system-info-provider.d.ts +18 -0
- package/dist/domain/trace-event-recorder/port/system-info-provider.js +7 -0
- package/dist/domain/trace-event-recorder/port/trace-event-consumer.d.ts +11 -0
- package/dist/domain/trace-event-recorder/port/trace-event-consumer.js +7 -0
- package/dist/domain/trace-event-recorder/service/active-enter-stack.d.ts +15 -0
- package/dist/domain/trace-event-recorder/service/active-enter-stack.js +34 -0
- package/dist/domain/trace-event-recorder/service/event-builders/enter-event-builder.d.ts +8 -0
- package/dist/domain/trace-event-recorder/service/event-builders/enter-event-builder.js +37 -0
- package/dist/domain/trace-event-recorder/service/event-builders/meta-event-builder.d.ts +7 -0
- package/dist/domain/trace-event-recorder/service/event-builders/meta-event-builder.js +19 -0
- package/dist/domain/trace-event-recorder/service/event-builders/ok-event-builder.d.ts +7 -0
- package/dist/domain/trace-event-recorder/service/event-builders/ok-event-builder.js +27 -0
- package/dist/domain/trace-event-recorder/service/event-builders/throw-event-builder.d.ts +7 -0
- package/dist/domain/trace-event-recorder/service/event-builders/throw-event-builder.js +23 -0
- package/dist/domain/trace-event-recorder/service/exporters/composite-heal-trace-exporter.d.ts +12 -0
- package/dist/domain/trace-event-recorder/service/exporters/composite-heal-trace-exporter.js +32 -0
- package/dist/domain/trace-event-recorder/service/index.d.ts +10 -0
- package/dist/domain/trace-event-recorder/service/index.js +15 -0
- package/dist/domain/trace-event-recorder/service/projectors/index.d.ts +6 -0
- package/dist/domain/trace-event-recorder/service/projectors/index.js +10 -0
- package/dist/domain/trace-event-recorder/service/projectors/statement-projector.d.ts +26 -0
- package/dist/domain/trace-event-recorder/service/projectors/statement-projector.js +183 -0
- package/dist/domain/trace-event-recorder/service/serializers/error-serializer.d.ts +8 -0
- package/dist/domain/trace-event-recorder/service/serializers/error-serializer.js +49 -0
- package/dist/domain/trace-event-recorder/service/serializers/variable-snapshot-serializer.d.ts +7 -0
- package/dist/domain/trace-event-recorder/service/serializers/variable-snapshot-serializer.js +102 -0
- package/dist/domain/trace-event-recorder/service/trace-event-recorder-state.d.ts +19 -0
- package/dist/domain/trace-event-recorder/service/trace-event-recorder-state.js +7 -0
- package/dist/domain/trace-event-recorder/service/trace-event-recorder.d.ts +56 -0
- package/dist/domain/trace-event-recorder/service/trace-event-recorder.js +80 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +43 -0
- package/dist/infrastructure/ndjson-exporter-adapter/index.d.ts +6 -0
- package/dist/infrastructure/ndjson-exporter-adapter/index.js +10 -0
- package/dist/infrastructure/ndjson-exporter-adapter/ndjson-exporter.d.ts +13 -0
- package/dist/infrastructure/ndjson-exporter-adapter/ndjson-exporter.js +77 -0
- package/dist/infrastructure/perf-hooks-clock-adapter/index.d.ts +6 -0
- package/dist/infrastructure/perf-hooks-clock-adapter/index.js +10 -0
- package/dist/infrastructure/perf-hooks-clock-adapter/perf-hooks-clock.d.ts +11 -0
- package/dist/infrastructure/perf-hooks-clock-adapter/perf-hooks-clock.js +22 -0
- package/dist/infrastructure/playwright-locator-screenshot-adapter/assertion-wrapper.d.ts +6 -0
- package/dist/infrastructure/playwright-locator-screenshot-adapter/assertion-wrapper.js +109 -0
- package/dist/infrastructure/playwright-locator-screenshot-adapter/index.d.ts +9 -0
- package/dist/infrastructure/playwright-locator-screenshot-adapter/index.js +21 -0
- package/dist/infrastructure/playwright-locator-screenshot-adapter/locator-patch.d.ts +11 -0
- package/dist/infrastructure/playwright-locator-screenshot-adapter/locator-patch.js +79 -0
- package/dist/infrastructure/playwright-locator-screenshot-adapter/overlay-helpers.d.ts +15 -0
- package/dist/infrastructure/playwright-locator-screenshot-adapter/overlay-helpers.js +33 -0
- package/dist/infrastructure/playwright-locator-screenshot-adapter/screenshot-capture-session.d.ts +26 -0
- package/dist/infrastructure/playwright-locator-screenshot-adapter/screenshot-capture-session.js +125 -0
- package/dist/infrastructure/playwright-step-tracking-adapter/index.d.ts +7 -0
- package/dist/infrastructure/playwright-step-tracking-adapter/index.js +10 -0
- package/dist/infrastructure/playwright-step-tracking-adapter/playwright-step-tracking-adapter.d.ts +14 -0
- package/dist/infrastructure/playwright-step-tracking-adapter/playwright-step-tracking-adapter.js +51 -0
- package/dist/infrastructure/playwright-test-context-adapter/heal-tag-prefix.d.ts +25 -0
- package/dist/infrastructure/playwright-test-context-adapter/heal-tag-prefix.js +28 -0
- package/dist/infrastructure/playwright-test-context-adapter/index.d.ts +8 -0
- package/dist/infrastructure/playwright-test-context-adapter/index.js +12 -0
- package/dist/infrastructure/playwright-test-context-adapter/playwright-test-context-adapter.d.ts +19 -0
- package/dist/infrastructure/playwright-test-context-adapter/playwright-test-context-adapter.js +43 -0
- package/dist/infrastructure/stdout-capture-adapter/index.d.ts +7 -0
- package/dist/infrastructure/stdout-capture-adapter/index.js +10 -0
- package/dist/infrastructure/stdout-capture-adapter/stdout-capture-session.d.ts +20 -0
- package/dist/infrastructure/stdout-capture-adapter/stdout-capture-session.js +47 -0
- package/dist/infrastructure/system-info-adapter/index.d.ts +6 -0
- package/dist/infrastructure/system-info-adapter/index.js +10 -0
- package/dist/infrastructure/system-info-adapter/system-info-adapter.d.ts +12 -0
- package/dist/infrastructure/system-info-adapter/system-info-adapter.js +83 -0
- package/package.json +95 -0
package/dist/domain/code-hook-injector/service/statement-analysis/leaf-statement-classifier.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright: (c) Myia SAS 2026.
|
|
3
|
+
* This file and its contents are licensed under the AGPLv3 License.
|
|
4
|
+
* Please see the LICENSE file at the root of this repository
|
|
5
|
+
*/
|
|
6
|
+
import type * as BabelTypes from '@babel/types';
|
|
7
|
+
type Types = typeof BabelTypes;
|
|
8
|
+
type Node = BabelTypes.Node;
|
|
9
|
+
export interface LeafStatementClassifier {
|
|
10
|
+
isLeafStatement: (node: Node) => boolean;
|
|
11
|
+
kindOf: (node: Node) => string;
|
|
12
|
+
containsAwait: (node: Node) => boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function createLeafStatementClassifier(t: Types): LeafStatementClassifier;
|
|
15
|
+
export {};
|
package/dist/domain/code-hook-injector/service/statement-analysis/leaf-statement-classifier.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright: (c) Myia SAS 2026.
|
|
4
|
+
* This file and its contents are licensed under the AGPLv3 License.
|
|
5
|
+
* Please see the LICENSE file at the root of this repository
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.createLeafStatementClassifier = createLeafStatementClassifier;
|
|
9
|
+
function createLeafStatementClassifier(t) {
|
|
10
|
+
const isLeafStatement = (node) => t.isExpressionStatement(node) ||
|
|
11
|
+
t.isVariableDeclaration(node) ||
|
|
12
|
+
t.isReturnStatement(node) ||
|
|
13
|
+
t.isThrowStatement(node) ||
|
|
14
|
+
t.isBreakStatement(node) ||
|
|
15
|
+
t.isContinueStatement(node) ||
|
|
16
|
+
t.isDebuggerStatement(node);
|
|
17
|
+
const kindOf = (node) => {
|
|
18
|
+
if (t.isExpressionStatement(node))
|
|
19
|
+
return 'expression';
|
|
20
|
+
if (t.isVariableDeclaration(node))
|
|
21
|
+
return 'variable';
|
|
22
|
+
if (t.isReturnStatement(node))
|
|
23
|
+
return 'return';
|
|
24
|
+
if (t.isThrowStatement(node))
|
|
25
|
+
return 'throw';
|
|
26
|
+
if (t.isBreakStatement(node))
|
|
27
|
+
return 'break';
|
|
28
|
+
if (t.isContinueStatement(node))
|
|
29
|
+
return 'continue';
|
|
30
|
+
if (t.isDebuggerStatement(node))
|
|
31
|
+
return 'debugger';
|
|
32
|
+
return node.type;
|
|
33
|
+
};
|
|
34
|
+
const containsAwait = (node) => {
|
|
35
|
+
let found = false;
|
|
36
|
+
const walk = (n) => {
|
|
37
|
+
if (!n || found || typeof n !== 'object')
|
|
38
|
+
return;
|
|
39
|
+
const asNode = n;
|
|
40
|
+
if (t.isAwaitExpression(asNode)) {
|
|
41
|
+
found = true;
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (t.isFunction(asNode))
|
|
45
|
+
return;
|
|
46
|
+
for (const key of Object.keys(asNode)) {
|
|
47
|
+
if (key === 'loc' || key === 'type' || key === 'start' || key === 'end')
|
|
48
|
+
continue;
|
|
49
|
+
const v = asNode[key];
|
|
50
|
+
if (v == null)
|
|
51
|
+
continue;
|
|
52
|
+
if (Array.isArray(v)) {
|
|
53
|
+
for (const item of v)
|
|
54
|
+
if (item && item.type)
|
|
55
|
+
walk(item);
|
|
56
|
+
}
|
|
57
|
+
else if (v.type) {
|
|
58
|
+
walk(v);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
walk(node);
|
|
63
|
+
return found;
|
|
64
|
+
};
|
|
65
|
+
return { isLeafStatement, kindOf, containsAwait };
|
|
66
|
+
}
|
package/dist/domain/code-hook-injector/service/statement-analysis/non-wrappable-statement.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright: (c) Myia SAS 2026.
|
|
3
|
+
* This file and its contents are licensed under the AGPLv3 License.
|
|
4
|
+
* Please see the LICENSE file at the root of this repository
|
|
5
|
+
*/
|
|
6
|
+
import type * as BabelTypes from '@babel/types';
|
|
7
|
+
import type { NodePath } from '@babel/traverse';
|
|
8
|
+
type Types = typeof BabelTypes;
|
|
9
|
+
export type NonWrappableStatementPredicate = (path: NodePath<BabelTypes.Statement>) => boolean;
|
|
10
|
+
export declare function createNonWrappableStatementPredicate(t: Types, isGeneratedModuleStatement: (node: BabelTypes.Node) => boolean): NonWrappableStatementPredicate;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright: (c) Myia SAS 2026.
|
|
4
|
+
* This file and its contents are licensed under the AGPLv3 License.
|
|
5
|
+
* Please see the LICENSE file at the root of this repository
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.createNonWrappableStatementPredicate = createNonWrappableStatementPredicate;
|
|
9
|
+
function createNonWrappableStatementPredicate(t, isGeneratedModuleStatement) {
|
|
10
|
+
return function isNonWrappableStatement(path) {
|
|
11
|
+
const node = path.node;
|
|
12
|
+
return (t.isFunctionDeclaration(node) ||
|
|
13
|
+
t.isImportDeclaration(node) ||
|
|
14
|
+
t.isExportDeclaration(node) ||
|
|
15
|
+
path.parentPath.isExportDeclaration() ||
|
|
16
|
+
t.isBlockStatement(node) ||
|
|
17
|
+
t.isEmptyStatement(node) ||
|
|
18
|
+
isGeneratedModuleStatement(node));
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright: (c) Myia SAS 2026.
|
|
3
|
+
* This file and its contents are licensed under the AGPLv3 License.
|
|
4
|
+
* Please see the LICENSE file at the root of this repository
|
|
5
|
+
*/
|
|
6
|
+
import type * as BabelTypes from '@babel/types';
|
|
7
|
+
import type { NodePath } from '@babel/traverse';
|
|
8
|
+
import type { PluginPass } from '@babel/core';
|
|
9
|
+
type Types = typeof BabelTypes;
|
|
10
|
+
interface MetaHelpers {
|
|
11
|
+
kindOf: (node: BabelTypes.Node) => string;
|
|
12
|
+
containsAwait: (node: BabelTypes.Node) => boolean;
|
|
13
|
+
findScopeName: (nodePath: NodePath) => string;
|
|
14
|
+
extractSource: (code: string | undefined | null, node: BabelTypes.Node) => string;
|
|
15
|
+
extractLeadingComment: (node: BabelTypes.Node) => string | null;
|
|
16
|
+
relFile: (cwd: string, absFile: string | undefined | null) => string;
|
|
17
|
+
}
|
|
18
|
+
export type EnterMetaLiteralBuilder = (state: PluginPass, nodePath: NodePath, node: BabelTypes.Node, cwd: string) => BabelTypes.ObjectExpression;
|
|
19
|
+
export declare function createEnterMetaLiteralBuilder(t: Types, helpers: MetaHelpers): EnterMetaLiteralBuilder;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright: (c) Myia SAS 2026.
|
|
4
|
+
* This file and its contents are licensed under the AGPLv3 License.
|
|
5
|
+
* Please see the LICENSE file at the root of this repository
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.createEnterMetaLiteralBuilder = createEnterMetaLiteralBuilder;
|
|
9
|
+
function createEnterMetaLiteralBuilder(t, helpers) {
|
|
10
|
+
const { kindOf, containsAwait, findScopeName, extractSource, extractLeadingComment, relFile } = helpers;
|
|
11
|
+
return function buildEnterMetaLiteral(state, nodePath, node, cwd) {
|
|
12
|
+
const file = relFile(cwd, state.file.opts.filename);
|
|
13
|
+
const loc = node.loc;
|
|
14
|
+
const properties = [
|
|
15
|
+
t.objectProperty(t.identifier('file'), t.stringLiteral(file)),
|
|
16
|
+
t.objectProperty(t.identifier('startLine'), t.numericLiteral(loc.start.line)),
|
|
17
|
+
t.objectProperty(t.identifier('startCol'), t.numericLiteral(loc.start.column)),
|
|
18
|
+
t.objectProperty(t.identifier('endLine'), t.numericLiteral(loc.end.line)),
|
|
19
|
+
t.objectProperty(t.identifier('endCol'), t.numericLiteral(loc.end.column)),
|
|
20
|
+
t.objectProperty(t.identifier('kind'), t.stringLiteral(kindOf(node))),
|
|
21
|
+
t.objectProperty(t.identifier('scope'), t.stringLiteral(findScopeName(nodePath))),
|
|
22
|
+
t.objectProperty(t.identifier('hasAwait'), t.booleanLiteral(containsAwait(node))),
|
|
23
|
+
t.objectProperty(t.identifier('source'), t.stringLiteral(extractSource(state.file.code, node))),
|
|
24
|
+
];
|
|
25
|
+
// Optional — only emit when the source has an attached comment
|
|
26
|
+
// so the common case stays at 9 keys and no `"leadingComment":
|
|
27
|
+
// null` leaks into the NDJSON.
|
|
28
|
+
const leadingComment = extractLeadingComment(node);
|
|
29
|
+
if (leadingComment !== null) {
|
|
30
|
+
properties.push(t.objectProperty(t.identifier('leadingComment'), t.stringLiteral(leadingComment)));
|
|
31
|
+
}
|
|
32
|
+
return t.objectExpression(properties);
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright: (c) Myia SAS 2026.
|
|
3
|
+
* This file and its contents are licensed under the AGPLv3 License.
|
|
4
|
+
* Please see the LICENSE file at the root of this repository
|
|
5
|
+
*/
|
|
6
|
+
import type * as BabelTypes from '@babel/types';
|
|
7
|
+
type Types = typeof BabelTypes;
|
|
8
|
+
export type GlobalTraceCallBuilder = (name: string, args: BabelTypes.Expression[]) => BabelTypes.ExpressionStatement;
|
|
9
|
+
export declare function createGlobalTraceCallBuilder(t: Types): GlobalTraceCallBuilder;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright: (c) Myia SAS 2026.
|
|
4
|
+
* This file and its contents are licensed under the AGPLv3 License.
|
|
5
|
+
* Please see the LICENSE file at the root of this repository
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.createGlobalTraceCallBuilder = createGlobalTraceCallBuilder;
|
|
9
|
+
function createGlobalTraceCallBuilder(t) {
|
|
10
|
+
return function buildGlobalTraceCall(name, args) {
|
|
11
|
+
const callee = t.memberExpression(t.identifier('globalThis'), t.identifier(name));
|
|
12
|
+
const stmt = t.expressionStatement(t.optionalCallExpression(callee, args, /* optional */ true));
|
|
13
|
+
stmt._traced = true;
|
|
14
|
+
return stmt;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright: (c) Myia SAS 2026.
|
|
3
|
+
* This file and its contents are licensed under the AGPLv3 License.
|
|
4
|
+
* Please see the LICENSE file at the root of this repository
|
|
5
|
+
*/
|
|
6
|
+
import type * as BabelTypes from '@babel/types';
|
|
7
|
+
import type { Scope } from '@babel/traverse';
|
|
8
|
+
import type { GlobalTraceCallBuilder } from './global-trace-call';
|
|
9
|
+
type Types = typeof BabelTypes;
|
|
10
|
+
export interface TryFinallyWrapperBuilder {
|
|
11
|
+
buildTryFinally: (scope: Scope, tryBodyStmts: BabelTypes.Statement[], okArgs?: BabelTypes.Expression[]) => {
|
|
12
|
+
threwId: BabelTypes.Identifier;
|
|
13
|
+
tryStmt: BabelTypes.TryStatement;
|
|
14
|
+
};
|
|
15
|
+
buildThrewDecl: (threwId: BabelTypes.Identifier) => BabelTypes.VariableDeclaration;
|
|
16
|
+
}
|
|
17
|
+
export declare function createTryFinallyWrapperBuilder(t: Types, buildGlobalTraceCall: GlobalTraceCallBuilder): TryFinallyWrapperBuilder;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright: (c) Myia SAS 2026.
|
|
4
|
+
* This file and its contents are licensed under the AGPLv3 License.
|
|
5
|
+
* Please see the LICENSE file at the root of this repository
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.createTryFinallyWrapperBuilder = createTryFinallyWrapperBuilder;
|
|
9
|
+
const global_names_1 = require("../../../trace-event-recorder/model/global-names");
|
|
10
|
+
function createTryFinallyWrapperBuilder(t, buildGlobalTraceCall) {
|
|
11
|
+
function buildTryFinally(scope, tryBodyStmts, okArgs = []) {
|
|
12
|
+
const errId = scope.generateUidIdentifier('traceErr');
|
|
13
|
+
const threwId = scope.generateUidIdentifier('traceThrew');
|
|
14
|
+
const rethrow = t.throwStatement(t.cloneNode(errId));
|
|
15
|
+
rethrow._traced = true;
|
|
16
|
+
const assignThrew = t.expressionStatement(t.assignmentExpression('=', t.cloneNode(threwId), t.booleanLiteral(true)));
|
|
17
|
+
assignThrew._traced = true;
|
|
18
|
+
const catchBlock = t.blockStatement([
|
|
19
|
+
assignThrew,
|
|
20
|
+
buildGlobalTraceCall(global_names_1.HEAL_THROW, [t.cloneNode(errId)]),
|
|
21
|
+
rethrow,
|
|
22
|
+
]);
|
|
23
|
+
const finallyBlock = t.blockStatement([
|
|
24
|
+
t.ifStatement(t.unaryExpression('!', t.cloneNode(threwId)), t.blockStatement([buildGlobalTraceCall(global_names_1.HEAL_OK, okArgs)])),
|
|
25
|
+
]);
|
|
26
|
+
finallyBlock.body.forEach((n) => {
|
|
27
|
+
n._traced = true;
|
|
28
|
+
const withConsequent = n;
|
|
29
|
+
if (withConsequent.consequent)
|
|
30
|
+
withConsequent.consequent._traced = true;
|
|
31
|
+
});
|
|
32
|
+
const tryStmt = t.tryStatement(t.blockStatement(tryBodyStmts), t.catchClause(errId, catchBlock), finallyBlock);
|
|
33
|
+
tryStmt._traced = true;
|
|
34
|
+
return { threwId, tryStmt };
|
|
35
|
+
}
|
|
36
|
+
function buildThrewDecl(threwId) {
|
|
37
|
+
const decl = t.variableDeclaration('let', [
|
|
38
|
+
t.variableDeclarator(threwId, t.booleanLiteral(false)),
|
|
39
|
+
]);
|
|
40
|
+
decl._traced = true;
|
|
41
|
+
return decl;
|
|
42
|
+
}
|
|
43
|
+
return { buildTryFinally, buildThrewDecl };
|
|
44
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright: (c) Myia SAS 2026.
|
|
3
|
+
* This file and its contents are licensed under the AGPLv3 License.
|
|
4
|
+
* Please see the LICENSE file at the root of this repository
|
|
5
|
+
*/
|
|
6
|
+
import type * as BabelTypes from '@babel/types';
|
|
7
|
+
type Types = typeof BabelTypes;
|
|
8
|
+
export interface HoistedVariableDeclaration {
|
|
9
|
+
/** Names introduced by the declaration, flattened across destructuring. */
|
|
10
|
+
bindingNames: Set<string>;
|
|
11
|
+
/** `let x, y;` — the bindings hoisted out of the try block. */
|
|
12
|
+
hoistDecl: BabelTypes.VariableDeclaration;
|
|
13
|
+
/** `x = EXPR; y = EXPR;` — one per declarator that had an initializer. */
|
|
14
|
+
assignments: BabelTypes.ExpressionStatement[];
|
|
15
|
+
/** `{ x, y }` — shorthand object literal passed to `__ok`. */
|
|
16
|
+
varsObject: BabelTypes.ObjectExpression;
|
|
17
|
+
}
|
|
18
|
+
export type VariableDeclarationHoister = (declaration: BabelTypes.VariableDeclaration) => HoistedVariableDeclaration;
|
|
19
|
+
export declare function createVariableDeclarationHoister(t: Types): VariableDeclarationHoister;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright: (c) Myia SAS 2026.
|
|
4
|
+
* This file and its contents are licensed under the AGPLv3 License.
|
|
5
|
+
* Please see the LICENSE file at the root of this repository
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.createVariableDeclarationHoister = createVariableDeclarationHoister;
|
|
9
|
+
function createVariableDeclarationHoister(t) {
|
|
10
|
+
return function hoistVariableDeclaration(declaration) {
|
|
11
|
+
const bindingNames = new Set();
|
|
12
|
+
for (const d of declaration.declarations) {
|
|
13
|
+
Object.keys(t.getBindingIdentifiers(d.id)).forEach((n) => bindingNames.add(n));
|
|
14
|
+
}
|
|
15
|
+
const hoistDecl = t.variableDeclaration('let', [...bindingNames].map((n) => t.variableDeclarator(t.identifier(n))));
|
|
16
|
+
hoistDecl._traced = true;
|
|
17
|
+
const assignments = declaration.declarations
|
|
18
|
+
.filter((d) => d.init != null)
|
|
19
|
+
.map((d) => {
|
|
20
|
+
const stmt = t.expressionStatement(t.assignmentExpression('=', d.id, d.init));
|
|
21
|
+
stmt._traced = true;
|
|
22
|
+
return stmt;
|
|
23
|
+
});
|
|
24
|
+
const varsObject = t.objectExpression([...bindingNames].map((n) => t.objectProperty(t.identifier(n), t.identifier(n), false, true)));
|
|
25
|
+
return { bindingNames, hoistDecl, assignments, varsObject };
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright: (c) Myia SAS 2026.
|
|
3
|
+
* This file and its contents are licensed under the AGPLv3 License.
|
|
4
|
+
* Please see the LICENSE file at the root of this repository
|
|
5
|
+
*/
|
|
6
|
+
export type IncludeEntry = string | RegExp | ((filename: string) => unknown);
|
|
7
|
+
export type Include = IncludeEntry | IncludeEntry[] | null | undefined;
|
|
8
|
+
export type Matcher = (filename: string | undefined | null) => boolean;
|
|
9
|
+
export declare const defaultInclude: IncludeEntry[];
|
|
10
|
+
export declare function buildMatcher(include: Include): Matcher;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright: (c) Myia SAS 2026.
|
|
4
|
+
* This file and its contents are licensed under the AGPLv3 License.
|
|
5
|
+
* Please see the LICENSE file at the root of this repository
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.defaultInclude = void 0;
|
|
9
|
+
exports.buildMatcher = buildMatcher;
|
|
10
|
+
exports.defaultInclude = [/\/tests\//];
|
|
11
|
+
function buildMatcher(include) {
|
|
12
|
+
const entries = include == null ? exports.defaultInclude : Array.isArray(include) ? include : [include];
|
|
13
|
+
return (filename) => {
|
|
14
|
+
if (!filename)
|
|
15
|
+
return false;
|
|
16
|
+
for (const e of entries) {
|
|
17
|
+
if (typeof e === 'string' && filename.includes(e))
|
|
18
|
+
return true;
|
|
19
|
+
if (e instanceof RegExp && e.test(filename))
|
|
20
|
+
return true;
|
|
21
|
+
if (typeof e === 'function' && e(filename))
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright: (c) Myia SAS 2026.
|
|
3
|
+
* This file and its contents are licensed under the AGPLv3 License.
|
|
4
|
+
* Please see the LICENSE file at the root of this repository
|
|
5
|
+
*/
|
|
6
|
+
export interface EnterMeta {
|
|
7
|
+
file: string;
|
|
8
|
+
startLine: number;
|
|
9
|
+
startCol: number;
|
|
10
|
+
endLine: number;
|
|
11
|
+
endCol: number;
|
|
12
|
+
kind: string;
|
|
13
|
+
scope: string;
|
|
14
|
+
hasAwait: boolean;
|
|
15
|
+
source: string;
|
|
16
|
+
/**
|
|
17
|
+
* User-written `// …` / `/* … *\/` comments attached to this
|
|
18
|
+
* statement's AST node, joined with `\n` in source order. Present
|
|
19
|
+
* only when the parser attached at least one comment; see
|
|
20
|
+
* `./statement-trace-schema.ts` `Statement.leadingComment` for the
|
|
21
|
+
* attachment caveats consumers should know about.
|
|
22
|
+
*/
|
|
23
|
+
leadingComment?: string;
|
|
24
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright: (c) Myia SAS 2026.
|
|
3
|
+
* This file and its contents are licensed under the AGPLv3 License.
|
|
4
|
+
* Please see the LICENSE file at the root of this repository
|
|
5
|
+
*/
|
|
6
|
+
export declare const HEAL_ENTER = "__heal_enter";
|
|
7
|
+
export declare const HEAL_OK = "__heal_ok";
|
|
8
|
+
export declare const HEAL_THROW = "__heal_throw";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright: (c) Myia SAS 2026.
|
|
4
|
+
* This file and its contents are licensed under the AGPLv3 License.
|
|
5
|
+
* Please see the LICENSE file at the root of this repository
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.HEAL_THROW = exports.HEAL_OK = exports.HEAL_ENTER = void 0;
|
|
9
|
+
// Names of the global functions the Babel plugin injects into
|
|
10
|
+
// instrumented source and the recorder entrypoint installs on
|
|
11
|
+
// `globalThis`. Both sides import from here so the contract lives in
|
|
12
|
+
// one place.
|
|
13
|
+
//
|
|
14
|
+
// The names are deliberately prefixed with `__heal_` so anyone
|
|
15
|
+
// reading the Babel-transformed test source understands at a glance
|
|
16
|
+
// which library these hooks belong to. Rename them together (plugin
|
|
17
|
+
// and recorder entrypoint) if the package is ever renamed.
|
|
18
|
+
exports.HEAL_ENTER = '__heal_enter';
|
|
19
|
+
exports.HEAL_OK = '__heal_ok';
|
|
20
|
+
exports.HEAL_THROW = '__heal_throw';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright: (c) Myia SAS 2026.
|
|
3
|
+
* This file and its contents are licensed under the AGPLv3 License.
|
|
4
|
+
* Please see the LICENSE file at the root of this repository
|
|
5
|
+
*/
|
|
6
|
+
export interface SerializedError {
|
|
7
|
+
name?: string;
|
|
8
|
+
message: string;
|
|
9
|
+
stack?: string;
|
|
10
|
+
isPlaywrightError?: boolean;
|
|
11
|
+
causes?: Array<{
|
|
12
|
+
name?: string;
|
|
13
|
+
message: string;
|
|
14
|
+
stack?: string;
|
|
15
|
+
}>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright: (c) Myia SAS 2026.
|
|
3
|
+
* This file and its contents are licensed under the AGPLv3 License.
|
|
4
|
+
* Please see the LICENSE file at the root of this repository
|
|
5
|
+
*/
|
|
6
|
+
export declare const HEAL_TRACE_SCHEMA_VERSION = 1;
|
|
7
|
+
/**
|
|
8
|
+
* One line of a `heal-traces.ndjson` file. Discriminated by `kind`.
|
|
9
|
+
*/
|
|
10
|
+
export type HealTraceRecord = TestHeaderRecord | StatementRecord | TestResultRecord;
|
|
11
|
+
export interface TestHeaderRecord {
|
|
12
|
+
kind: 'test-header';
|
|
13
|
+
schemaVersion: typeof HEAL_TRACE_SCHEMA_VERSION;
|
|
14
|
+
test: TestHeader;
|
|
15
|
+
}
|
|
16
|
+
export interface TestHeader {
|
|
17
|
+
title: string;
|
|
18
|
+
titlePath: string[];
|
|
19
|
+
file: string;
|
|
20
|
+
project: string;
|
|
21
|
+
workerIndex: number;
|
|
22
|
+
retry: number;
|
|
23
|
+
/** Wall-clock ms (Date.now()) at which the recorder was reset for this test. */
|
|
24
|
+
startedAt: number;
|
|
25
|
+
env: TestEnv;
|
|
26
|
+
context: TestContext;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Per-test correlation identifiers. Populated by the fixture from
|
|
30
|
+
* Playwright's `TestInfo`. The global correlation key for a test
|
|
31
|
+
* attempt is `(testId, attempt)` — two attempts of the same test
|
|
32
|
+
* share `testId` and differ in `attempt`.
|
|
33
|
+
*/
|
|
34
|
+
export interface TestContext {
|
|
35
|
+
/**
|
|
36
|
+
* Playwright's `testInfo.testId` — a stable hash of
|
|
37
|
+
* (file, title, project). Distinct tests always get distinct
|
|
38
|
+
* values; two attempts of the same test share this value. Also
|
|
39
|
+
* serves as the cross-worker correlation key: a retry landing in
|
|
40
|
+
* a different worker still reports the same `testId`.
|
|
41
|
+
*/
|
|
42
|
+
testId: string;
|
|
43
|
+
/**
|
|
44
|
+
* 1-indexed attempt number. Equal to `testInfo.retry + 1` — the
|
|
45
|
+
* first run of a test is attempt 1, the first retry is attempt 2,
|
|
46
|
+
* and so on.
|
|
47
|
+
*/
|
|
48
|
+
attempt: number;
|
|
49
|
+
/**
|
|
50
|
+
* Heal test case id sourced from the `@heal-<id>` Playwright tag
|
|
51
|
+
* on the test (e.g. `test('…', { tag: '@heal-42' }, …)`). The
|
|
52
|
+
* suffix after `@heal-` is parsed as a positive integer — it must
|
|
53
|
+
* match the `bigint` primary key on `backend.test_cases`. When
|
|
54
|
+
* present, the backend resolver links every trace event for this
|
|
55
|
+
* run to the referenced test case (after verifying the id belongs
|
|
56
|
+
* to the API key's org). When absent, events go to the unlinked
|
|
57
|
+
* bucket.
|
|
58
|
+
*
|
|
59
|
+
* Tags over annotations because they are CLI-filterable — the
|
|
60
|
+
* backend triggers a specific set of test cases with
|
|
61
|
+
* `npx playwright test -g "@heal-42|@heal-57"`, no file paths or
|
|
62
|
+
* line numbers required.
|
|
63
|
+
*/
|
|
64
|
+
testCaseId?: number;
|
|
65
|
+
}
|
|
66
|
+
export interface TestEnv {
|
|
67
|
+
nodeVersion?: string;
|
|
68
|
+
platform?: string;
|
|
69
|
+
arch?: string;
|
|
70
|
+
hostname?: string;
|
|
71
|
+
isCI?: boolean;
|
|
72
|
+
cwd?: string;
|
|
73
|
+
gitSha?: string;
|
|
74
|
+
pid?: number;
|
|
75
|
+
}
|
|
76
|
+
export interface StatementRecord {
|
|
77
|
+
kind: 'statement';
|
|
78
|
+
/**
|
|
79
|
+
* Always a ROOT statement (its runtime parentSeq was null). The
|
|
80
|
+
* full subtree is nested in `statement.children`; nested calls
|
|
81
|
+
* never appear as separate records in the stream.
|
|
82
|
+
*/
|
|
83
|
+
statement: Statement;
|
|
84
|
+
}
|
|
85
|
+
export interface Statement {
|
|
86
|
+
/** Execution-order sequence number, identical to the raw enter event's seq. */
|
|
87
|
+
seq: number;
|
|
88
|
+
file: string;
|
|
89
|
+
line: number;
|
|
90
|
+
endLine: number;
|
|
91
|
+
kind: string;
|
|
92
|
+
scope: string;
|
|
93
|
+
source: string;
|
|
94
|
+
hasAwait: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* User-written source comments (`// …` or `/* … *\/`) that Babel's
|
|
97
|
+
* parser attached to this statement's AST node, joined with `\n`
|
|
98
|
+
* in source order, with a single leading/trailing space stripped
|
|
99
|
+
* from each comment value. Absent from the JSON when the node has
|
|
100
|
+
* no attached comments (the field is never `null` or `""`).
|
|
101
|
+
*
|
|
102
|
+
* Intended as a best-effort intent hint — the autopilot agent and
|
|
103
|
+
* humans debugging a failing test read this the same way they
|
|
104
|
+
* would read the comment above a step in the source file.
|
|
105
|
+
*
|
|
106
|
+
* Attachment caveat: Babel assigns a same-line trailing comment
|
|
107
|
+
* of statement N as a *leading* comment of statement N+1 when the
|
|
108
|
+
* two are separated only by whitespace. `foo(); // about foo\n
|
|
109
|
+
* bar();` therefore surfaces `about foo` on `bar()`, not `foo()`.
|
|
110
|
+
* Treat the field accordingly.
|
|
111
|
+
*/
|
|
112
|
+
leadingComment?: string;
|
|
113
|
+
/** Innermost test.step title, or null if not inside one. */
|
|
114
|
+
step: string | null;
|
|
115
|
+
/** Full chain of enclosing test.step titles. */
|
|
116
|
+
stepPath: string[] | null;
|
|
117
|
+
status: 'ok' | 'threw';
|
|
118
|
+
/** Milliseconds the statement took to execute. */
|
|
119
|
+
duration: number;
|
|
120
|
+
/** Relative start time in ms (from test.startedAt). */
|
|
121
|
+
t: number;
|
|
122
|
+
pageUrl?: string;
|
|
123
|
+
/** Snapshot of bindings introduced by `const`/`let` that succeeded. */
|
|
124
|
+
vars?: Record<string, unknown>;
|
|
125
|
+
/** Present only when status === 'threw'. */
|
|
126
|
+
error?: StatementError;
|
|
127
|
+
/**
|
|
128
|
+
* Filename (relative to the test's heal-data directory) of the
|
|
129
|
+
* highlight screenshot captured by locator-screenshots while this
|
|
130
|
+
* statement was running. Present only for statements that call a
|
|
131
|
+
* patched Locator action (`click`, `fill`, `hover`, …) or a
|
|
132
|
+
* wrapped assertion.
|
|
133
|
+
*/
|
|
134
|
+
screenshot?: string;
|
|
135
|
+
/**
|
|
136
|
+
* Statements executed inside this one. Sorted by execution order
|
|
137
|
+
* (`seq`). Empty for leaves.
|
|
138
|
+
*/
|
|
139
|
+
children: Statement[];
|
|
140
|
+
}
|
|
141
|
+
export interface TestResultRecord {
|
|
142
|
+
kind: 'test-result';
|
|
143
|
+
status: 'passed' | 'failed' | 'timedOut' | 'skipped' | 'interrupted';
|
|
144
|
+
/** Total test duration in ms, as reported by Playwright's TestInfo. */
|
|
145
|
+
duration: number;
|
|
146
|
+
stdout?: string[];
|
|
147
|
+
stderr?: string[];
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Normalized error attached to a statement whose status is `threw`.
|
|
151
|
+
* Decoupled from the runtime `SerializedError` type so consumers of
|
|
152
|
+
* `heal-traces.ndjson` can import this schema without reaching into
|
|
153
|
+
* internal modules.
|
|
154
|
+
*/
|
|
155
|
+
export interface StatementError {
|
|
156
|
+
name?: string;
|
|
157
|
+
message: string;
|
|
158
|
+
stack?: string;
|
|
159
|
+
/**
|
|
160
|
+
* True when the error originated from Playwright itself (timeouts,
|
|
161
|
+
* locator failures, expect mismatches) as opposed to user code.
|
|
162
|
+
*/
|
|
163
|
+
isPlaywrightError?: boolean;
|
|
164
|
+
/** Walked `.cause` chain, up to 5 levels deep. */
|
|
165
|
+
causes?: StatementErrorCause[];
|
|
166
|
+
}
|
|
167
|
+
export interface StatementErrorCause {
|
|
168
|
+
name?: string;
|
|
169
|
+
message: string;
|
|
170
|
+
stack?: string;
|
|
171
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright: (c) Myia SAS 2026.
|
|
4
|
+
* This file and its contents are licensed under the AGPLv3 License.
|
|
5
|
+
* Please see the LICENSE file at the root of this repository
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.HEAL_TRACE_SCHEMA_VERSION = void 0;
|
|
9
|
+
// Output schema for `heal-traces.ndjson` — the agent-facing wire
|
|
10
|
+
// format written one record per line.
|
|
11
|
+
//
|
|
12
|
+
// The file is a stream, not a single document: each line is exactly
|
|
13
|
+
// one `HealTraceRecord`. Per test the records appear in this order:
|
|
14
|
+
//
|
|
15
|
+
// 1. Exactly one `test-header` record (first line). Carries static
|
|
16
|
+
// per-test metadata and environment fields; the fields known
|
|
17
|
+
// only at test-end (status, duration, stdout, stderr) live on
|
|
18
|
+
// `test-result` instead.
|
|
19
|
+
// 2. Zero or more `statement` records, each a ROOT statement
|
|
20
|
+
// (directly inside the test body). Nested calls live inline
|
|
21
|
+
// inside `statement.children` and never appear as standalone
|
|
22
|
+
// records. Consumers must not expect a flat stream of every
|
|
23
|
+
// executed statement.
|
|
24
|
+
// 3. Exactly one `test-result` record (last line). If it is
|
|
25
|
+
// missing, the test crashed mid-run and the trace should be
|
|
26
|
+
// treated as partial.
|
|
27
|
+
//
|
|
28
|
+
// The projector in `../../trace-event-recorder/projectors/
|
|
29
|
+
// statement-projector.ts` is what produces these records from the
|
|
30
|
+
// raw recorder event stream (enter/ok/throw/meta). Consumers (the
|
|
31
|
+
// Heal autopilot agent, humans debugging a failing test) should
|
|
32
|
+
// import these types to stay in sync with the file format.
|
|
33
|
+
exports.HEAL_TRACE_SCHEMA_VERSION = 1;
|