@elench/testkit 0.1.82 → 0.1.84

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.
Files changed (100) hide show
  1. package/README.md +37 -7
  2. package/lib/cli/agents/index.mjs +64 -0
  3. package/lib/cli/agents/investigate.mjs +75 -0
  4. package/lib/cli/agents/investigation-context.mjs +102 -0
  5. package/lib/cli/agents/prompt-builder.mjs +25 -0
  6. package/lib/cli/agents/providers/claude.mjs +74 -0
  7. package/lib/cli/agents/providers/codex.mjs +83 -0
  8. package/lib/cli/agents/providers/shared.mjs +134 -0
  9. package/lib/cli/command-helpers.mjs +53 -25
  10. package/lib/cli/commands/investigate.mjs +87 -0
  11. package/lib/cli/entrypoint.mjs +3 -0
  12. package/lib/cli/presentation/colors.mjs +12 -0
  13. package/lib/cli/presentation/events-reporter.mjs +135 -0
  14. package/lib/cli/presentation/summary-box.mjs +11 -11
  15. package/lib/cli/presentation/tree-reporter.mjs +159 -0
  16. package/lib/cli/tui/run-app.mjs +1 -0
  17. package/lib/cli/tui/run-session-app.mjs +370 -0
  18. package/lib/cli/tui/run-session-state.mjs +481 -0
  19. package/lib/cli/tui/run-tree-state.mjs +1 -0
  20. package/lib/config-api/auth-fixtures.mjs +15 -10
  21. package/lib/discovery/index.mjs +1 -1
  22. package/lib/index.d.ts +5 -1
  23. package/lib/runner/orchestrator.mjs +1 -0
  24. package/lib/runtime/index.d.ts +138 -5
  25. package/lib/runtime/index.mjs +68 -2
  26. package/lib/runtime-src/k6/http-assertions.js +31 -1
  27. package/lib/runtime-src/k6/http-checks.js +120 -0
  28. package/lib/runtime-src/k6/http-suite-runtime.js +5 -1
  29. package/lib/runtime-src/k6/http.js +213 -23
  30. package/lib/runtime-src/shared/error-body.mjs +42 -0
  31. package/lib/runtime-src/shared/http-parsing.mjs +68 -0
  32. package/node_modules/@elench/next-analysis/package.json +1 -1
  33. package/node_modules/@elench/testkit-bridge/package.json +2 -2
  34. package/node_modules/@elench/testkit-protocol/package.json +1 -1
  35. package/node_modules/@elench/ts-analysis/package.json +1 -1
  36. package/package.json +7 -6
  37. package/lib/app/configs.test.mjs +0 -34
  38. package/lib/app/typecheck.test.mjs +0 -24
  39. package/lib/bundler/index.test.mjs +0 -164
  40. package/lib/cli/args.test.mjs +0 -110
  41. package/lib/cli/presentation/code-frames.test.mjs +0 -71
  42. package/lib/cli/presentation/run-reporter.test.mjs +0 -192
  43. package/lib/cli/presentation/summary-box.test.mjs +0 -43
  44. package/lib/cli/presentation/terminal-layout.test.mjs +0 -23
  45. package/lib/config/database.test.mjs +0 -29
  46. package/lib/config/discovery.test.mjs +0 -276
  47. package/lib/config/env.test.mjs +0 -40
  48. package/lib/config/index.test.mjs +0 -44
  49. package/lib/config/paths.test.mjs +0 -27
  50. package/lib/config/runtime.test.mjs +0 -82
  51. package/lib/config/skip-config.test.mjs +0 -63
  52. package/lib/config-api/index.test.mjs +0 -344
  53. package/lib/config-api/next-runtime-tsconfig.test.mjs +0 -58
  54. package/lib/coverage/backend-discovery.test.mjs +0 -61
  55. package/lib/coverage/evidence.test.mjs +0 -87
  56. package/lib/coverage/index.test.mjs +0 -715
  57. package/lib/coverage/routing.test.mjs +0 -36
  58. package/lib/coverage/shared.test.mjs +0 -72
  59. package/lib/database/fingerprint.test.mjs +0 -99
  60. package/lib/database/index.test.mjs +0 -95
  61. package/lib/database/naming.test.mjs +0 -39
  62. package/lib/database/state.test.mjs +0 -66
  63. package/lib/database/template-steps.test.mjs +0 -43
  64. package/lib/discovery/file-metadata.test.mjs +0 -51
  65. package/lib/discovery/index.test.mjs +0 -182
  66. package/lib/discovery/path-policy.test.mjs +0 -65
  67. package/lib/drizzle/index.test.mjs +0 -33
  68. package/lib/env/index.test.mjs +0 -82
  69. package/lib/history/index.test.mjs +0 -115
  70. package/lib/package.test.mjs +0 -59
  71. package/lib/playwright/index.test.mjs +0 -43
  72. package/lib/regressions/github.test.mjs +0 -324
  73. package/lib/regressions/index.test.mjs +0 -187
  74. package/lib/reporters/playwright.test.mjs +0 -167
  75. package/lib/runner/default-runtime-errors.test.mjs +0 -49
  76. package/lib/runner/execution-config.test.mjs +0 -67
  77. package/lib/runner/failure-details.test.mjs +0 -114
  78. package/lib/runner/formatting.test.mjs +0 -205
  79. package/lib/runner/metadata.test.mjs +0 -52
  80. package/lib/runner/planning.test.mjs +0 -371
  81. package/lib/runner/playwright-config.test.mjs +0 -78
  82. package/lib/runner/processes.test.mjs +0 -21
  83. package/lib/runner/regressions.test.mjs +0 -168
  84. package/lib/runner/reporting.test.mjs +0 -310
  85. package/lib/runner/results.test.mjs +0 -376
  86. package/lib/runner/runtime-manager.test.mjs +0 -252
  87. package/lib/runner/runtime-preparation.test.mjs +0 -141
  88. package/lib/runner/selection.test.mjs +0 -24
  89. package/lib/runner/setup-operations.test.mjs +0 -94
  90. package/lib/runner/state.test.mjs +0 -62
  91. package/lib/runner/suite-selection.test.mjs +0 -49
  92. package/lib/runner/template.test.mjs +0 -272
  93. package/lib/shared/build-config.test.mjs +0 -132
  94. package/lib/shared/configured-steps.test.mjs +0 -102
  95. package/lib/shared/execution-schema.test.mjs +0 -26
  96. package/lib/shared/file-timeout.test.mjs +0 -64
  97. package/lib/shared/test-context.test.mjs +0 -43
  98. package/lib/timing/index.test.mjs +0 -64
  99. package/lib/toolchains/index.test.mjs +0 -168
  100. package/lib/vitest/index.test.mjs +0 -20
