@vitest-agent/ui 4.0.1 → 5.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.
Files changed (39) hide show
  1. package/README.md +3 -3
  2. package/dispatcher/cells/single-file-fail.js +1 -5
  3. package/dispatcher/cells/single-file-pass.js +1 -5
  4. package/dispatcher/cells/single-file-threshold.js +3 -8
  5. package/dispatcher/cells/single-project-fail.js +1 -5
  6. package/dispatcher/cells/single-project-pass.js +1 -5
  7. package/dispatcher/cells/single-project-threshold.js +4 -8
  8. package/dispatcher/cells/single-test-fail.js +1 -5
  9. package/dispatcher/cells/single-test-pass.js +1 -5
  10. package/dispatcher/cells/workspace-fail.js +1 -5
  11. package/dispatcher/cells/workspace-pass.js +1 -5
  12. package/dispatcher/cells/workspace-threshold.js +4 -8
  13. package/dispatcher/classify.js +6 -1
  14. package/dispatcher/dispatch.js +20 -25
  15. package/dispatcher/helpers.js +52 -3
  16. package/index.d.ts +148 -316
  17. package/index.js +5 -18
  18. package/{render-ink → ink}/CountColumns.js +2 -2
  19. package/{render-ink → ink}/CoverageBlock.js +2 -2
  20. package/{render-ink → ink}/FailureSection.js +2 -2
  21. package/{render-ink → ink}/FailuresSection.js +2 -2
  22. package/{render-ink → ink}/ModuleHeader.js +1 -1
  23. package/{render-ink → ink}/ProjectRow.js +1 -1
  24. package/{render-ink → ink}/StatusIcon.js +2 -2
  25. package/{render-ink → ink}/StreamApp.js +14 -5
  26. package/{render-ink → ink}/SuggestedActions.js +2 -2
  27. package/{render-ink → ink}/TagColumns.js +1 -1
  28. package/{render-ink → ink}/TestRow.js +1 -1
  29. package/{render-ink → ink}/TrendLine.js +2 -2
  30. package/ink/dispatch-ink.js +61 -0
  31. package/{dispatcher → ink}/ink-helpers.js +1 -1
  32. package/ink.d.ts +789 -0
  33. package/ink.js +15 -0
  34. package/package.json +12 -7
  35. package/reducer.js +4 -2
  36. package/render-agent.js +4 -1
  37. package/{render-ink/spinner.js → spinner.js} +1 -1
  38. package/synthesize.js +22 -7
  39. package/render-ink/index.js +0 -15
package/ink.js ADDED
@@ -0,0 +1,15 @@
1
+ import { CountColumns, DURATION_CELL_WIDTH } from "./ink/CountColumns.js";
2
+ import { CoverageBlock } from "./ink/CoverageBlock.js";
3
+ import { dispatchInk, inkDispatcherTable } from "./ink/dispatch-ink.js";
4
+ import { FailureSection } from "./ink/FailureSection.js";
5
+ import { FailuresSection } from "./ink/FailuresSection.js";
6
+ import { StatusIcon } from "./ink/StatusIcon.js";
7
+ import { ModuleHeader } from "./ink/ModuleHeader.js";
8
+ import { TagColumns, tagUnion } from "./ink/TagColumns.js";
9
+ import { ProjectRow } from "./ink/ProjectRow.js";
10
+ import { TestRow } from "./ink/TestRow.js";
11
+ import { TrendLine } from "./ink/TrendLine.js";
12
+ import { StreamApp } from "./ink/StreamApp.js";
13
+ import { SuggestedActions } from "./ink/SuggestedActions.js";
14
+
15
+ export { CountColumns, CoverageBlock, DURATION_CELL_WIDTH, FailureSection, FailuresSection, ModuleHeader, ProjectRow, StatusIcon, StreamApp, SuggestedActions, TagColumns, TestRow, TrendLine, dispatchInk, inkDispatcherTable, tagUnion };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitest-agent/ui",
3
- "version": "4.0.1",
3
+ "version": "5.0.0",
4
4
  "private": false,
