@elench/testkit 0.1.79 → 0.1.81

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 (47) hide show
  1. package/README.md +50 -35
  2. package/lib/cli/args.mjs +2 -14
  3. package/lib/cli/args.test.mjs +1 -17
  4. package/lib/cli/command-helpers.mjs +1 -20
  5. package/lib/cli/entrypoint.mjs +0 -4
  6. package/lib/cli/presentation/colors.mjs +1 -1
  7. package/lib/cli/presentation/failure-presentation.mjs +31 -0
  8. package/lib/cli/presentation/run-reporter.mjs +63 -93
  9. package/lib/cli/presentation/run-reporter.test.mjs +137 -26
  10. package/lib/cli/presentation/summary-box.mjs +45 -0
  11. package/lib/cli/presentation/summary-box.test.mjs +43 -0
  12. package/lib/cli/presentation/terminal-layout.mjs +43 -0
  13. package/lib/cli/presentation/terminal-layout.test.mjs +23 -0
  14. package/lib/cli/viewer.mjs +18 -19
  15. package/lib/config/index.mjs +6 -6
  16. package/lib/config/runtime.mjs +8 -8
  17. package/lib/config-api/index.d.ts +4 -4
  18. package/lib/package.test.mjs +4 -4
  19. package/lib/{known-failures → regressions}/github.mjs +39 -77
  20. package/lib/regressions/github.test.mjs +324 -0
  21. package/lib/regressions/index.d.ts +189 -0
  22. package/lib/{known-failures → regressions}/index.mjs +90 -93
  23. package/lib/{known-failures → regressions}/index.test.mjs +37 -48
  24. package/lib/runner/formatting.mjs +105 -103
  25. package/lib/runner/formatting.test.mjs +94 -131
  26. package/lib/runner/metadata.mjs +1 -1
  27. package/lib/runner/orchestrator.mjs +7 -8
  28. package/lib/runner/regressions.mjs +304 -0
  29. package/lib/runner/{triage.test.mjs → regressions.test.mjs} +50 -36
  30. package/lib/runner/reporting.mjs +2 -2
  31. package/lib/runner/reporting.test.mjs +2 -2
  32. package/lib/runner/run-finalization.mjs +18 -30
  33. package/lib/runner/template-steps.mjs +2 -2
  34. package/lib/runner/worker-loop.mjs +1 -0
  35. package/node_modules/@elench/next-analysis/package.json +1 -1
  36. package/node_modules/@elench/testkit-bridge/package.json +2 -2
  37. package/node_modules/@elench/testkit-protocol/package.json +1 -1
  38. package/node_modules/@elench/ts-analysis/package.json +1 -1
  39. package/package.json +12 -9
  40. package/lib/cli/commands/known-failures/render.mjs +0 -19
  41. package/lib/cli/commands/known-failures/validate.mjs +0 -20
  42. package/lib/cli/known-failures.mjs +0 -164
  43. package/lib/known-failures/github.test.mjs +0 -512
  44. package/lib/known-failures/index.d.ts +0 -192
  45. package/lib/runner/triage.mjs +0 -221
  46. /package/lib/{known-failures → regressions}/github-cache.mjs +0 -0
  47. /package/lib/{known-failures → regressions}/github-transport.mjs +0 -0
@@ -3,17 +3,29 @@ import figures from "figures";
3
3
  import { describe, expect, it } from "vitest";
4
4
  import { createRunReporter } from "./run-reporter.mjs";
5
5
 