@@ -1,310 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { buildLiveRunArtifact, buildRunArtifact, buildStatusArtifact } from "./reporting.mjs";
3
-
4
- describe("runner reporting", () => {
5
- it("builds run artifacts", () => {
6
- const results = [
7
- {
8
- name: "api",
9
- failed: false,
10
- skipped: false,
11
- suiteCount: 1,
12
- completedSuiteCount: 1,
13
- skippedSuiteCount: 0,
14
- failedSuiteCount: 0,
15
- totalFileCount: 3,
16
- completedFileCount: 3,
17
- passedFileCount: 3,
18
- failedFileCount: 0,
19
- skippedFileCount: 0,
20
- notRunFileCount: 0,
21
- durationMs: 1200,
22
- totalTaskDurationMs: 2400,
23
- dbBackend: "local",
24
- suites: [],
25
- errors: [],
26
- },
27
- {
28
- name: "frontend",
29
- failed: false,
30
- skipped: true,
31
- suiteCount: 0,
32
- completedSuiteCount: 0,
33
- skippedSuiteCount: 0,
34
- failedSuiteCount: 0,
35
- totalFileCount: 0,
36
- completedFileCount: 0,
37
- passedFileCount: 0,
38
- failedFileCount: 0,
39
- skippedFileCount: 0,
40
- notRunFileCount: 0,
41
- durationMs: 0,
42
- totalTaskDurationMs: 0,
43
- dbBackend: null,
44
- suites: [],
45
- errors: [],
46
- },
47
- ];
48
-
49
- const artifact = buildRunArtifact({
50
- productDir: "/tmp/my-product",
51
- results,
52
- startedAt: 1000,
53
- finishedAt: 4000,
54
- execution: {
55
- workers: 2,
56
- fileTimeoutSeconds: 60,
57
- },
58
- workerCount: 1,
59
- runtimeInstanceCount: 2,
60
- typeValues: ["all"],
61
- suiteSelectors: [],
62
- fileNames: [],
63
- shard: null,
64
- serviceFilter: null,
65
- scenarioSeed: "demo-seed",
66
- metadata: {
67
- git: {
68
- branch: "main",
69
- commitSha: "abc",
70
- repoRoot: "/tmp",
71
- },
72
- host: {
73
- hostname: "local",
74
- username: "dev",
75
- },
76
- testkitVersion: "0.1.17",
77
- },
78
- summarizeDbBackend: () => "local",
79
- });
80
-
81
- expect(artifact.product.name).toBe("my-product");
82
- expect(artifact.schemaVersion).toBe(9);
83
- expect(artifact.run).toMatchObject({
84
- workers: 2,
85
- fileTimeoutSeconds: 60,
86
- workerCount: 1,
87
- runtimeInstanceCount: 2,
88
- scenarioSeed: "demo-seed",
89
- });
90
- expect(artifact.summary.services).toEqual({
91
- total: 1,
92
- passed: 1,
93
- failed: 0,
94
- skipped: 0,
95
- });
96
- expect(artifact.summary.suites).toEqual({
97
- total: 1,
98
- completed: 1,
99
- passed: 1,
100
- failed: 0,
101
- skipped: 0,
102
- });
103
- expect(artifact.summary.files).toEqual({
104
- total: 3,
105
- passed: 3,
106
- failed: 0,
107
- skipped: 0,
108
- notRun: 0,
109
- });
110
- expect(artifact.services[0].durationMs).toBe(1200);
111
- expect(artifact.services[0].totalTaskDurationMs).toBe(2400);
112
- expect(artifact.logs).toEqual({
113
- services: [],
114
- setup: [],
115
- });
116
- expect(artifact.setup).toEqual({
117
- operations: [],
118
- });
119
- });
120
-
121
- it("builds live run artifacts with running status and setup details", () => {
122
- const artifact = buildLiveRunArtifact({
123
- productDir: "/tmp/my-product",
124
- results: [],
125
- startedAt: 1_000,
126
- updatedAt: 2_000,
127
- execution: {
128
- workers: 2,
129
- fileTimeoutSeconds: 60,
130
- },
131
- workerCount: 1,
132
- runtimeInstanceCount: 1,
133
- runtimeStats: [],
134
- typeValues: ["int"],
135
- suiteSelectors: [],
136
- fileNames: [],
137
- shard: null,
138
- serviceFilter: null,
139
- metadata: {
140
- git: {
141
- branch: "main",
142
- commitSha: "abc",
143
- repoRoot: "/tmp",
144
- },
145
- host: {
146
- hostname: "local",
147
- username: "dev",
148
- },
149
- testkitVersion: "0.1.54",
150
- },
151
- summarizeDbBackend: () => "local",
152
- serviceLogs: [],
153
- setupLogs: [
154
- {
155
- serviceName: "api",
156
- runtimeLabel: "api",
157
- stage: "runtime:prepare",
158
- path: ".testkit/results/setup/api__api__runtime-prepare.log",
159
- },
160
- ],
161
- setupOperations: [
162
- {
163
- id: "setup-1",
164
- serviceName: "api",
165
- runtimeLabel: "api",
166
- stage: "runtime:prepare",
167
- kind: "runtime-prepare",
168
- summary: "runtime prepare",
169
- parentId: null,
170
- status: "running",
171
- startedAt: "1970-01-01T00:00:01.000Z",
172
- finishedAt: null,
173
- durationMs: null,
174
- error: null,
175
- logRef: {
176
- path: ".testkit/results/setup/api__api__runtime-prepare.log",
177
- stage: "runtime:prepare",
178
- },
179
- },
180
- ],
181
- });
182
-
183
- expect(artifact.run.status).toBe("running");
184
- expect(artifact.logs.setup).toEqual([
185
- {
186
- serviceName: "api",
187
- runtimeLabel: "api",
188
- stage: "runtime:prepare",
189
- path: ".testkit/results/setup/api__api__runtime-prepare.log",
190
- },
191
- ]);
192
- expect(artifact.setup.operations).toHaveLength(1);
193
- });
194
-
195
- it("builds deterministic status artifacts", () => {
196
- const status = buildStatusArtifact({
197
- productDir: "/tmp/my-product",
198
- results: [
199
- {
200
- name: "api",
201
- failed: true,
202
- skipped: false,
203
- suites: [
204
- {
205
- name: "health",
206
- type: "int",
207
- framework: "k6",
208
- files: [
209
- { path: "tests/api/integration/a.int.testkit.ts", status: "passed" },
210
- {
211
- path: "tests/api/integration/b.int.testkit.ts",
212
- status: "skipped",
213
- reason: "Billing is stubbed",
214
- },
215
- ],
216
- },
217
- ],
218
- },
219
- ],
220
- typeValues: ["int"],
221
- suiteSelectors: [{ kind: "plain", name: "health", raw: "health" }],
222
- fileNames: ["tests/api/integration/b.int.testkit.ts"],
223
- shard: null,
224
- serviceFilter: "api",
225
- scenarioSeed: "demo-seed",
226
- metadata: {
227
- git: {
228
- branch: "main",
229
- commitSha: "abc123",
230
- },
231
- testkitVersion: "0.1.20",
232
- },
233
- });
234
-
235
- expect(status).toEqual({
236
- schemaVersion: 7,
237
- source: "testkit",
238
- notice: "Generated file. Do not edit manually.",
239
- product: {
240
- name: "my-product",
241
- },
242
- git: {
243
- branch: "main",
244
- commitSha: "abc123",
245
- },
246
- testkitVersion: "0.1.20",
247
- scope: {
248
- types: ["int"],
249
- suiteSelectors: ["health"],
250
- fileNames: ["tests/api/integration/b.int.testkit.ts"],
251
- shard: null,
252
- serviceFilter: "api",
253
- scenarioSeed: "demo-seed",
254
- isFullRun: false,
255
- },
256
- summary: {
257
- services: {
258
- total: 1,
259
- passed: 0,
260
- failed: 1,
261
- skipped: 0,
262
- },
263
- tests: {
264
- total: 2,
265
- passed: 1,
266
- failed: 0,
267
- skipped: 1,
268
- notRun: 0,
269
- },
270
- },
271
- tests: [
272
- {
273
- service: "api",
274
- type: "int",
275
- path: "tests/api/integration/a.int.testkit.ts",
276
- status: "passed",
277
- },
278
- {
279
- service: "api",
280
- type: "int",
281
- path: "tests/api/integration/b.int.testkit.ts",
282
- status: "skipped",
283
- reason: "Billing is stubbed",
284
- },
285
- ],
286
- });
287
- });
288
-
289
- it("marks unfiltered status artifacts as full runs", () => {
290
- const status = buildStatusArtifact({
291
- productDir: "/tmp/my-product",
292
- results: [],
293
- typeValues: ["all"],
294
- suiteSelectors: [],
295
- fileNames: [],
296
- shard: null,
297
- serviceFilter: null,
298
- scenarioSeed: null,
299
- metadata: {
300
- git: {
301
- branch: "main",
302
- commitSha: "abc123",
303
- },
304
- testkitVersion: "0.1.20",
305
- },
306
- });
307
-
308
- expect(status.scope.isFullRun).toBe(true);
309
- });
310
- });
@@ -1,376 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import {
3
- addTrackerError,
4
- buildServiceTrackers,
5
- finalizeServiceResult,
6
- recordGraphError,
7
- recordTaskOutcome,
8
- summarizeDbBackend,
9
- } from "./results.mjs";
10
-
11
- describe("runner results", () => {
12
- it("tracks task outcomes and graph errors", () => {
13
- const trackers = buildServiceTrackers(
14
- [
15
- {
16
- skipped: false,
17
- config: {
18
- name: "api",
19
- testkit: {
20
- database: {
21
- selectedBackend: "local",
22
- },
23
- },
24
- },
25
- suites: [
26
- {
27
- name: "health",
28
- type: "integration",
29
- framework: "k6",
30
- files: ["tests/health.js"],
31
- orderIndex: 0,
32
- },
33
- ],
34
- },
35
- ],
36
- 1000
37
- );
38
-
39
- recordTaskOutcome(
40
- trackers,
41
- {
42
- serviceName: "api",
43
- suiteKey: "integration:health",
44
- file: "tests/health.js",
45
- },
46
- {
47
- failed: true,
48
- durationMs: 250,
49
- error: "boom",
50
- },
51
- 1250
52
- );
53
-
54
- const tracker = trackers.get("api");
55
- addTrackerError(tracker, "worker failed");
56
- addTrackerError(tracker, "worker failed");
57
- recordGraphError(trackers, { targetNames: ["api"] }, "graph failed", 1300);
58
-
59
- const result = finalizeServiceResult(tracker, 1000, 1500);
60
- expect(result.failed).toBe(true);
61
- expect(result.failedSuiteCount).toBe(1);
62
- expect(result.totalFileCount).toBe(1);
63
- expect(result.failedFileCount).toBe(1);
64
- expect(result.passedFileCount).toBe(0);
65
- expect(result.errors).toEqual(["worker failed", "graph failed"]);
66
- expect(result.suites[0].framework).toBe("default");
67
- expect(result.suites[0].failedFileCount).toBe(1);
68
- expect(result.suites[0].files).toEqual([
69
- {
70
- path: "tests/health.js",
71
- failed: true,
72
- status: "failed",
73
- durationMs: 250,
74
- error: "boom",
75
- reason: null,
76
- },
77
- ]);
78
- });
79
-
80
- it("reports service duration as wall-clock time, not accumulated file time", () => {
81
- const trackers = buildServiceTrackers(
82
- [
83
- {
84
- skipped: false,
85
- config: {
86
- name: "frontend",
87
- testkit: {
88
- database: {
89
- selectedBackend: null,
90
- },
91
- },
92
- },
93
- suites: [
94
- {
95
- name: "browser",
96
- type: "e2e",
97
- framework: "playwright",
98
- files: ["tests/a.pw.testkit.ts", "tests/b.pw.testkit.ts"],
99
- orderIndex: 0,
100
- },
101
- ],
102
- },
103
- ],
104
- 1000
105
- );
106
-
107
- recordTaskOutcome(
108
- trackers,
109
- {
110
- serviceName: "frontend",
111
- suiteKey: "e2e:browser",
112
- file: "tests/a.pw.testkit.ts",
113
- },
114
- {
115
- failed: false,
116
- durationMs: 30_000,
117
- startedAt: 1000,
118
- finishedAt: 8000,
119
- error: null,
120
- },
121
- 8000
122
- );
123
- recordTaskOutcome(
124
- trackers,
125
- {
126
- serviceName: "frontend",
127
- suiteKey: "e2e:browser",
128
- file: "tests/b.pw.testkit.ts",
129
- },
130
- {
131
- failed: false,
132
- durationMs: 45_000,
133
- startedAt: 3000,
134
- finishedAt: 9000,
135
- error: null,
136
- },
137
- 9000
138
- );
139
-
140
- const result = finalizeServiceResult(trackers.get("frontend"), 1000, 10_000);
141
-
142
- expect(result.durationMs).toBe(8000);
143
- expect(result.totalTaskDurationMs).toBe(75_000);
144
- expect(result.suites[0].durationMs).toBe(75_000);
145
- });
146
-
147
- it("handles epoch-zero task timestamps when calculating wall-clock duration", () => {
148
- const trackers = buildServiceTrackers(
149
- [
150
- {
151
- skipped: false,
152
- config: {
153
- name: "frontend",
154
- testkit: {
155
- database: {
156
- selectedBackend: null,
157
- },
158
- },
159
- },
160
- suites: [
161
- {
162
- name: "browser",
163
- type: "e2e",
164
- framework: "playwright",
165
- files: ["tests/a.pw.testkit.ts"],
166
- orderIndex: 0,
167
- },
168
- ],
169
- },
170
- ],
171
- 0
172
- );
173
-
174
- recordTaskOutcome(
175
- trackers,
176
- {
177
- serviceName: "frontend",
178
- suiteKey: "e2e:browser",
179
- file: "tests/a.pw.testkit.ts",
180
- },
181
- {
182
- failed: false,
183
- durationMs: 3_000,
184
- startedAt: 0,
185
- finishedAt: 8_000,
186
- error: null,
187
- },
188
- 8_000
189
- );
190
-
191
- const result = finalizeServiceResult(trackers.get("frontend"), 0, 10_000);
192
-
193
- expect(result.durationMs).toBe(8_000);
194
- expect(result.totalTaskDurationMs).toBe(3_000);
195
- });
196
-
197
- it("counts config-skipped files and runtime-skipped files separately from passed work", () => {
198
- const trackers = buildServiceTrackers(
199
- [
200
- {
201
- skipped: false,
202
- config: {
203
- name: "api",
204
- testkit: {
205
- database: {
206
- selectedBackend: null,
207
- },
208
- },
209
- },
210
- suites: [
211
- {
212
- name: "billing",
213
- type: "integration",
214
- framework: "k6",
215
- files: ["tests/billing-live.int.testkit.ts"],
216
- skippedFiles: [
217
- {
218
- path: "tests/billing-stubbed.int.testkit.ts",
219
- reason: "Billing is stubbed",
220
- },
221
- ],
222
- totalFileCount: 2,
223
- orderIndex: 0,
224
- },
225
- {
226
- name: "frontend-smoke",
227
- type: "e2e",
228
- framework: "playwright",
229
- files: ["tests/frontend-smoke.pw.testkit.ts"],
230
- orderIndex: 1,
231
- },
232
- ],
233
- },
234
- ],
235
- 1000
236
- );
237
-
238
- recordTaskOutcome(
239
- trackers,
240
- {
241
- serviceName: "api",
242
- suiteKey: "integration:billing",
243
- file: "tests/billing-live.int.testkit.ts",
244
- },
245
- {
246
- failed: false,
247
- durationMs: 100,
248
- error: null,
249
- },
250
- 1100
251
- );
252
- recordTaskOutcome(
253
- trackers,
254
- {
255
- serviceName: "api",
256
- suiteKey: "e2e:frontend-smoke",
257
- file: "tests/frontend-smoke.pw.testkit.ts",
258
- },
259
- {
260
- failed: false,
261
- status: "skipped",
262
- reason: "Playwright test.skip()",
263
- durationMs: 50,
264
- error: null,
265
- },
266
- 1150
267
- );
268
-
269
- const result = finalizeServiceResult(trackers.get("api"), 1000, 1200);
270
-
271
- expect(result.failed).toBe(false);
272
- expect(result.completedSuiteCount).toBe(2);
273
- expect(result.skippedSuiteCount).toBe(1);
274
- expect(result.totalFileCount).toBe(3);
275
- expect(result.completedFileCount).toBe(1);
276
- expect(result.passedFileCount).toBe(1);
277
- expect(result.failedFileCount).toBe(0);
278
- expect(result.skippedFileCount).toBe(2);
279
- expect(result.notRunFileCount).toBe(0);
280
- expect(result.suites[0].files).toEqual([
281
- {
282
- path: "tests/billing-live.int.testkit.ts",
283
- failed: false,
284
- status: "passed",
285
- durationMs: 100,
286
- error: null,
287
- reason: null,
288
- },
289
- {
290
- path: "tests/billing-stubbed.int.testkit.ts",
291
- failed: false,
292
- status: "skipped",
293
- durationMs: 0,
294
- error: null,
295
- reason: "Billing is stubbed",
296
- },
297
- ]);
298
- expect(result.suites[1].files).toEqual([
299
- {
300
- path: "tests/frontend-smoke.pw.testkit.ts",
301
- failed: false,
302
- status: "skipped",
303
- durationMs: 50,
304
- error: null,
305
- reason: "Playwright test.skip()",
306
- },
307
- ]);
308
- });
309
-
310
- it("preserves not-run task outcomes in suite and service summaries", () => {
311
- const trackers = buildServiceTrackers(
312
- [
313
- {
314
- skipped: false,
315
- config: {
316
- name: "api",
317
- testkit: {
318
- database: {
319
- selectedBackend: null,
320
- },
321
- },
322
- },
323
- suites: [
324
- {
325
- name: "health",
326
- type: "integration",
327
- framework: "k6",
328
- files: ["tests/a.int.testkit.ts", "tests/b.int.testkit.ts"],
329
- orderIndex: 0,
330
- },
331
- ],
332
- },
333
- ],
334
- 1000
335
- );
336
-
337
- recordTaskOutcome(
338
- trackers,
339
- {
340
- serviceName: "api",
341
- suiteKey: "integration:health",
342
- file: "tests/a.int.testkit.ts",
343
- },
344
- {
345
- failed: false,
346
- status: "not_run",
347
- reason: "Graph initialization failed",
348
- durationMs: 0,
349
- error: null,
350
- },
351
- 1000
352
- );
353
-
354
- const result = finalizeServiceResult(trackers.get("api"), 1000, 1200);
355
-
356
- expect(result.completedFileCount).toBe(0);
357
- expect(result.passedFileCount).toBe(0);
358
- expect(result.failedFileCount).toBe(0);
359
- expect(result.skippedFileCount).toBe(0);
360
- expect(result.notRunFileCount).toBe(2);
361
- expect(result.suites[0].files).toContainEqual({
362
- path: "tests/a.int.testkit.ts",
363
- failed: false,
364
- status: "not_run",
365
- durationMs: 0,
366
- error: null,
367
- reason: "Graph initialization failed",
368
- });
369
- });
370
-
371
- it("summarizes mixed db backends", () => {
372
- expect(
373
- summarizeDbBackend([{ dbBackend: "local" }, { dbBackend: "neon" }])
374
- ).toBe("mixed");
375
- });
376
- });