5
5
  "description": "Shared event-sourced renderer for vitest-agent. React Ink view for humans, plain-string view for agents, both fed by the same reducer over a RunEvent stream.",
6
6
  "keywords": [
@@ -36,26 +36,31 @@
36
36
  "import": "./index.js",
37
37
  "default": "./index.js"
38
38
  },
39
+ "./ink": {
40
+ "types": "./ink.d.ts",
41
+ "import": "./ink.js",
42
+ "default": "./ink.js"
43
+ },
39
44
  "./package.json": "./package.json"
40
45
  },
41
46
  "dependencies": {
42
- "@vitest-agent/sdk": "6.0.0",
43
- "effect": "^4.0.0"
47
+ "@vitest-agent/sdk": "7.0.0",
48
+ "effect": "^4.0.2"
44
49
  },
45
50
  "peerDependencies": {
46
- "@effected/cli": "^0.12.0",
51
+ "@effected/cli": "^0.15.0",
47
52
  "@effected/env": "^0.1.0",
48
53
  "@effected/glob": "^0.10.0",
49
54
  "@effected/walker": "^0.15.0",
50
- "ink": "^7.1.0",
55
+ "ink": "^8.0.0",
51
56
  "react": "^19.3.0"
52
57
  },
53
58
  "peerDependenciesMeta": {
54
59
  "ink": {
55
- "optional": false
60
+ "optional": true
56
61
  },
57
62
  "react": {
58
- "optional": false
63
+ "optional": true
59
64
  }
60
65
  },
61
66
  "engines": {
package/reducer.js CHANGED
@@ -178,7 +178,8 @@ const reduceRenderState = (state, event) => {
178
178
  violations: state.coverage?.violations ?? [],
179
179
  ...e.scoped !== void 0 ? { scoped: e.scoped } : {},
180
180
  ...e.scopedFiles !== void 0 ? { scopedFiles: e.scopedFiles } : {},
181
- ...e.totalFiles !== void 0 ? { totalFiles: e.totalFiles } : {}
181
+ ...e.totalFiles !== void 0 ? { totalFiles: e.totalFiles } : {},
182
+ ...e.globShortfalls !== void 0 ? { globShortfalls: e.globShortfalls } : {}
182
183
  }
183
184
  }),
184
185
  ThresholdViolation: (e) => {
@@ -223,7 +224,8 @@ const reduceRenderState = (state, event) => {
223
224
  durationMs: e.durationMs
224
225
  },
225
226
  ...e.collectedModules !== void 0 && { collectedModules: e.collectedModules },
226
- ...e.unhandledErrors !== void 0 && { unhandledErrors: e.unhandledErrors }
227
+ ...e.unhandledErrors !== void 0 && { unhandledErrors: e.unhandledErrors },
228
+ ...e.strayOutput !== void 0 && { strayOutput: e.strayOutput }
227
229
  }),