6
+ function createCapture(columns = 100) {
7
+ let stdout = "";
8
+ const stream = new Writable({
9
+ write(chunk, _encoding, callback) {
10
+ stdout += chunk.toString();
11
+ callback();
12
+ },
13
+ });
14
+ stream.columns = columns;
15
+ return {
16
+ stream,
17
+ read() {
18
+ return stdout;
19
+ },
20
+ };
21
+ }
22
+
6
23
  describe("run reporter setup output", () => {
7
24
  it("prints concise high-level setup summaries in compact mode", () => {
8
- let stdout = "";
25
+ const capture = createCapture();
9
26
  const reporter = createRunReporter({
10
27
  outputMode: "compact",
11
- stdout: new Writable({
12
- write(chunk, _encoding, callback) {
13
- stdout += chunk.toString();
14
- callback();
15
- },
16
- }),
28
+ stdout: capture.stream,
17
29
  });
18
30
 
19
31
  reporter.setupOperationFinished({
@@ -25,20 +37,15 @@ describe("run reporter setup output", () => {
25
37
  durationMs: 8_000,
26
38
  });
27
39
 
28
- expect(stdout).toContain(`${figures.play} RUN SETUP api template rebuild`);
29
- expect(stdout).toContain("8s");
40
+ expect(capture.read()).toContain(`${figures.play} RUN SETUP api template rebuild`);
41
+ expect(capture.read()).toContain("8s");
30
42
  });
31
43
 
32
44
  it("does not print low-level setup steps in compact mode", () => {
33
- let stdout = "";
45
+ const capture = createCapture();
34
46
  const reporter = createRunReporter({
35
47
  outputMode: "compact",
36
- stdout: new Writable({
37
- write(chunk, _encoding, callback) {
38
- stdout += chunk.toString();
39
- callback();
40
- },
41
- }),
48
+ stdout: capture.stream,
42
49
  });
43
50
 
44
51
  reporter.setupOperationFinished({
@@ -50,19 +57,14 @@ describe("run reporter setup output", () => {
50
57
  durationMs: 8_000,
51
58
  });
52
59
 
53
- expect(stdout).toBe("");
60
+ expect(capture.read()).toBe("");
54
61
  });
55
62
 
56
63
  it("prints concise setup failures", () => {
57
- let stdout = "";
64
+ const capture = createCapture();
58
65
  const reporter = createRunReporter({
59
66
  outputMode: "compact",
60
- stdout: new Writable({
61
- write(chunk, _encoding, callback) {
62
- stdout += chunk.toString();
63
- callback();
64
- },
65
- }),
67
+ stdout: capture.stream,
66
68
  });
67
69
 
68
70
  reporter.setupOperationFinished({
@@ -75,7 +77,116 @@ describe("run reporter setup output", () => {
75
77
  error: "Command failed with exit code 1: node scripts/fail-prepare.mjs",
76
78
  });
77
79
 
78
- expect(stdout).toContain(`${figures.cross} FAIL SETUP api runtime:prepare`);
79
- expect(stdout).toContain("Command failed with exit code 1");
80
+ expect(capture.read()).toContain(`${figures.cross} FAIL SETUP api runtime:prepare`);
81
+ expect(capture.read()).toContain("Command failed with exit code 1");
82
+ });
83
+ });
84
+
85
+ describe("run reporter task output", () => {
86
+ it("prints failure details on lines beneath the failed file result", () => {
87
+ const capture = createCapture(88);
88
+ const reporter = createRunReporter({
89
+ outputMode: "compact",
90
+ stdout: capture.stream,
91
+ });
92
+
93
+ reporter.setTotalFileCount(3);
94
+ reporter.taskFinished(
95
+ {
96
+ serviceName: "api",
97
+ type: "integration",
98
+ framework: "k6",
99
+ file: "__testkit__/health/health.int.testkit.ts",
100
+ },
101
+ {
102
+ status: "failed",
103
+ failed: true,
104
+ durationMs: 4_000,
105
+ error: "Default runtime thresholds failed: checks(rate==1.0)",
106
+ failureDetails: [
107
+ {
108
+ kind: "http-assertion",
109
+ title: "status is 200",
110
+ message: "GET /health expected 200, got 404",
111
+ request: {
112
+ method: "GET",
113
+ path: "/health",
114
+ requestId: "req-1",
115
+ },
116
+ response: {
117
+ status: 404,
118
+ bodyPreview: '{"error":"route not found"}',
119
+ },
120
+ },
121
+ ],
122
+ }
123
+ );
124
+
125
+ const lines = capture.read().trimEnd().split("\n");
126
+ expect(lines[0]).toContain("[1/3]");
127
+ expect(lines[0]).toContain(`${figures.cross} FAIL api int __testkit__/health/health.int.testkit.ts 4s`);
128
+ expect(lines[1]).toBe(" GET /health expected 200, got 404");
129
+ expect(lines[2]).toContain(' response: {"error":"route not found"}');
130
+ expect(lines[3]).toBe(" regression: new");
131
+ expect(lines[4]).toBe(" logs: requestId=req-1");
132
+ });
133
+
134
+ it("renders a compact aggregate summary box", () => {
135
+ const capture = createCapture(72);
136
+ const reporter = createRunReporter({
137
+ outputMode: "compact",
138
+ stdout: capture.stream,
139
+ });
140
+
141
+ reporter.runSummary(
142
+ [
143
+ {
144
+ name: "api",
145
+ skipped: false,
146
+ failed: true,
147
+ suiteCount: 1,
148
+ completedSuiteCount: 1,
149
+ skippedSuiteCount: 0,
150
+ failedSuiteCount: 1,
151
+ totalFileCount: 3,
152
+ passedFileCount: 2,
153
+ failedFileCount: 1,
154
+ skippedFileCount: 0,
155
+ notRunFileCount: 0,
156
+ durationMs: 10_000,
157
+ suites: [],
158
+ errors: [],
159
+ },
160
+ ],
161
+ 20_000,
162
+ {
163
+ summary: {
164
+ newRegressions: 1,
165
+ knownRegressions: 2,
166
+ fixedKnownRegressions: 3,
167
+ catalogStale: 4,
168
+ catalogSyncUnavailable: false,
169
+ usedStaleCache: true,
170
+ },
171
+ }
172
+ );
173
+
174
+ const output = capture.read();
175
+ expect(output).toContain("┌");
176
+ expect(output).toContain("│ Result");
177
+ expect(output).toContain("FAILED");
178
+ expect(output).toContain("│ Passed");
179
+ expect(output).toContain("│ Failed");
180
+ expect(output).toContain("│ Skipped");
181
+ expect(output).toContain("│ Not run");
182
+ expect(output).toContain("│ Files");
183
+ expect(output).toContain("│ Duration");
184
+ expect(output).toContain("│ New regressions");
185
+ expect(output).toContain("│ Known regressions");
186
+ expect(output).toContain("│ Fixed known");
187
+ expect(output).toContain("│ Catalog stale");
188
+ expect(output).toContain("│ Catalog sync");
189
+ expect(output).not.toContain("Failures:");
190
+ expect(output).not.toContain("Runtime Errors:");
80
191
  });
81
192
  });
@@ -0,0 +1,45 @@
1
+ import figures from "figures";
2
+ import { clamp, getTerminalWidth, measureWidth, padEndVisible, wrapText } from "./terminal-layout.mjs";
3
+
4
+ export function renderSummaryBox(
5
+ rows,
6
+ {
7
+ stdout = process.stdout,
8
+ widthRatio = 0.55,
9
+ minWidth = 30,
10
+ maxWidth = 56,
11
+ minValueWidth = 8,
12
+ maxKeyWidth = 12,
13
+ } = {}
14
+ ) {
15
+ if (!Array.isArray(rows) || rows.length === 0) return [];
16
+
17
+ const terminalWidth = getTerminalWidth(stdout, 100);
18
+ const preferredWidth = clamp(Math.floor(terminalWidth * widthRatio), minWidth, maxWidth);
19
+ const maxRenderableWidth = Math.max(minWidth, Math.min(preferredWidth, terminalWidth - 1));
20
+ const keyWidth = Math.min(
21
+ maxKeyWidth,
22
+ Math.max(...rows.map(([label]) => measureWidth(label)), 6)
23
+ );
24
+ const minBoxWidth = keyWidth + minValueWidth + 7;
25
+ const boxWidth = Math.max(minBoxWidth, maxRenderableWidth);
26
+ const valueWidth = Math.max(minValueWidth, boxWidth - keyWidth - 7);
27
+
28
+ const top = `${figures.lineDownRight}${figures.line.repeat(boxWidth - 2)}${figures.lineDownLeft}`;
29
+ const bottom = `${figures.lineUpRight}${figures.line.repeat(boxWidth - 2)}${figures.lineUpLeft}`;
30
+ const rendered = [top];
31
+
32
+ for (const [label, value] of rows) {
33
+ const wrappedValueLines = wrapText(value, valueWidth);
34
+ for (let index = 0; index < wrappedValueLines.length; index += 1) {
35
+ const keyCell = index === 0 ? padEndVisible(label, keyWidth) : " ".repeat(keyWidth);
36
+ const valueCell = padEndVisible(wrappedValueLines[index], valueWidth);
37
+ rendered.push(
38
+ `${figures.lineVertical} ${keyCell} ${figures.lineVertical} ${valueCell} ${figures.lineVertical}`
39
+ );
40
+ }
41
+ }
42
+
43
+ rendered.push(bottom);
44
+ return rendered;
45
+ }
@@ -0,0 +1,43 @@
1
+ import { Writable } from "stream";
2
+ import { describe, expect, it } from "vitest";
3
+ import { renderSummaryBox } from "./summary-box.mjs";
4
+
5
+ function createStream(columns) {
6
+ const stream = new Writable({
7
+ write(_chunk, _encoding, callback) {
8
+ callback();
9
+ },
10
+ });
11
+ stream.columns = columns;
12
+ return stream;
13
+ }
14
+
15
+ describe("summary box", () => {
16
+ it("renders key/value rows inside a bounded box", () => {
17
+ const lines = renderSummaryBox(
18
+ [
19
+ ["Result", "FAILED"],
20
+ ["Passed", "203"],
21
+ ["Duration", "8m 56s"],
22
+ ],
23
+ { stdout: createStream(80) }
24
+ );
25
+
26
+ expect(lines[0]).toMatch(/^┌/);
27
+ expect(lines.at(-1)).toMatch(/^└/);
28
+ expect(lines.join("\n")).toContain("Result");
29
+ expect(lines.join("\n")).toContain("FAILED");
30
+ });
31
+
32
+ it("wraps long values instead of widening to content length", () => {
33
+ const lines = renderSummaryBox(
34
+ [["Catalog sync", "Used stale GitHub cache while catalog validation was unavailable"]],
35
+ { stdout: createStream(40) }
36
+ );
37
+
38
+ expect(lines.length).toBeGreaterThan(4);
39
+ expect(lines.join("\n")).toContain("Catalog sync");
40
+ expect(lines.join("\n")).toContain("stale");
41
+ expect(lines.join("\n")).toContain("cache");
42
+ });
43
+ });
@@ -0,0 +1,43 @@
1
+ import stringWidth from "string-width";
2
+ import stripAnsi from "strip-ansi";
3
+ import wrapAnsi from "wrap-ansi";
4
+
5
+ export function getTerminalWidth(stream = process.stdout, fallback = 100) {
6
+ const columns = Number(stream?.columns);
7
+ if (Number.isFinite(columns) && columns > 0) return columns;
8
+ return fallback;
9
+ }
10
+
11
+ export function measureWidth(text) {
12
+ return stringWidth(String(text ?? ""));
13
+ }
14
+
15
+ export function stripTerminalFormatting(text) {
16
+ return stripAnsi(String(text ?? ""));
17
+ }
18
+
19
+ export function padEndVisible(text, width) {
20
+ const normalized = String(text ?? "");
21
+ const padding = Math.max(0, width - measureWidth(normalized));
22
+ return `${normalized}${" ".repeat(padding)}`;
23
+ }
24
+
25
+ export function wrapText(text, width) {
26
+ const normalized = String(text ?? "");
27
+ if (width <= 0) return [normalized];
28
+ return wrapAnsi(normalized, width, {
29
+ hard: true,
30
+ trim: false,
31
+ wordWrap: true,
32
+ }).split("\n");
33
+ }
34
+
35
+ export function renderIndentedBlock(text, { width, indent = " " } = {}) {
36
+ const visibleIndent = measureWidth(indent);
37
+ const contentWidth = Math.max(12, width - visibleIndent);
38
+ return wrapText(text, contentWidth).map((line) => `${indent}${line}`);
39
+ }
40
+
41
+ export function clamp(value, min, max) {
42
+ return Math.max(min, Math.min(max, value));
43
+ }
@@ -0,0 +1,23 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { getTerminalWidth, renderIndentedBlock, wrapText } from "./terminal-layout.mjs";
3
+
4
+ describe("terminal layout", () => {
5
+ it("falls back to a default width when stream columns are unavailable", () => {
6
+ expect(getTerminalWidth({}, 91)).toBe(91);
7
+ });
8
+
9
+ it("wraps indented blocks to the provided width", () => {
10
+ const lines = renderIndentedBlock("response: abcdefghijklmnopqrstuvwxyz", {
11
+ width: 20,
12
+ indent: " ",
13
+ });
14
+
15
+ expect(lines[0].startsWith(" ")).toBe(true);
16
+ expect(lines.length).toBeGreaterThan(1);
17
+ });
18
+
19
+ it("hard-wraps long unbroken values", () => {
20
+ const lines = wrapText("abcdefghijklmnopqrstuvwxyz", 8);
21
+ expect(lines.length).toBeGreaterThan(1);
22
+ });
23
+ });
@@ -109,11 +109,11 @@ export function formatFileDetail(productDir, runArtifact, subject, options = {})
109
109
  for (const line of codeFrame) lines.push(` ${line}`);
110
110
  }
111
111
 
112
- if (subject.file.triage) {
112
+ if (subject.file.diagnosis) {
113
113
  lines.push("");
114
- lines.push("Triage:");
115
- const triageLines = formatTriage(subject.file.triage);
116
- for (const line of triageLines) lines.push(` ${line}`);
114
+ lines.push("Diagnosis:");
115
+ const diagnosisLines = formatDiagnosis(subject.file.diagnosis);
116
+ for (const line of diagnosisLines) lines.push(` ${line}`);
117
117
  }
118
118
 
119
119
  const setupOperations = getSetupOperationsForService(runArtifact, subject.service.name);
@@ -290,30 +290,29 @@ function formatResponseLine(detail) {
290
290
  return parts.join(" ");
291
291
  }
292
292
 
293
- function formatTriage(triage) {
294
- const lines = [`status: ${triage.status}`];
295
- if (triage.classifications?.length) {
296
- lines.push(`classification: ${triage.classifications.join(", ")}`);
293
+ function formatDiagnosis(diagnosis) {
294
+ const lines = [`status: ${diagnosis.status}`];
295
+ if (diagnosis.classifications?.length) {
296
+ lines.push(`classification: ${diagnosis.classifications.join(", ")}`);
297
297
  }
298
- if (triage.availability?.mode) {
299
- lines.push(
300
- `validation: ${triage.availability.mode}${triage.availability.reason ? ` (${triage.availability.reason})` : ""}`
301
- );
302
- }
303
- for (const entry of triage.entries || []) {
298
+ for (const entry of diagnosis.entries || []) {
304
299
  lines.push(`issue: ${entry.issue.repo}#${entry.issue.number}`);
305
- if (entry.issue.url) lines.push(`url: ${entry.issue.url}`);
300
+ lines.push(`summary: ${entry.summary}`);
301
+ if (entry.github?.url) lines.push(`url: ${entry.github.url}`);
306
302
  if (entry.github?.state) {
307
303
  lines.push(`github state: ${entry.github.state}${entry.github.cached ? " (cache)" : ""}`);
308
304
  }
309
- if (entry.validationStatus) lines.push(`validation status: ${entry.validationStatus}`);
310
- if (entry.findings?.length) {
311
- for (const finding of entry.findings.slice(0, 3)) {
312
- lines.push(`finding: ${finding.message}`);
305
+ if (entry.syncStatus) lines.push(`catalog status: ${entry.syncStatus}`);
306
+ if (entry.catalogFindings?.length) {
307
+ for (const finding of entry.catalogFindings.slice(0, 3)) {
308
+ lines.push(`catalog finding: ${finding.message}`);
313
309
  }
314
310
  }
315
311
  break;
316
312
  }
313
+ if (diagnosis.status === "new_regression") {
314
+ lines.push("next: review .testkit/results/latest.json drafts.newRegressions for a prepared catalog entry");
315
+ }
317
316
  return lines;
318
317
  }
319
318
 
@@ -14,9 +14,9 @@ import {
14
14
  detectNextApp,
15
15
  inferLocalRuntime,
16
16
  normalizeBrowserServiceConfig,
17
+ normalizeRegressionsConfig,
17
18
  normalizeOptionalString,
18
19
  normalizeRepoExecution,
19
- normalizeReportingConfig,
20
20
  normalizeRuntimeConfig,
21
21
  } from "./runtime.mjs";
22
22
  import { normalizeServiceRequirements, normalizeSkipConfig } from "./skip-config.mjs";
@@ -30,7 +30,7 @@ export async function loadConfigContext(opts = {}) {
30
30
  const configContext = opts.configContext || (await loadTestkitConfig(productDir));
31
31
  const { config, configFile } = configContext;
32
32
  const execution = normalizeRepoExecution(config.execution);
33
- const reporting = normalizeReportingConfig(config.reporting);
33
+ const regressions = normalizeRegressionsConfig(config.regressions);
34
34
  const toolchains = normalizeToolchainRegistry(config.toolchains);
35
35
  const discoveryConfig = normalizeRepoDiscoveryConfig(config.discovery);
36
36
  const explicitServices = config.services || {};
@@ -54,7 +54,7 @@ export async function loadConfigContext(opts = {}) {
54
54
  configFile,
55
55
  execution,
56
56
  discovery: discoveryConfig,
57
- reporting,
57
+ regressions,
58
58
  toolchains,
59
59
  explicitService: explicitServices[name] || {},
60
60
  discoveredService: discovery.services[name] || null,
@@ -71,7 +71,7 @@ export async function loadConfigContext(opts = {}) {
71
71
  configFile,
72
72
  execution,
73
73
  discovery: discoveryConfig,
74
- reporting,
74
+ regressions,
75
75
  toolchains,
76
76
  explicitServices,
77
77
  discovery,
@@ -102,7 +102,7 @@ function normalizeServiceConfig({
102
102
  configFile,
103
103
  execution,
104
104
  discovery,
105
- reporting,
105
+ regressions,
106
106
  toolchains,
107
107
  explicitService,
108
108
  discoveredService,
@@ -156,7 +156,7 @@ function normalizeServiceConfig({
156
156
  suites,
157
157
  testkit: {
158
158
  execution,
159
- reporting,
159
+ regressions,
160
160
  dependsOn: explicitService.dependsOn || [],
161
161
  discovery: normalizedDiscovery,
162
162
  database,
@@ -15,23 +15,23 @@ import {
15
15
  parseModuleSpecifier,
16
16
  } from "../shared/configured-steps.mjs";
17
17
  import { buildConfigToPrepare, normalizeBuildConfig } from "../shared/build-config.mjs";
18
- import { normalizeKnownFailureIssueValidationConfig } from "../known-failures/github.mjs";
18
+ import { normalizeRegressionSyncConfig } from "../regressions/github.mjs";
19
19
  import { normalizeRuntimeToolchain } from "../toolchains/index.mjs";
20
20
  import { resolveServiceCwd } from "./paths.mjs";
21
21
 
22
- export function normalizeReportingConfig(value) {
22
+ export function normalizeRegressionsConfig(value) {
23
23
  if (!value) return null;
24
24
 
25
- const knownFailuresFile = normalizeOptionalString(value.knownFailuresFile);
26
- if (!knownFailuresFile) {
27
- throw new Error('testkit.config.ts reporting.knownFailuresFile must be a non-empty string');
25
+ const file = normalizeOptionalString(value.file);
26
+ if (!file) {
27
+ throw new Error('testkit.config.ts regressions.file must be a non-empty string');
28
28
  }
29
29
 
30
- const issueValidation = normalizeKnownFailureIssueValidationConfig(value.issueValidation);
30
+ const sync = normalizeRegressionSyncConfig(value.sync);
31
31
 
32
32
  return {
33
- knownFailuresFile,
34
- issueValidation,
33
+ file,
34
+ sync,
35
35
  };
36
36
  }
37
37
 
@@ -143,7 +143,7 @@ export interface BrowserServiceConfig {
143
143
  origins?: string[];
144
144
  }
145
145
 
146
- export interface KnownFailureIssueValidationConfig {
146
+ export interface RegressionSyncConfig {
147
147
  provider?: "github";
148
148
  mode?: "off" | "warn" | "error";
149
149
  cacheTtlSeconds?: number;
@@ -412,9 +412,9 @@ export interface TestkitConfig {
412
412
  profiles?: {
413
413
  http?: Record<string, HttpSuiteConfig<any>>;
414
414
  };
415
- reporting?: {
416
- knownFailuresFile?: string;
417
- issueValidation?: KnownFailureIssueValidationConfig;
415
+ regressions?: {
416
+ file?: string;
417
+ sync?: RegressionSyncConfig;
418
418
  };
419
419
  services?: Record<string, ServiceConfig>;
420
420
  toolchains?: Record<string, ToolchainConfig>;
@@ -42,9 +42,9 @@ describe("package metadata", () => {
42
42
  types: "./lib/discovery/index.d.ts",
43
43
  default: "./lib/discovery/index.mjs",
44
44
  });
45
- expect(packageJson.exports["./known-failures"]).toEqual({
46
- types: "./lib/known-failures/index.d.ts",
47
- default: "./lib/known-failures/index.mjs",
45
+ expect(packageJson.exports["./regressions"]).toEqual({
46
+ types: "./lib/regressions/index.d.ts",
47
+ default: "./lib/regressions/index.mjs",
48
48
  });
49
49
  expect(fs.existsSync(path.join(rootDir, "lib", "index.d.ts"))).toBe(true);
50
50
  expect(fs.existsSync(path.join(rootDir, "lib", "config-api", "index.d.ts"))).toBe(true);
@@ -54,6 +54,6 @@ describe("package metadata", () => {
54
54
  expect(fs.existsSync(path.join(rootDir, "lib", "runtime", "index.d.ts"))).toBe(true);
55
55
  expect(fs.existsSync(path.join(rootDir, "lib", "vitest", "index.d.ts"))).toBe(true);
56
56
  expect(fs.existsSync(path.join(rootDir, "lib", "discovery", "index.d.ts"))).toBe(true);
57
- expect(fs.existsSync(path.join(rootDir, "lib", "known-failures", "index.d.ts"))).toBe(true);
57
+ expect(fs.existsSync(path.join(rootDir, "lib", "regressions", "index.d.ts"))).toBe(true);
58
58
  });
59
59
  });