228
230
  RunTimedOut: () => ({
229
231
  ...state,
package/render-agent.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { formatTotalsLine } from "./counts.js";
2
- import { formatFailure as formatFailure$1 } from "./dispatcher/helpers.js";
2
+ import { formatFailure as formatFailure$1, formatGlobShortfallLines } from "./dispatcher/helpers.js";
3
+ import { formatStrayOutputNote } from "@vitest-agent/sdk";
3
4
  import { Fmt } from "@effected/cli";
4
5
 
5
6
  //#region src/render-agent.ts
@@ -91,6 +92,7 @@ const formatCoverageSection = (state, maxGaps) => {
91
92
  lines.push("Violations:");
92
93
  for (const v of cov.violations) lines.push(`- ${v.metric}: ${formatPercent(v.actual)} < ${formatPercent(v.expected)}`);
93
94
  }
95
+ lines.push(...formatGlobShortfallLines(cov.globShortfalls));
94
96
  if (maxGaps > 0 && cov.gaps.length > 0) {
95
97
  const topN = [...cov.gaps].sort((a, b) => b.missing.lines - a.missing.lines).slice(0, maxGaps);
96
98
  lines.push("Gaps:");
@@ -140,6 +142,7 @@ const renderAgent = (state, options = {}) => {
140
142
  if (coverage !== null) sections.push(coverage);
141
143
  const actions = formatActionsSection(state);
142
144
  if (actions !== null) sections.push(actions);
145
+ if (state.strayOutput !== void 0) sections.push(formatStrayOutputNote(state.strayOutput).join("\n"));
143
146
  return `${sections.join("\n\n")}\n`;
144
147
  };
145
148
 
@@ -1,6 +1,6 @@
1
1
  import { Glyphs } from "@effected/cli";
2
2
 
3
- //#region src/render-ink/spinner.ts
3
+ //#region src/spinner.ts
4
4
  /**
5
5
  * The Unicode spinner frames, in animation order (`Glyphs.unicode.spinner`).
6
6
  *
package/synthesize.js CHANGED
@@ -10,6 +10,16 @@ import { isTimeoutError } from "@vitest-agent/sdk";
10
10
  * @public
11
11
  */
12
12
  const SUITE_LOAD_FAILURE_LABEL = "test suite failed to load";
13
+ /**
14
+ * Synthetic test name for a suite-level failure in a module that loaded
15
+ * and collected one or more test cases — a failing `beforeAll` or
16
+ * `afterAll` hook, for example. The file imported fine, so
17
+ * {@link SUITE_LOAD_FAILURE_LABEL} would mislead; this label is used
18
+ * instead when the module has collected tests.
19
+ *
20
+ * @public
21
+ */
22
+ const SUITE_FAILURE_LABEL = "test suite failed";
13
23
  const ISO_ZERO = "1970-01-01T00:00:00.000Z";
14
24
  const normalizeTestState = (state) => {
15
25
  if (state === "passed") return "passed";
@@ -150,7 +160,8 @@ const synthesizeRunEvents = (modules, options = {}) => {
150
160
  gaps: cov.gaps,
151
161
  ...cov.scoped !== void 0 ? { scoped: cov.scoped } : {},
152
162
  ...cov.scopedFiles !== void 0 ? { scopedFiles: cov.scopedFiles } : {},
153
- ...cov.totalFiles !== void 0 ? { totalFiles: cov.totalFiles } : {}
163
+ ...cov.totalFiles !== void 0 ? { totalFiles: cov.totalFiles } : {},
164
+ ...cov.globShortfalls !== void 0 ? { globShortfalls: cov.globShortfalls } : {}
154
165
  });
155
166
  if (cov.violations !== void 0) for (const v of cov.violations) events.push({
156
167
  _tag: "ThresholdViolation",
@@ -218,7 +229,8 @@ const coverageReportToBlock = (report) => {
218
229
  violations,
219
230
  ...cov.scoped ? { scoped: cov.scoped } : {},
220
231
  ...cov.scopedFiles !== void 0 ? { scopedFiles: cov.scopedFiles.length } : {},
221
- ...cov.totalFiles !== void 0 ? { totalFiles: cov.totalFiles } : {}
232
+ ...cov.totalFiles !== void 0 ? { totalFiles: cov.totalFiles } : {},
233
+ ...cov.globShortfalls !== void 0 ? { globShortfalls: cov.globShortfalls } : {}
222
234
  };
223
235
  };
224
236
  /**
@@ -300,16 +312,17 @@ const synthesizeFromAgentReport = (report, options = {}) => {
300
312
  fail = 1;
301
313
  suiteFailureCount++;
302
314
  const moduleError = mod.errors?.[0];
315
+ const suiteLabel = mod.tests.length > 0 ? SUITE_FAILURE_LABEL : SUITE_LOAD_FAILURE_LABEL;
303
316
  events.push({
304
317
  _tag: "TestStarted",
305
318
  modulePath: mod.file,
306
- testName: SUITE_LOAD_FAILURE_LABEL,
319
+ testName: suiteLabel,
307
320
  suitePath: []
308
321
  });
309
322
  events.push({
310
323
  _tag: "TestFinished",
311
324
  modulePath: mod.file,
312
- testName: SUITE_LOAD_FAILURE_LABEL,
325
+ testName: suiteLabel,
313
326
  suitePath: [],
314
327
  status: "failed",
315
328
  durationMs: 0,
@@ -340,7 +353,8 @@ const synthesizeFromAgentReport = (report, options = {}) => {
340
353
  gaps: coverage.gaps,
341
354
  ...coverage.scoped !== void 0 ? { scoped: coverage.scoped } : {},
342
355
  ...coverage.scopedFiles !== void 0 ? { scopedFiles: coverage.scopedFiles } : {},
343
- ...coverage.totalFiles !== void 0 ? { totalFiles: coverage.totalFiles } : {}
356
+ ...coverage.totalFiles !== void 0 ? { totalFiles: coverage.totalFiles } : {},
357
+ ...coverage.globShortfalls !== void 0 ? { globShortfalls: coverage.globShortfalls } : {}
344
358
  });
345
359
  if (coverage.violations !== void 0) for (const v of coverage.violations) events.push({
346
360
  _tag: "ThresholdViolation",
@@ -372,10 +386,11 @@ const synthesizeFromAgentReport = (report, options = {}) => {
372
386
  durationMs: report.summary.duration,
373
387
  ...totalTimeoutCount > 0 && { timeoutCount: totalTimeoutCount },
374
388
  ...report.summary.modules !== void 0 && { collectedModules: report.summary.modules },
375
- ...report.unhandledErrors.length > 0 && { unhandledErrors: report.unhandledErrors }
389
+ ...report.unhandledErrors.length > 0 && { unhandledErrors: report.unhandledErrors },
390
+ ...report.strayOutput !== void 0 && { strayOutput: report.strayOutput }
376
391
  });
377
392
  return events;
378
393
  };
379
394
 
380
395
  //#endregion
381
- export { SUITE_LOAD_FAILURE_LABEL, synthesizeFromAgentReport, synthesizeRunEvents };
396
+ export { SUITE_FAILURE_LABEL, SUITE_LOAD_FAILURE_LABEL, synthesizeFromAgentReport, synthesizeRunEvents };
@@ -1,15 +0,0 @@
1
- import { CountColumns, DURATION_CELL_WIDTH } from "./CountColumns.js";
2
- import { CoverageBlock } from "./CoverageBlock.js";
3
- import { FailureSection } from "./FailureSection.js";
4
- import { FailuresSection } from "./FailuresSection.js";
5
- import { StatusIcon } from "./StatusIcon.js";
6
- import { ModuleHeader } from "./ModuleHeader.js";
7
- import { TagColumns, tagUnion } from "./TagColumns.js";
8
- import { ProjectRow } from "./ProjectRow.js";
9
- import { SPINNER_FRAMES, SPINNER_FRAME_MS, spinnerFrame } from "./spinner.js";
10
- import { TestRow } from "./TestRow.js";
11
- import { TrendLine } from "./TrendLine.js";
12
- import { StreamApp } from "./StreamApp.js";
13
- import { SuggestedActions } from "./SuggestedActions.js";
14
-
15
- export { CountColumns, CoverageBlock, DURATION_CELL_WIDTH, FailureSection, FailuresSection, ModuleHeader, ProjectRow, SPINNER_FRAMES, SPINNER_FRAME_MS, StatusIcon, StreamApp, SuggestedActions, TagColumns, TestRow, TrendLine, spinnerFrame, tagUnion };