headlamp 0.1.10 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -76,7 +76,7 @@ var init_args = __esm({
76
76
  isSome = (opt) => opt._tag === "some";
77
77
  step = (actions, skipNext = false) => [actions, skipNext];
78
78
  rule = {
79
- when: (predicate, build) => (value, env2) => predicate(value, env2) ? Some(build(value, env2)) : None,
79
+ when: (predicate, build) => (value, env) => predicate(value, env) ? Some(build(value, env)) : None,
80
80
  eq: (flag, build) => rule.when(
81
81
  (value) => value === flag,
82
82
  () => build()
@@ -86,12 +86,12 @@ var init_args = __esm({
86
86
  (value) => build(value)
87
87
  ),
88
88
  inSet: (select, build) => rule.when(
89
- (value, env2) => select(env2).has(value),
89
+ (value, env) => select(env).has(value),
90
90
  (value) => build(value)
91
91
  ),
92
92
  withLookahead: (lookaheadFlag, build) => rule.when(
93
- (value, env2) => value === lookaheadFlag && typeof env2.lookahead === "string" && env2.lookahead.length > 0,
94
- (value, env2) => build(value, env2.lookahead)
93
+ (value, env) => value === lookaheadFlag && typeof env.lookahead === "string" && env.lookahead.length > 0,
94
+ (value, env) => build(value, env.lookahead)
95
95
  )
96
96
  };
97
97
  STRING_EMPTY = "";
@@ -224,7 +224,7 @@ var init_args = __esm({
224
224
  ),
225
225
  rule.startsWith("--testPathPattern=", (value) => step([ActionBuilders.jestArg(value)])),
226
226
  rule.inSet(
227
- (env2) => env2.jestFlags,
227
+ (env) => env.jestFlags,
228
228
  (value) => step([ActionBuilders.jestArg(value)])
229
229
  ),
230
230
  rule.when(
@@ -320,9 +320,9 @@ var init_args = __esm({
320
320
  }
321
321
  const tokenValue = token ?? STRING_EMPTY;
322
322
  const nextToken = tokens[index + INDEX_STEP];
323
- let env2 = { jestFlags: jestOnlyFlags };
323
+ let env = { jestFlags: jestOnlyFlags };
324
324
  if (typeof nextToken === "string" && nextToken.length > 0) {
325
- env2 = { jestFlags: jestOnlyFlags, lookahead: nextToken };
325
+ env = { jestFlags: jestOnlyFlags, lookahead: nextToken };
326
326
  }
327
327
  const firstMatch = (rs, value, envForRules) => {
328
328
  for (const ruleFn of rs) {
@@ -333,7 +333,7 @@ var init_args = __esm({
333
333
  }
334
334
  return None;
335
335
  };
336
- const matched = firstMatch(rules, tokenValue, env2);
336
+ const matched = firstMatch(rules, tokenValue, env);
337
337
  const isTestFileToken = (candidate) => /\.(test|spec)\.[tj]sx?$/.test(candidate) || /(^|\/)tests?\//.test(candidate);
338
338
  const isPathLike = (candidate) => /[\\/]/.test(candidate) || /\.(m?[tj]sx?)$/i.test(candidate);
339
339
  const [matchedActions, shouldSkipNext] = isSome(matched) ? matched.value : (() => {
@@ -593,7 +593,7 @@ var init_TimeoutError = __esm({
593
593
 
594
594
  // node_modules/es-toolkit/dist/promise/delay.mjs
595
595
  function delay(ms, { signal } = {}) {
596
- return new Promise((resolve9, reject) => {
596
+ return new Promise((resolve10, reject) => {
597
597
  const abortError = () => {
598
598
  reject(new AbortError());
599
599
  };
@@ -606,7 +606,7 @@ function delay(ms, { signal } = {}) {
606
606
  }
607
607
  const timeoutId = setTimeout(() => {
608
608
  signal?.removeEventListener("abort", abortHandler);
609
- resolve9();
609
+ resolve10();
610
610
  }, ms);
611
611
  signal?.addEventListener("abort", abortHandler, { once: true });
612
612
  });
@@ -671,11 +671,11 @@ var init_exec = __esm({
671
671
  child.stderr?.on("data", (chunk) => {
672
672
  stderr += String(chunk);
673
673
  });
674
- const exec = new Promise((resolve9, reject) => {
674
+ const exec = new Promise((resolve10, reject) => {
675
675
  child.on("error", reject);
676
676
  child.on(
677
677
  "close",
678
- (code) => Number(code) === 0 ? resolve9(stdout) : reject(new Error(stderr || `exit ${code}`))
678
+ (code) => Number(code) === 0 ? resolve10(stdout) : reject(new Error(stderr || `exit ${code}`))
679
679
  );
680
680
  });
681
681
  try {
@@ -695,7 +695,7 @@ var init_exec = __esm({
695
695
  throw caughtError;
696
696
  }
697
697
  };
698
- runExitCode = async (cmd, args, opts = {}) => new Promise((resolve9, reject) => {
698
+ runExitCode = async (cmd, args, opts = {}) => new Promise((resolve10, reject) => {
699
699
  const child = spawn(cmd, [...args], {
700
700
  cwd: opts.cwd,
701
701
  env: opts.env,
@@ -704,9 +704,9 @@ var init_exec = __esm({
704
704
  windowsHide: true
705
705
  });
706
706
  child.on("error", reject);
707
- child.on("close", (code) => resolve9(Number(code)));
707
+ child.on("close", (code) => resolve10(Number(code)));
708
708
  });
709
- runWithCapture = async (cmd, args, opts) => new Promise((resolve9, reject) => {
709
+ runWithCapture = async (cmd, args, opts) => new Promise((resolve10, reject) => {
710
710
  const child = spawn(cmd, [...args], {
711
711
  cwd: opts.cwd,
712
712
  env: opts.env,
@@ -722,7 +722,7 @@ var init_exec = __esm({
722
722
  buf += String(chunk);
723
723
  });
724
724
  child.on("error", reject);
725
- child.on("close", (code) => resolve9({ code: Number(code), output: buf }));
725
+ child.on("close", (code) => resolve10({ code: Number(code), output: buf }));
726
726
  });
727
727
  }
728
728
  });
@@ -1133,8 +1133,8 @@ var require_utils = __commonJS({
1133
1133
  }
1134
1134
  return output;
1135
1135
  };
1136
- exports.basename = (path11, { windows } = {}) => {
1137
- const segs = path11.split(windows ? /[\\/]/ : "/");
1136
+ exports.basename = (path12, { windows } = {}) => {
1137
+ const segs = path12.split(windows ? /[\\/]/ : "/");
1138
1138
  const last = segs[segs.length - 1];
1139
1139
  if (last === "") {
1140
1140
  return segs[segs.length - 2];
@@ -2250,7 +2250,7 @@ var require_picomatch = __commonJS({
2250
2250
  var parse = require_parse();
2251
2251
  var utils = require_utils();
2252
2252
  var constants = require_constants();
2253
- var isObject = (val) => val && typeof val === "object" && !Array.isArray(val);
2253
+ var isObject2 = (val) => val && typeof val === "object" && !Array.isArray(val);
2254
2254
  var picomatch2 = (glob, options, returnState = false) => {
2255
2255
  if (Array.isArray(glob)) {
2256
2256
  const fns = glob.map((input) => picomatch2(input, options, returnState));
@@ -2263,7 +2263,7 @@ var require_picomatch = __commonJS({
2263
2263
  };
2264
2264
  return arrayMatcher;
2265
2265
  }
2266
- const isState = isObject(glob) && glob.tokens && glob.input;
2266
+ const isState = isObject2(glob) && glob.tokens && glob.input;
2267
2267
  if (glob === "" || typeof glob !== "string" && !isState) {
2268
2268
  throw new TypeError("Expected pattern to be a non-empty string");
2269
2269
  }
@@ -3503,11 +3503,11 @@ var require_lib = __commonJS({
3503
3503
  "node_modules/json5/lib/index.js"(exports, module) {
3504
3504
  var parse = require_parse2();
3505
3505
  var stringify = require_stringify();
3506
- var JSON52 = {
3506
+ var JSON53 = {
3507
3507
  parse,
3508
3508
  stringify
3509
3509
  };
3510
- module.exports = JSON52;
3510
+ module.exports = JSON53;
3511
3511
  }
3512
3512
  });
3513
3513
 
@@ -4705,6 +4705,19 @@ var missedFunctions = (file) => {
4705
4705
  }
4706
4706
  return out.sort((firstFunction, secondFunction) => firstFunction.line - secondFunction.line);
4707
4707
  };
4708
+ var clamp = (value, lowerBound, upperBound) => Math.max(lowerBound, Math.min(upperBound, value));
4709
+ var renderCodeFrame = (source, miss, context = 3) => {
4710
+ const lines = source.split(/\r?\n/);
4711
+ const from = clamp(miss.start - context, 1, lines.length);
4712
+ const to = clamp(miss.end + context, 1, lines.length);
4713
+ const out = [];
4714
+ for (let ln = from; ln <= to; ln += 1) {
4715
+ const body = lines[ln - 1] ?? "";
4716
+ const tag = ln >= miss.start && ln <= miss.end ? `> ${ln.toString().padStart(4)}|` : ` ${ln.toString().padStart(4)}|`;
4717
+ out.push(`${tag} ${body}`);
4718
+ }
4719
+ return out.join("\n");
4720
+ };
4708
4721
  var compositeBarPct = (summary, hotspots) => {
4709
4722
  const base = Math.min(
4710
4723
  Number.isFinite(summary.lines.pct) ? summary.lines.pct : 0,
@@ -4970,7 +4983,7 @@ var printCompactCoverage = async (opts) => {
4970
4983
  );
4971
4984
  }
4972
4985
  };
4973
- var shortenPathPreservingFilename = (relPath, maxWidth, opts) => {
4986
+ var shortenPathPreservingFilename = (relPath2, maxWidth, opts) => {
4974
4987
  const ellipsis = opts?.ellipsis ?? "\u2026";
4975
4988
  const START_HEAD = Math.max(0, opts?.keepHead ?? 1);
4976
4989
  const START_TAIL = Math.max(0, opts?.keepTail ?? 1);
@@ -5142,7 +5155,7 @@ var shortenPathPreservingFilename = (relPath, maxWidth, opts) => {
5142
5155
  }
5143
5156
  return null;
5144
5157
  };
5145
- const normalized = relPath.replace(/\\/g, "/");
5158
+ const normalized = relPath2.replace(/\\/g, "/");
5146
5159
  if (visibleWidth(normalized) <= maxWidth) {
5147
5160
  return normalized;
5148
5161
  }
@@ -5598,34 +5611,81 @@ var printPerFileCompositeTables = async (opts) => {
5598
5611
  }
5599
5612
  };
5600
5613
 
5601
- // src/lib/jest-bridge.ts
5602
- var import_json5 = __toESM(require_lib(), 1);
5603
- import * as path9 from "node:path";
5604
- import * as fs4 from "node:fs";
5605
- import * as util from "node:util";
5606
- var extractBridgePath = (raw, cwd) => {
5607
- const matches = Array.from(
5608
- raw.matchAll(/Test results written to:\s+([^\n\r]+jest-bridge-[^\s'"]+\.json)/g)
5609
- );
5610
- if (!matches.length) {
5611
- return null;
5614
+ // src/lib/fp.ts
5615
+ function pipe(initial, ...fns) {
5616
+ return fns.reduce((acc, fn) => fn(acc), initial);
5617
+ }
5618
+ var some = (value) => ({ tag: "Some", value });
5619
+ var none = { tag: "None" };
5620
+ var unfoldr = (initial, step2) => {
5621
+ const out = [];
5622
+ for (let state = initial; ; ) {
5623
+ const result = step2(state);
5624
+ if (result.tag === "None") {
5625
+ break;
5626
+ }
5627
+ const [element, next] = result.value;
5628
+ out.push(element);
5629
+ state = next;
5612
5630
  }
5613
- const jsonPath = matches[matches.length - 1][1].trim().replace(/^["'`]|["'`]$/g, "");
5614
- return path9.isAbsolute(jsonPath) ? jsonPath : path9.resolve(cwd, jsonPath);
5631
+ return out;
5615
5632
  };
5616
- var drawRule = (label) => {
5617
- const width = Math.max(
5618
- 40,
5619
- process.stdout && process.stdout.columns || 80
5620
- );
5621
- if (!label) {
5622
- return ansi.dim("\u2500".repeat(width));
5633
+
5634
+ // src/lib/formatter/parse.ts
5635
+ var isFailureStart = (lineText) => /^\s*●\s+/.test(lineText);
5636
+ var isSuiteLine = (lineText) => /^\s*(PASS|FAIL)\s+/.test(lineText);
5637
+ var isSummaryLine = (lineText) => /^\s*(Test Suites:|Tests:|Snapshots:|Time:|Ran all)/.test(lineText);
5638
+ var collectFailure = (allLines, startIndex) => {
5639
+ const title = stripAnsiSimple(allLines[startIndex]).replace(/^\s*●\s+/, "").trim();
5640
+ const buf = [allLines[startIndex]];
5641
+ let i = startIndex + 1;
5642
+ for (; i < allLines.length; i += 1) {
5643
+ const simple = stripAnsiSimple(allLines[i]);
5644
+ const nextIsStart = isFailureStart(simple) || isSuiteLine(simple) || isSummaryLine(simple);
5645
+ const prevBlank = stripAnsiSimple(allLines[i - 1] ?? "").trim() === "";
5646
+ if (nextIsStart && prevBlank) {
5647
+ break;
5648
+ }
5649
+ buf.push(allLines[i]);
5623
5650
  }
5624
- const plain = stripAnsiSimple(label);
5625
- const pad = Math.max(1, width - plain.length - 1);
5626
- return `${ansi.dim("\u2500".repeat(pad))} ${label}`;
5651
+ return [{ tag: "FailureBlock", title, lines: buf }, i];
5652
+ };
5653
+ var parseSuite = (lineText) => {
5654
+ const match = lineText.match(/^\s*(PASS|FAIL)\s+(.+)$/);
5655
+ return { tag: "PassFail", badge: match[1], rel: match[2] };
5627
5656
  };
5628
- var env = process.env;
5657
+ var parseChunks = (raw) => {
5658
+ const lines = raw.split(/\r?\n/);
5659
+ return unfoldr({ index: 0 }, (state) => {
5660
+ if (state.index >= lines.length) {
5661
+ return none;
5662
+ }
5663
+ const line = lines[state.index];
5664
+ const simple = stripAnsiSimple(line);
5665
+ if (isFailureStart(simple)) {
5666
+ const [chunk, next] = collectFailure(lines, state.index);
5667
+ return some([chunk, { index: next }]);
5668
+ }
5669
+ if (isSuiteLine(simple)) {
5670
+ return some([parseSuite(simple), { index: state.index + 1 }]);
5671
+ }
5672
+ if (isSummaryLine(simple)) {
5673
+ return some([{ tag: "Summary", line }, { index: state.index + 1 }]);
5674
+ }
5675
+ if (isStackLine(simple)) {
5676
+ return some([{ tag: "Stack", line }, { index: state.index + 1 }]);
5677
+ }
5678
+ return some([{ tag: "Other", line }, { index: state.index + 1 }]);
5679
+ });
5680
+ };
5681
+
5682
+ // src/lib/formatter/render.ts
5683
+ import * as path9 from "node:path";
5684
+
5685
+ // src/lib/formatter/fns.ts
5686
+ var import_json5 = __toESM(require_lib(), 1);
5687
+ import * as fs4 from "node:fs";
5688
+ import * as util from "node:util";
5629
5689
  var colorTokens = {
5630
5690
  pass: Colors.Success,
5631
5691
  fail: Colors.Failure,
@@ -5636,80 +5696,18 @@ var colorTokens = {
5636
5696
  failPill: (text) => BackgroundColors.Failure(ansi.white(` ${text} `)),
5637
5697
  runPill: (text) => BackgroundColors.Run(ansi.white(` ${text} `))
5638
5698
  };
5639
- var MAX_CONSOLE_ERRORS_TO_SHOW = 3;
5640
- var isArrayOfPrimitives = (value) => Array.isArray(value) && value.every(
5641
- (element) => ["string", "number", "boolean"].includes(typeof element) || element === null
5642
- );
5643
- var indentBlock = (text, pad = " ") => text.split("\n").map((line) => line ? pad + line : pad.trimEnd()).join("\n");
5644
- var prettifyPrettyFormatBlock = (raw) => {
5645
- const lines = raw.split("\n");
5646
- if (!lines.length) {
5647
- return raw;
5648
- }
5649
- const first = lines[0] ?? "";
5650
- const isArrayStart = /^\s*(?:Array\s*\[|\[)\s*$/.test(first);
5651
- const isObjectStart = /^\s*(?:Object\s*\{|\{)\s*$/.test(first);
5652
- if (!isArrayStart && !isObjectStart) {
5653
- return raw;
5654
- }
5655
- lines[0] = first.replace(/^(\s*)Array\s*\[/, "$1[").replace(/^(\s*)Object\s*\{/, "$1{").replace(/^\s*\[\s*$/, "[").replace(/^\s*\{\s*$/, "{");
5656
- const closingChar = isArrayStart ? "]" : "}";
5657
- let closeIdx = -1;
5658
- for (let i = 1; i < lines.length; i += 1) {
5659
- if (/^\s*[\]}]\s*$/.test(lines[i])) {
5660
- closeIdx = i;
5661
- break;
5662
- }
5663
- }
5664
- if (closeIdx < 0) {
5665
- return lines.join("\n");
5666
- }
5667
- const inner = lines.slice(1, closeIdx);
5668
- const indents = [];
5669
- for (const lineText of inner) {
5670
- if (lineText.trim().length === 0) {
5671
- continue;
5672
- }
5673
- indents.push(lineText.match(/^\s*/)?.[0]?.length ?? 0);
5674
- }
5675
- const minIndent = indents.length ? Math.min(...indents) : 0;
5676
- const reindented = inner.map((lineText, idx) => {
5677
- if (lineText.trim().length === 0) {
5678
- return lineText;
5679
- }
5680
- const current = lineText.match(/^\s*/)?.[0]?.length ?? 0;
5681
- const rest = lineText.slice(current);
5682
- const extra = Math.max(0, current - minIndent);
5683
- const base = " ";
5684
- const withoutDangling = idx === inner.length - 1 ? rest.replace(/,\s*$/, "") : rest;
5685
- return base + " ".repeat(extra) + withoutDangling;
5686
- });
5687
- lines.splice(1, inner.length, ...reindented);
5688
- lines[closeIdx] = closingChar;
5689
- return lines.join("\n");
5690
- };
5691
- var normalizeBlock = (raw) => raw.replace(/^\s*Array\s*\[/, "[").replace(/^\s*Object\s*\{/, "{").replace(/,(\s*[\]}])/g, "$1");
5692
- var stringifyPrettierish = (value) => {
5693
- if (typeof value === "string") {
5694
- const text = normalizeBlock(value.trim());
5695
- if (/^[[{]/.test(text)) {
5696
- try {
5697
- const parsed = import_json5.default.parse(text);
5698
- return JSON.stringify(parsed, null, 2);
5699
- } catch {
5700
- }
5701
- }
5702
- return value;
5703
- }
5704
- if (Array.isArray(value) || value && typeof value === "object") {
5705
- try {
5706
- return JSON.stringify(value, null, 2);
5707
- } catch {
5708
- }
5699
+ var drawRule = (label) => {
5700
+ const width = Math.max(
5701
+ 40,
5702
+ process.stdout && process.stdout.columns || 80
5703
+ );
5704
+ if (!label) {
5705
+ return ansi.dim("\u2500".repeat(width));
5709
5706
  }
5710
- return util.inspect(value, { depth: 10, breakLength: Infinity, compact: false, sorted: true });
5707
+ const plain = stripAnsiSimple(label);
5708
+ const pad = Math.max(1, width - plain.length - 1);
5709
+ return `${ansi.dim("\u2500".repeat(pad))} ${label}`;
5711
5710
  };
5712
- var drawFailRule = (label = " FAIL ") => drawRule(colorTokens.failPill(label));
5713
5711
  var drawFailLine = () => {
5714
5712
  const width = Math.max(
5715
5713
  40,
@@ -5718,9 +5716,29 @@ var drawFailLine = () => {
5718
5716
  return colorTokens.fail("\u2500".repeat(width));
5719
5717
  };
5720
5718
  var renderRunLine = (cwd) => `${colorTokens.runPill("RUN")} ${ansi.dim(cwd.replace(/\\/g, "/"))}`;
5719
+ var buildFileBadgeLine = (rel, failedCount) => failedCount > 0 ? `${colorTokens.failPill("FAIL")} ${ansi.white(rel)}` : `${colorTokens.passPill("PASS")} ${ansi.white(rel)}`;
5720
+ var buildPerFileOverview = (rel, assertions) => {
5721
+ const out = [];
5722
+ out.push(`${ansi.magenta(rel)} ${ansi.dim(`(${assertions.length})`)}`);
5723
+ for (const assertion of assertions) {
5724
+ const name = assertion.fullName;
5725
+ if (assertion.status === "passed") {
5726
+ out.push(` ${colorTokens.pass("\u2713")} ${ansi.dim(name)}`);
5727
+ } else if (assertion.status === "todo") {
5728
+ out.push(` ${colorTokens.todo("\u2610")} ${ansi.dim(name)} ${colorTokens.todo("[todo]")}`);
5729
+ } else if (assertion.status === "pending") {
5730
+ out.push(` ${colorTokens.skip("\u2193")} ${ansi.dim(name)} ${colorTokens.skip("[skipped]")}`);
5731
+ } else {
5732
+ out.push(` ${colorTokens.fail("\xD7")} ${ansi.white(name)}`);
5733
+ }
5734
+ }
5735
+ out.push("");
5736
+ return out;
5737
+ };
5738
+ var isObjectRecord = (value) => typeof value === "object" && value !== null;
5721
5739
  var colorStackLine = (line, projectHint) => {
5722
5740
  const plainLine = stripAnsiSimple(line);
5723
- if (!isStackLine(plainLine)) {
5741
+ if (!/\s+at\s+/.test(plainLine)) {
5724
5742
  return plainLine;
5725
5743
  }
5726
5744
  const match = plainLine.match(/\(?([^\s()]+):(\d+):(\d+)\)?$/);
@@ -5736,255 +5754,257 @@ var colorStackLine = (line, projectHint) => {
5736
5754
  `(${coloredPath}${ansi.dim(":")}${ansi.white(`${lineNumber}:${columnNumber}`)})`
5737
5755
  );
5738
5756
  };
5739
- var renderCodeFrame = (lines, start) => {
5740
- const out = [];
5741
- for (let i = start; i < lines.length; i += 1) {
5742
- const raw = stripAnsiSimple(lines[i]);
5743
- if (!raw.trim()) {
5744
- break;
5745
- }
5746
- if (/^\s*\^+\s*$/.test(raw)) {
5747
- out.push(` ${colorTokens.fail(raw.trimEnd())}`);
5748
- continue;
5749
- }
5750
- const pointerMatch = raw.match(/^\s*>(\s*\d+)\s*\|\s?(.*)$/);
5751
- if (pointerMatch) {
5752
- const num = ansi.dim(pointerMatch[1].trim());
5753
- const code = ansi.yellow(pointerMatch[2] ?? "");
5754
- out.push(` ${colorTokens.fail(">")} ${num} ${ansi.dim("|")} ${code}`);
5755
- continue;
5756
- }
5757
- const normalMatch = raw.match(/^\s*(\d+)\s*\|\s?(.*)$/);
5758
- if (normalMatch) {
5759
- const num = ansi.dim(normalMatch[1]);
5760
- const code = ansi.dim(normalMatch[2] ?? "");
5761
- out.push(` ${num} ${ansi.dim("|")} ${code}`);
5762
- continue;
5763
- }
5764
- out.push(` ${raw}`);
5757
+ var extractBridgePath = (raw, cwd) => {
5758
+ const re = /Test results written to:\s+([^\n\r]+jest-bridge-[^\s'"]+\.json)/g;
5759
+ const matches = Array.from(raw.matchAll(re));
5760
+ if (matches.length === 0) {
5761
+ return null;
5765
5762
  }
5766
- return out;
5763
+ const jsonPath = (matches[matches.length - 1][1] ?? "").trim().replace(/^["'`]|["'`]$/g, "");
5764
+ return /^\//.test(jsonPath) ? jsonPath : `${cwd.replace(/\\/g, "/")}/${jsonPath}`;
5767
5765
  };
5766
+ var findCodeFrameStart = (lines) => lines.findIndex((line) => /^\s*(>?\s*\d+\s*\|)/.test(stripAnsiSimple(line)));
5768
5767
  var _sourceCache = /* @__PURE__ */ new Map();
5769
5768
  var readSource = (file) => {
5770
- const normalizedFile = file.replace(/\\/g, "/");
5771
- const cached = _sourceCache.get(normalizedFile);
5772
- if (cached) {
5773
- return cached;
5769
+ const normalized = file.replace(/\\/g, "/");
5770
+ const hit = _sourceCache.get(normalized);
5771
+ if (hit) {
5772
+ return hit;
5774
5773
  }
5775
5774
  try {
5776
- const txt = fs4.readFileSync(normalizedFile, "utf8");
5777
- const arr = txt.split(/\r?\n/);
5778
- _sourceCache.set(normalizedFile, arr);
5775
+ const arr = fs4.readFileSync(normalized, "utf8").split(/\r?\n/);
5776
+ _sourceCache.set(normalized, arr);
5779
5777
  return arr;
5780
5778
  } catch {
5781
5779
  return [];
5782
5780
  }
5783
5781
  };
5782
+ var renderInlineCodeFrame = (lines, start) => {
5783
+ const out = [];
5784
+ for (let i = start; i < lines.length; i += 1) {
5785
+ const raw = stripAnsiSimple(lines[i]);
5786
+ if (!raw.trim()) {
5787
+ break;
5788
+ }
5789
+ if (/^\s*\^+\s*$/.test(raw)) {
5790
+ out.push(` ${Colors.Failure(raw.trimEnd())}`);
5791
+ } else {
5792
+ const ptr = raw.match(/^\s*>(\s*\d+)\s*\|\s?(.*)$/);
5793
+ if (ptr) {
5794
+ const num = ansi.dim(ptr[1].trim());
5795
+ const code = ansi.yellow(ptr[2] ?? "");
5796
+ out.push(` ${Colors.Failure(">")} ${num} ${ansi.dim("|")} ${code}`);
5797
+ } else {
5798
+ const nor = raw.match(/^\s*(\d+)\s*\|\s?(.*)$/);
5799
+ if (nor) {
5800
+ const num = ansi.dim(nor[1]);
5801
+ const code = ansi.dim(nor[2] ?? "");
5802
+ out.push(` ${num} ${ansi.dim("|")} ${code}`);
5803
+ } else {
5804
+ out.push(` ${raw}`);
5805
+ }
5806
+ }
5807
+ }
5808
+ }
5809
+ return out;
5810
+ };
5784
5811
  var renderSourceCodeFrame = (file, line, context = 3) => {
5785
5812
  const lines = readSource(file);
5786
- if (!lines.length || !Number.isFinite(line)) {
5813
+ if (lines.length === 0 || !Number.isFinite(line)) {
5787
5814
  return [];
5788
5815
  }
5789
5816
  const idx = Math.max(1, Math.min(line, lines.length));
5790
5817
  const start = Math.max(1, idx - context);
5791
5818
  const end = Math.min(lines.length, idx + context);
5792
5819
  const out = [];
5793
- for (let currentLineNumber = start; currentLineNumber <= end; currentLineNumber += 1) {
5794
- const num = ansi.dim(String(currentLineNumber));
5795
- const code = currentLineNumber === idx ? ansi.yellow(lines[currentLineNumber - 1] ?? "") : ansi.dim(lines[currentLineNumber - 1] ?? "");
5796
- if (currentLineNumber === idx) {
5797
- out.push(` ${colorTokens.fail(">")} ${num} ${ansi.dim("|")} ${code}`);
5820
+ for (let current = start; current <= end; current += 1) {
5821
+ const num = ansi.dim(String(current));
5822
+ const code = current === idx ? ansi.yellow(lines[current - 1] ?? "") : ansi.dim(lines[current - 1] ?? "");
5823
+ if (current === idx) {
5824
+ out.push(` ${Colors.Failure(">")} ${num} ${ansi.dim("|")} ${code}`);
5798
5825
  } else {
5799
5826
  out.push(` ${num} ${ansi.dim("|")} ${code}`);
5800
5827
  }
5801
5828
  }
5802
- out.push(` ${colorTokens.fail("^")}`);
5829
+ out.push(` ${Colors.Failure("^")}`);
5803
5830
  return out;
5804
5831
  };
5805
- var findLastProjectFrameIndex = (lines, projectHint) => {
5806
- for (let i = lines.length - 1; i >= 0; i -= 1) {
5807
- const simple = stripAnsiSimple(lines[i]);
5832
+ var stackLocation = (line) => {
5833
+ const match = stripAnsiSimple(line).match(/\(?([^\s()]+):(\d+):\d+\)?$/);
5834
+ if (!match) {
5835
+ return null;
5836
+ }
5837
+ return { file: match[1].replace(/\\/g, "/"), line: Number(match[2]) };
5838
+ };
5839
+ var deepestProjectLoc = (stackLines, projectHint) => {
5840
+ for (let i = stackLines.length - 1; i >= 0; i -= 1) {
5841
+ const simple = stripAnsiSimple(stackLines[i]);
5808
5842
  if (isStackLine(simple) && projectHint.test(simple) && !/node_modules|vitest|jest/.test(simple)) {
5809
- return i;
5843
+ return stackLocation(stackLines[i]);
5810
5844
  }
5811
5845
  }
5812
- return -1;
5846
+ return null;
5813
5847
  };
5814
- var renderStackTail = (lines, projectHint, max = 4) => {
5815
- const onlyStack = lines.filter((candidateLine) => isStackLine(stripAnsiSimple(candidateLine)));
5816
- if (!onlyStack.length) {
5817
- return [];
5848
+ var buildCodeFrameSection = (messageLines, ctx, synthLoc) => {
5849
+ const out = [];
5850
+ const start = findCodeFrameStart(messageLines);
5851
+ if (start >= 0) {
5852
+ out.push(...renderInlineCodeFrame(messageLines, start), "");
5853
+ return out;
5818
5854
  }
5819
- const tail = onlyStack.slice(-max);
5820
- return tail.map((frameLine) => ` ${colorStackLine(frameLine, projectHint)}`);
5821
- };
5822
- var firstProjectFrames = (lines, projectHint, max = 2) => {
5823
- const onlyStack = lines.filter((ln) => isStackLine(stripAnsiSimple(ln)));
5824
- const projectOnly = onlyStack.filter((ln) => projectHint.test(stripAnsiSimple(ln)));
5825
- return projectOnly.slice(0, max).map((ln) => ` ${colorStackLine(ln, projectHint)}`);
5855
+ if (ctx.showStacks && synthLoc) {
5856
+ out.push(...renderSourceCodeFrame(synthLoc.file, synthLoc.line), "");
5857
+ }
5858
+ return out;
5826
5859
  };
5827
- var isTerminator = (lineText) => !lineText.trim() || isStackLine(lineText);
5828
- var extractAssertionMessage = (msgLines) => {
5829
- const lines = msgLines.map((rawLine) => stripAnsiSimple(rawLine));
5830
- const out = [];
5831
- const hintIdx = lines.findIndex(
5832
- (candidateLine) => /expect\(.+?\)\.(?:to|not\.)/.test(candidateLine) || /\b(?:AssertionError|Error):/.test(candidateLine)
5833
- );
5834
- if (hintIdx >= 0) {
5835
- out.push(lines[hintIdx]);
5860
+ var normalizeBlock = (raw) => raw.replace(/^\s*Array\s*\[/, "[").replace(/^\s*Object\s*\{/, "{").replace(/,(\s*[\]}])/g, "$1");
5861
+ var stringifyPrettierish = (value) => {
5862
+ if (typeof value === "string") {
5863
+ const text = normalizeBlock(value.trim());
5864
+ try {
5865
+ const parsed = import_json5.default.parse(text);
5866
+ return JSON.stringify(parsed, null, 2);
5867
+ } catch {
5868
+ return value;
5869
+ }
5836
5870
  }
5837
- const collectBlock = (start) => {
5838
- out.push(lines[start]);
5839
- for (let i = start + 1; i < lines.length; i += 1) {
5840
- const candidate = lines[i];
5841
- if (isTerminator(candidate)) {
5842
- break;
5843
- }
5844
- out.push(candidate);
5871
+ if (Array.isArray(value) || isObjectRecord(value)) {
5872
+ try {
5873
+ return JSON.stringify(value, null, 2);
5874
+ } catch {
5875
+ return util.inspect(value, {
5876
+ depth: 10,
5877
+ breakLength: Infinity,
5878
+ compact: false,
5879
+ sorted: true
5880
+ });
5845
5881
  }
5846
- };
5847
- const expectedIdx = lines.findIndex(
5848
- (candidateLine) => /^\s*Expected:/.test(candidateLine)
5849
- );
5850
- const receivedIdx = lines.findIndex(
5851
- (candidateLine) => /^\s*Received:/.test(candidateLine)
5852
- );
5853
- const diffIdx = lines.findIndex(
5854
- (candidateLine) => /^\s*(?:- Expected|\+ Received|Difference:)/.test(candidateLine)
5855
- );
5856
- if (expectedIdx >= 0) {
5857
- collectBlock(expectedIdx);
5858
5882
  }
5859
- if (receivedIdx >= 0) {
5860
- collectBlock(receivedIdx);
5883
+ return util.inspect(value, {
5884
+ depth: 10,
5885
+ breakLength: Infinity,
5886
+ compact: false,
5887
+ sorted: true
5888
+ });
5889
+ };
5890
+ var isArrayOfPrimitives = (value) => Array.isArray(value) && value.every(
5891
+ (element) => ["string", "number", "boolean"].includes(typeof element) || element === null
5892
+ );
5893
+ var extractFromUnifiedDiff = (rawLines) => {
5894
+ const lines = (rawLines ?? []).map((lineText) => stripAnsiSimple(lineText));
5895
+ let startIndex = -1;
5896
+ for (let i = 0; i < lines.length; i += 1) {
5897
+ const lt = lines[i];
5898
+ if (/^\s*(?:[-+]\s*)?(Array\s*\[|Object\s*\{)/.test(lt)) {
5899
+ startIndex = i;
5900
+ break;
5901
+ }
5861
5902
  }
5862
- if (diffIdx >= 0) {
5863
- collectBlock(diffIdx);
5903
+ if (startIndex < 0) {
5904
+ return {};
5864
5905
  }
5865
- if (out.length === 0 && hintIdx >= 0) {
5866
- for (let i = hintIdx + 1; i < lines.length && out.length < 4; i += 1) {
5867
- const candidate = lines[i];
5868
- if (isTerminator(candidate)) {
5869
- break;
5906
+ const expectedParts = [];
5907
+ const receivedParts = [];
5908
+ let opened = false;
5909
+ let expDone = false;
5910
+ let recDone = false;
5911
+ const canParseJsonish = (input) => {
5912
+ const text = normalizeBlock(input).trim();
5913
+ try {
5914
+ import_json5.default.parse(text);
5915
+ return true;
5916
+ } catch {
5917
+ return false;
5918
+ }
5919
+ };
5920
+ for (let i = startIndex; i < lines.length; i += 1) {
5921
+ const lineText = lines[i];
5922
+ const unsigned = lineText.replace(/^\s*[-+]\s?/, "");
5923
+ const isMinus = /^\s*-\s/.test(lineText);
5924
+ const isPlus = /^\s*\+\s/.test(lineText);
5925
+ if (!opened) {
5926
+ const looksLikeStart = /^\s*(Array\s*\[|Object\s*\{)/.test(unsigned);
5927
+ if (!looksLikeStart) {
5928
+ continue;
5870
5929
  }
5871
- out.push(candidate);
5930
+ opened = true;
5931
+ }
5932
+ if (isMinus) {
5933
+ expectedParts.push(unsigned);
5934
+ } else if (isPlus) {
5935
+ receivedParts.push(unsigned);
5936
+ } else {
5937
+ expectedParts.push(unsigned);
5938
+ receivedParts.push(unsigned);
5939
+ }
5940
+ if (!expDone && expectedParts.length > 0) {
5941
+ expDone = canParseJsonish(expectedParts.join("\n"));
5942
+ }
5943
+ if (!recDone && receivedParts.length > 0) {
5944
+ recDone = canParseJsonish(receivedParts.join("\n"));
5945
+ }
5946
+ if (opened && expDone && recDone) {
5947
+ break;
5872
5948
  }
5873
5949
  }
5874
- return out;
5875
- };
5876
- var stackLocation = (line) => {
5877
- const match = stripAnsiSimple(line).match(/\(?([^\s()]+):(\d+):\d+\)?$/);
5878
- return match ? { file: match[1].replace(/\\/g, "/"), line: Number(match[2]) } : null;
5879
- };
5880
- var JEST_BRIDGE_REPORTER_SOURCE = `const fs = require('fs');
5881
- const path = require('path');
5882
-
5883
- class BridgeReporter {
5884
- constructor(globalConfig, options) {
5885
- this.out = process.env.JEST_BRIDGE_OUT || (options && options.outFile) || path.join(process.cwd(), 'coverage', 'jest-run.json');
5886
- this.buf = { startTime: Date.now(), testResults: [], aggregated: null };
5887
- }
5888
- onRunStart() { this.buf.startTime = Date.now(); }
5889
- onTestResult(_test, tr) {
5890
- const mapAssertion = (a) => ({
5891
- title: a.title,
5892
- fullName: a.fullName || [...(a.ancestorTitles || []), a.title].join(' '),
5893
- status: a.status,
5894
- duration: a.duration || 0,
5895
- location: a.location || null,
5896
- failureMessages: (a.failureMessages || []).map(String),
5897
- });
5898
- this.buf.testResults.push({
5899
- testFilePath: tr.testFilePath,
5900
- status: tr.numFailingTests ? 'failed' : 'passed',
5901
- failureMessage: tr.failureMessage || '',
5902
- failureDetails: tr.failureDetails || [],
5903
- console: tr.console || null,
5904
- perfStats: tr.perfStats || {},
5905
- testResults: (tr.testResults || []).map(mapAssertion),
5906
- });
5907
- }
5908
- onRunComplete(_contexts, agg) {
5909
- this.buf.aggregated = {
5910
- numTotalTestSuites: agg.numTotalTestSuites,
5911
- numPassedTestSuites: agg.numPassedTestSuites,
5912
- numFailedTestSuites: agg.numFailedTestSuites,
5913
- numTotalTests: agg.numTotalTests,
5914
- numPassedTests: agg.numPassedTests,
5915
- numFailedTests: agg.numFailedTests,
5916
- numPendingTests: agg.numPendingTests,
5917
- numTodoTests: agg.numTodoTests,
5918
- startTime: agg.startTime,
5919
- success: agg.success,
5920
- runTimeMs: agg.testResults.reduce((t, r) => t + Math.max(0, (r.perfStats?.end || 0) - (r.perfStats?.start || 0)), 0),
5921
- };
5922
- fs.mkdirSync(path.dirname(this.out), { recursive: true });
5923
- fs.writeFileSync(this.out, JSON.stringify(this.buf), 'utf8');
5924
- }
5925
- }
5926
- module.exports = BridgeReporter;`;
5927
- var asDict = (value) => value && typeof value === "object" ? value : null;
5928
- var get = (objectValue, key) => objectValue ? objectValue[key] : void 0;
5929
- var getStr = (objectValue, key) => {
5930
- const candidate = get(objectValue, key);
5931
- return typeof candidate === "string" ? candidate : void 0;
5932
- };
5933
- function linesFromDetails(details) {
5934
- const stacks = [];
5935
- const messages = [];
5936
- if (!details) {
5937
- return { stacks, messages };
5938
- }
5939
- const pushMaybe = (value, bucket) => {
5940
- if (typeof value === "string" && value.trim()) {
5941
- bucket.push(...value.split(/\r?\n/));
5942
- }
5943
- };
5944
- for (const detail of details) {
5945
- if (typeof detail === "string") {
5946
- if (/\s+at\s.+\(.+:\d+:\d+\)/.test(detail)) {
5947
- pushMaybe(detail, stacks);
5948
- } else {
5949
- pushMaybe(detail, messages);
5950
- }
5951
- continue;
5950
+ const toJsonLikeString = (joined) => {
5951
+ if (!joined) {
5952
+ return void 0;
5952
5953
  }
5953
- const dict = asDict(detail);
5954
- if (dict) {
5955
- pushMaybe(getStr(dict, "stack"), stacks);
5956
- pushMaybe(getStr(dict, "message"), messages);
5957
- const err = asDict(get(dict, "error"));
5958
- pushMaybe(getStr(err, "stack"), stacks);
5959
- pushMaybe(getStr(err, "message"), messages);
5960
- const matcherResult = asDict(get(dict, "matcherResult"));
5961
- pushMaybe(getStr(matcherResult, "stack"), stacks);
5962
- pushMaybe(getStr(matcherResult, "message"), messages);
5963
- pushMaybe(getStr(matcherResult, "expected"), messages);
5964
- pushMaybe(getStr(matcherResult, "received"), messages);
5954
+ const text = normalizeBlock(joined).trim();
5955
+ try {
5956
+ const parsed = import_json5.default.parse(text);
5957
+ return JSON.stringify(parsed, null, 2);
5958
+ } catch {
5959
+ return text;
5965
5960
  }
5961
+ };
5962
+ const expected = expectedParts.length ? expectedParts.join("\n") : void 0;
5963
+ const received = receivedParts.length ? receivedParts.join("\n") : void 0;
5964
+ const result = {};
5965
+ const expStr = toJsonLikeString(expected);
5966
+ const recStr = toJsonLikeString(received);
5967
+ if (expStr !== void 0) {
5968
+ result.expected = expStr;
5966
5969
  }
5967
- return { stacks, messages };
5968
- }
5969
- function labelForMessage(lines) {
5970
- const joined = lines.join(" ");
5971
- const matched = joined.match(/\b(TypeError|ReferenceError|SyntaxError|RangeError|AssertionError)\b/) || joined.match(/\bError\b/);
5972
- if (matched) {
5973
- const typeName = matched[1] ?? "Error";
5974
- return `${typeName}:`;
5975
- }
5976
- return /expect\(.+?\)\.(?:to|not\.)/.test(joined) ? "Assertion:" : "Message:";
5977
- }
5978
- function extractExpectedReceived(details, lines) {
5970
+ if (recStr !== void 0) {
5971
+ result.received = recStr;
5972
+ }
5973
+ return result;
5974
+ };
5975
+ var extractExpectedReceived = (details, lines) => {
5979
5976
  if (details) {
5980
5977
  for (const detail of details) {
5981
- const dict = asDict(detail);
5982
- const matcherResult = dict && asDict(get(dict, "matcherResult"));
5983
- if (matcherResult) {
5984
- const expected = get(matcherResult, "expected");
5985
- const received = get(matcherResult, "received");
5986
- if (expected !== void 0 || received !== void 0) {
5987
- return { expected, received };
5978
+ const dict = isObjectRecord(detail) ? detail : void 0;
5979
+ const matcher = dict && isObjectRecord(dict.matcherResult) ? dict.matcherResult : void 0;
5980
+ if (matcher) {
5981
+ const expectedValue = matcher.expected;
5982
+ const receivedValue = matcher.received;
5983
+ const matcherName = String(
5984
+ matcher.matcherName || ""
5985
+ );
5986
+ if (matcherName === "toHaveBeenCalledTimes" || matcherName === "toBeCalledTimes") {
5987
+ const getCallsCount = (actual) => {
5988
+ if (isObjectRecord(actual) && Array.isArray(actual.calls)) {
5989
+ return actual.calls.length;
5990
+ }
5991
+ if (typeof actual === "number") {
5992
+ return actual;
5993
+ }
5994
+ if (Array.isArray(actual)) {
5995
+ return actual.length;
5996
+ }
5997
+ return void 0;
5998
+ };
5999
+ const expectedNumber = getCallsCount(expectedValue);
6000
+ const actualValue = matcher.actual ?? receivedValue;
6001
+ const receivedNumber = getCallsCount(actualValue);
6002
+ if (expectedNumber !== void 0 || receivedNumber !== void 0) {
6003
+ return { expected: expectedNumber, received: receivedNumber };
6004
+ }
6005
+ }
6006
+ if (expectedValue !== void 0 && receivedValue !== void 0) {
6007
+ return { expected: expectedValue, received: receivedValue };
5988
6008
  }
5989
6009
  }
5990
6010
  }
@@ -6025,116 +6045,34 @@ function extractExpectedReceived(details, lines) {
6025
6045
  }
6026
6046
  }
6027
6047
  return {};
6028
- }
6029
- function extractFromUnifiedDiff(rawLines) {
6030
- const lines = rawLines.map((lineText) => stripAnsiSimple(lineText));
6031
- let startIndex = -1;
6032
- for (let i = 0; i < lines.length; i += 1) {
6033
- const lt = lines[i];
6034
- if (/^\s*(?:[-+]\s*)?(Array\s*\[|Object\s*\{)/.test(lt)) {
6035
- startIndex = i;
6036
- break;
6037
- }
6038
- }
6039
- if (startIndex < 0) {
6040
- return {};
6041
- }
6042
- const expectedParts = [];
6043
- const receivedParts = [];
6044
- let opened = false;
6045
- let expDone = false;
6046
- let recDone = false;
6047
- const canParseJsonish = (input) => {
6048
- const text = normalizeBlock(input).trim();
6049
- try {
6050
- import_json5.default.parse(text);
6051
- return true;
6052
- } catch {
6053
- return false;
6054
- }
6055
- };
6056
- for (let i = startIndex; i < lines.length; i += 1) {
6057
- const lineText = lines[i];
6058
- const unsigned = lineText.replace(/^\s*[-+]\s?/, "");
6059
- const isMinus = /^\s*-\s/.test(lineText);
6060
- const isPlus = /^\s*\+\s/.test(lineText);
6061
- if (!opened) {
6062
- const looksLikeStart = /^\s*(Array\s*\[|Object\s*\{)/.test(unsigned);
6063
- if (!looksLikeStart) {
6064
- continue;
6065
- }
6066
- opened = true;
6067
- }
6068
- if (isMinus) {
6069
- expectedParts.push(unsigned);
6070
- } else if (isPlus) {
6071
- receivedParts.push(unsigned);
6072
- } else {
6073
- expectedParts.push(unsigned);
6074
- receivedParts.push(unsigned);
6075
- }
6076
- if (!expDone && expectedParts.length > 0) {
6077
- const expJoined = expectedParts.join("\n");
6078
- expDone = canParseJsonish(expJoined);
6079
- }
6080
- if (!recDone && receivedParts.length > 0) {
6081
- const recJoined = receivedParts.join("\n");
6082
- recDone = canParseJsonish(recJoined);
6083
- }
6084
- if (opened && expDone && recDone) {
6085
- break;
6086
- }
6087
- }
6088
- const toJsonLikeString = (joined) => {
6089
- if (!joined) {
6090
- return void 0;
6091
- }
6092
- const text = normalizeBlock(joined).trim();
6093
- try {
6094
- const parsed = import_json5.default.parse(text);
6095
- return JSON.stringify(parsed, null, 2);
6096
- } catch {
6097
- return text;
6098
- }
6099
- };
6100
- const expected = expectedParts.length ? expectedParts.join("\n") : void 0;
6101
- const received = receivedParts.length ? receivedParts.join("\n") : void 0;
6102
- const result = {};
6103
- const expStr = toJsonLikeString(expected);
6104
- const recStr = toJsonLikeString(received);
6105
- if (expStr !== void 0) {
6106
- result.expected = expStr;
6107
- }
6108
- if (recStr !== void 0) {
6109
- result.received = recStr;
6048
+ };
6049
+ var buildPrettyDiffSection = (details, messageLines) => {
6050
+ const payload = extractExpectedReceived(details, messageLines);
6051
+ if (payload.expected === void 0 && payload.received === void 0) {
6052
+ return [];
6110
6053
  }
6111
- return result;
6112
- }
6113
- function renderPrettyDiff(payload) {
6054
+ const expectedString = stringifyPrettierish(payload.expected);
6055
+ const receivedString = stringifyPrettierish(payload.received);
6114
6056
  const out = [];
6115
- const { expected, received } = payload;
6116
- if (expected === void 0 && received === void 0) {
6117
- return out;
6118
- }
6119
- const expectedString = stringifyPrettierish(expected);
6120
- const receivedString = stringifyPrettierish(received);
6057
+ const expectedLenLabel = Array.isArray(payload.expected) ? ansi.dim(` (len ${payload.expected.length})`) : "";
6058
+ out.push(` ${ansi.bold("Expected")}${expectedLenLabel}`);
6121
6059
  out.push(
6122
- ` ${ansi.bold("Expected")} ${ansi.dim(
6123
- expected && Array.isArray(expected) ? `(len ${expected.length})` : ""
6124
- )}`
6060
+ expectedString.split("\n").map((expectedLine) => ` ${Colors.Success(expectedLine)}`).join("\n")
6125
6061
  );
6126
- out.push(indentBlock(colorTokens.pass(expectedString)));
6062
+ const receivedLenLabel = Array.isArray(payload.received) ? ansi.dim(` (len ${payload.received.length})`) : "";
6063
+ out.push(` ${ansi.bold("Received")}${receivedLenLabel}`);
6127
6064
  out.push(
6128
- ` ${ansi.bold("Received")} ${ansi.dim(
6129
- received && Array.isArray(received) ? `(len ${received.length})` : ""
6130
- )}`
6065
+ receivedString.split("\n").map((receivedLine) => ` ${Colors.Failure(receivedLine)}`).join("\n")
6131
6066
  );
6132
- out.push(indentBlock(colorTokens.fail(receivedString)));
6133
- if (isArrayOfPrimitives(expected) && isArrayOfPrimitives(received)) {
6134
- const expectedSet = new Set(expected.map((element) => String(element)));
6135
- const receivedSet = new Set(received.map((element) => String(element)));
6136
- const missing = [...expectedSet].filter((element) => !receivedSet.has(element));
6137
- const unexpected = [...receivedSet].filter((element) => !expectedSet.has(element));
6067
+ if (isArrayOfPrimitives(payload.expected) && isArrayOfPrimitives(payload.received)) {
6068
+ const expectedSet = new Set(
6069
+ payload.expected.map((element) => String(element))
6070
+ );
6071
+ const receivedSet = new Set(
6072
+ payload.received.map((element) => String(element))
6073
+ );
6074
+ const missing = Array.from(expectedSet).filter((element) => !receivedSet.has(element));
6075
+ const unexpected = Array.from(receivedSet).filter((element) => !expectedSet.has(element));
6138
6076
  const parts = [];
6139
6077
  if (missing.length) {
6140
6078
  parts.push(
@@ -6147,68 +6085,85 @@ function renderPrettyDiff(payload) {
6147
6085
  );
6148
6086
  }
6149
6087
  if (parts.length) {
6150
- out.push(` ${ansi.dim("Difference:")} ${colorTokens.fail(parts.join(ansi.dim(" | ")))}`);
6088
+ out.push(` ${ansi.dim("Difference:")} ${Colors.Failure(parts.join(ansi.dim(" | ")))}`);
6151
6089
  }
6152
6090
  }
6153
6091
  out.push("");
6154
6092
  return out;
6155
- }
6156
- function pickPrimaryMessage(candidateMessageLines, details) {
6157
- const extracted = extractAssertionMessage(candidateMessageLines);
6158
- if (extracted.length) {
6159
- return extracted;
6160
- }
6161
- const errorLine = details.messages.find(
6162
- (lineText) => /\b(?:Error|TypeError|ReferenceError|SyntaxError|RangeError|AssertionError)\b/.test(lineText)
6093
+ };
6094
+ var buildMessageSection = (messageLines, details, _ctx, opts) => {
6095
+ const out = [];
6096
+ const lines = messageLines.map((lineText) => stripAnsiSimple(lineText));
6097
+ const hintIdx = lines.findIndex(
6098
+ (candidate) => /expect\(.+?\)\.(?:to|not\.)/.test(candidate) || /\b(?:AssertionError|Error):/.test(candidate)
6163
6099
  );
6164
- if (errorLine) {
6165
- return [errorLine];
6166
- }
6167
- const firstNonEmpty = details.messages.find((lineText) => lineText.trim().length);
6168
- if (firstNonEmpty) {
6169
- return [firstNonEmpty];
6170
- }
6171
- return [];
6172
- }
6173
- function colorUnifiedDiffLine(simple) {
6174
- if (/^\s*-\s/.test(simple)) {
6175
- return colorTokens.fail(simple);
6100
+ const acc = [];
6101
+ if (hintIdx >= 0) {
6102
+ acc.push(lines[hintIdx]);
6176
6103
  }
6177
- if (/^\s*\+\s/.test(simple)) {
6178
- return colorTokens.pass(simple);
6104
+ const pushBlock = (start) => {
6105
+ acc.push(lines[start]);
6106
+ for (let i = start + 1; i < lines.length; i += 1) {
6107
+ const candidate = lines[i];
6108
+ if (!candidate.trim() || isStackLine(candidate)) {
6109
+ break;
6110
+ }
6111
+ acc.push(candidate);
6112
+ }
6113
+ };
6114
+ const expectedIdx = lines.findIndex((lineText) => /^\s*Expected:/.test(lineText));
6115
+ const receivedIdx = lines.findIndex((lineText) => /^\s*Received:/.test(lineText));
6116
+ const diffIdx = lines.findIndex(
6117
+ (lineText) => /^\s*(?:- Expected|\+ Received|Difference:)/.test(lineText)
6118
+ );
6119
+ if (expectedIdx >= 0) {
6120
+ pushBlock(expectedIdx);
6179
6121
  }
6180
- return simple;
6181
- }
6182
- var findCodeFrameStart = (lines) => lines.findIndex((line) => /^\s*(>?\s*\d+\s*\|)/.test(stripAnsiSimple(line)));
6183
- var deepestProjectLoc = (stackLines, projectHint) => {
6184
- const idx = findLastProjectFrameIndex(stackLines, projectHint);
6185
- return idx >= 0 ? stackLocation(stackLines[idx]) : null;
6186
- };
6187
- var buildCodeFrameSection = (messageLines, ctx, synthLoc) => {
6188
- const lines = [];
6189
- const start = findCodeFrameStart(messageLines);
6190
- if (start >= 0) {
6191
- lines.push(...renderCodeFrame(messageLines, start), "");
6192
- return lines;
6122
+ if (receivedIdx >= 0) {
6123
+ pushBlock(receivedIdx);
6193
6124
  }
6194
- if (ctx.showStacks && synthLoc) {
6195
- lines.push(...renderSourceCodeFrame(synthLoc.file, synthLoc.line), "");
6125
+ if (diffIdx >= 0) {
6126
+ pushBlock(diffIdx);
6196
6127
  }
6197
- return lines;
6198
- };
6199
- var buildPrettyDiffSection = (details, messageLines) => renderPrettyDiff(extractExpectedReceived(details, messageLines));
6200
- var buildMessageSection = (messageLines, details, ctx, opts) => {
6201
- const out = [];
6202
- const primary = pickPrimaryMessage(messageLines, details);
6203
- const filtered = opts?.suppressDiff ? primary.filter((raw) => {
6128
+ const filtered = opts?.suppressDiff ? acc.filter((raw) => {
6204
6129
  const simple = stripAnsiSimple(raw);
6205
6130
  return !/^\s*(Expected:|Received:|Difference:)\b/.test(simple) && !/^\s*[-+]\s/.test(simple) && !/^\s*(Array\s*\[|Object\s*\{)/.test(simple);
6206
- }) : primary;
6207
- if (filtered.length) {
6208
- const label = labelForMessage(filtered);
6131
+ }) : acc;
6132
+ const hasOnlyBareError = filtered.length === 0 || filtered.length === 1 && /^\s*(?:Error|AssertionError):?\s*$/.test(filtered[0] ?? "");
6133
+ const fallbackLines = [];
6134
+ if (hasOnlyBareError) {
6135
+ const startFrom = hintIdx >= 0 ? hintIdx + 1 : 0;
6136
+ for (let i = startFrom; i < lines.length; i += 1) {
6137
+ const candidate = lines[i];
6138
+ if (!candidate.trim()) {
6139
+ break;
6140
+ }
6141
+ if (isStackLine(candidate)) {
6142
+ break;
6143
+ }
6144
+ fallbackLines.push(candidate);
6145
+ }
6146
+ if (fallbackLines.length === 0 && details && details.messages && details.messages.length) {
6147
+ fallbackLines.push(
6148
+ ...details.messages.map((messageText) => stripAnsiSimple(messageText)).filter((messageText) => messageText.trim().length > 0).slice(0, 6)
6149
+ );
6150
+ }
6151
+ }
6152
+ if (filtered.length > 0) {
6153
+ const label = (() => {
6154
+ const joined = filtered.join(" ");
6155
+ const matchResult = joined.match(/\b(TypeError|ReferenceError|SyntaxError|RangeError|AssertionError)\b/) || joined.match(/\bError\b/);
6156
+ if (matchResult) {
6157
+ const typeName = matchResult[1] ?? "Error";
6158
+ return `${typeName}:`;
6159
+ }
6160
+ return /expect\(.+?\)\.(?:to|not\.)/.test(joined) ? "Assertion:" : "Message:";
6161
+ })();
6209
6162
  out.push(` ${ansi.bold(label)}`);
6210
- for (const lineText of filtered) {
6211
- out.push(` ${ansi.yellow(colorUnifiedDiffLine(lineText))}`);
6163
+ const body = hasOnlyBareError ? fallbackLines : filtered;
6164
+ for (const lineText of body) {
6165
+ const colored = /^\s*-\s/.test(lineText) ? Colors.Failure(lineText) : /^\s*\+\s/.test(lineText) ? Colors.Success(lineText) : lineText;
6166
+ out.push(` ${ansi.yellow(colored)}`);
6212
6167
  }
6213
6168
  if (opts?.stackPreview && opts.stackPreview.length) {
6214
6169
  for (const frame of opts.stackPreview) {
@@ -6219,32 +6174,85 @@ var buildMessageSection = (messageLines, details, ctx, opts) => {
6219
6174
  }
6220
6175
  return out;
6221
6176
  };
6222
- function isConsoleEntry(candidate) {
6223
- return typeof candidate === "object" && candidate !== null;
6224
- }
6225
- var buildConsoleSection = (maybeConsole) => {
6226
- const out = [];
6227
- if (!Array.isArray(maybeConsole)) {
6228
- return out;
6177
+ var linesFromDetails = (details) => {
6178
+ const stacks = [];
6179
+ const messages = [];
6180
+ if (!details) {
6181
+ return { stacks, messages };
6229
6182
  }
6230
- const entries = maybeConsole.filter(isConsoleEntry);
6231
- const errorsOnly = entries.filter((entry) => {
6232
- const val = entry?.type;
6233
- return String(val ?? "").toLowerCase() === "error";
6234
- });
6235
- const scored = errorsOnly.map((entry) => {
6236
- const raw = entry?.message;
6237
- const msg = Array.isArray(raw) ? raw.map(String).join(" ") : typeof raw === "string" ? raw : String(raw ?? "");
6238
- return { msg, score: msg.length };
6239
- }).filter((item) => item.msg.trim().length > 0).sort((left, right) => right.score - left.score).slice(0, MAX_CONSOLE_ERRORS_TO_SHOW);
6240
- if (scored.length) {
6241
- out.push(ansi.dim(" Console errors:"));
6242
- for (const item of scored) {
6243
- out.push(` ${ansi.dim("\u2022")} ${item.msg}`);
6183
+ const pushMaybe = (value, bucket) => {
6184
+ if (typeof value === "string" && value.trim()) {
6185
+ bucket.push(...value.split(/\r?\n/));
6186
+ }
6187
+ };
6188
+ const visitDeep = (value, depth) => {
6189
+ if (depth > 3 || value == null) {
6190
+ return;
6191
+ }
6192
+ if (typeof value === "string") {
6193
+ pushMaybe(value, messages);
6194
+ return;
6195
+ }
6196
+ if (typeof value !== "object") {
6197
+ return;
6198
+ }
6199
+ const obj = value;
6200
+ if (typeof obj.message === "string") {
6201
+ pushMaybe(obj.message, messages);
6202
+ }
6203
+ if (typeof obj.stack === "string") {
6204
+ pushMaybe(obj.stack, stacks);
6205
+ }
6206
+ if (typeof obj.expected === "string") {
6207
+ pushMaybe(obj.expected, messages);
6208
+ }
6209
+ if (typeof obj.received === "string") {
6210
+ pushMaybe(obj.received, messages);
6211
+ }
6212
+ const arrays = ["errors", "causes", "aggregatedErrors"];
6213
+ for (const key of arrays) {
6214
+ const arr = obj[key];
6215
+ if (Array.isArray(arr)) {
6216
+ for (const element of arr) {
6217
+ visitDeep(element, depth + 1);
6218
+ }
6219
+ }
6220
+ }
6221
+ const nestedCandidates = ["error", "cause", "matcherResult"];
6222
+ for (const key of nestedCandidates) {
6223
+ if (obj[key] && typeof obj[key] === "object") {
6224
+ visitDeep(obj[key], depth + 1);
6225
+ }
6226
+ }
6227
+ };
6228
+ for (const detail of details) {
6229
+ if (typeof detail === "string") {
6230
+ if (/\s+at\s.+\(.+:\d+:\d+\)/.test(detail)) {
6231
+ pushMaybe(detail, stacks);
6232
+ } else {
6233
+ pushMaybe(detail, messages);
6234
+ }
6235
+ } else if (isObjectRecord(detail)) {
6236
+ pushMaybe(detail.stack, stacks);
6237
+ pushMaybe(detail.message, messages);
6238
+ const err = isObjectRecord(detail.error) ? detail.error : void 0;
6239
+ if (err) {
6240
+ pushMaybe(err.stack, stacks);
6241
+ pushMaybe(err.message, messages);
6242
+ }
6243
+ const matcher = isObjectRecord(detail.matcherResult) ? detail.matcherResult : void 0;
6244
+ if (matcher) {
6245
+ pushMaybe(matcher.stack, stacks);
6246
+ pushMaybe(matcher.message, messages);
6247
+ pushMaybe(matcher.expected, messages);
6248
+ pushMaybe(matcher.received, messages);
6249
+ }
6250
+ if (messages.length === 0 && stacks.length === 0) {
6251
+ visitDeep(detail, 0);
6252
+ }
6244
6253
  }
6245
- out.push("");
6246
6254
  }
6247
- return out;
6255
+ return { stacks, messages };
6248
6256
  };
6249
6257
  var buildStackSection = (mergedForStack, ctx, fallbackLoc) => {
6250
6258
  const out = [];
@@ -6253,13 +6261,18 @@ var buildStackSection = (mergedForStack, ctx, fallbackLoc) => {
6253
6261
  out.push(` ${ansi.dim("(hidden by TEST_CLI_STACKS=)")}`, "");
6254
6262
  return out;
6255
6263
  }
6256
- const tail = renderStackTail(mergedForStack, ctx.projectHint, 4);
6264
+ const onlyStack = mergedForStack.filter(
6265
+ (lineText) => isStackLine(stripAnsiSimple(lineText))
6266
+ );
6267
+ const tail = onlyStack.slice(-4);
6257
6268
  if (tail.length) {
6258
- out.push(...tail);
6269
+ for (const frameLine of tail) {
6270
+ out.push(` ${colorStackLine(String(frameLine), ctx.projectHint)}`);
6271
+ }
6259
6272
  const loc = deepestProjectLoc(mergedForStack, ctx.projectHint);
6260
6273
  if (loc) {
6261
6274
  const href = preferredEditorHref(loc.file, loc.line, ctx.editorCmd);
6262
- out.push(` ${ansi.dim("at")} ${osc8(`${path9.basename(loc.file)}:${loc.line}`, href)}`);
6275
+ out.push(` ${ansi.dim("at")} ${osc8(`${loc.file.split("/").pop()}:${loc.line}`, href)}`);
6263
6276
  }
6264
6277
  out.push("");
6265
6278
  return out;
@@ -6274,171 +6287,460 @@ var buildStackSection = (mergedForStack, ctx, fallbackLoc) => {
6274
6287
  out.push(` ${ansi.dim("(no stack provided)")}`, "");
6275
6288
  return out;
6276
6289
  };
6277
- var buildFileBadgeLine = (rel, failedCount) => failedCount > 0 ? `${colorTokens.failPill("FAIL")} ${ansi.white(rel)}` : `${colorTokens.passPill("PASS")} ${ansi.white(rel)}`;
6278
- var buildPerFileOverview = (rel, assertions) => {
6290
+ var MAX_CONSOLE_ERRORS_TO_SHOW = 3;
6291
+ var isConsoleEntry = (candidate) => typeof candidate === "object" && candidate !== null;
6292
+ var buildConsoleSection = (maybeConsole) => {
6279
6293
  const out = [];
6280
- out.push(`${ansi.magenta(rel)} ${ansi.dim(`(${assertions.length})`)}`);
6281
- for (const assertion of assertions) {
6282
- const name = assertion.fullName;
6283
- if (assertion.status === "passed") {
6284
- out.push(` ${colorTokens.pass("\u2713")} ${ansi.dim(name)}`);
6285
- } else if (assertion.status === "todo") {
6286
- out.push(` ${colorTokens.todo("\u2610")} ${ansi.dim(name)} ${colorTokens.todo("[todo]")}`);
6287
- } else if (assertion.status === "pending") {
6288
- out.push(` ${colorTokens.skip("\u2193")} ${ansi.dim(name)} ${colorTokens.skip("[skipped]")}`);
6289
- } else {
6290
- out.push(` ${colorTokens.fail("\xD7")} ${ansi.white(name)}`);
6294
+ if (!Array.isArray(maybeConsole)) {
6295
+ return out;
6296
+ }
6297
+ const entries = maybeConsole.filter(isConsoleEntry);
6298
+ const errorsOnly = entries.filter((entry) => String(entry?.type ?? "").toLowerCase() === "error");
6299
+ const scored = errorsOnly.map((entry) => {
6300
+ const raw = entry?.message;
6301
+ const msg = Array.isArray(raw) ? raw.map(String).join(" ") : typeof raw === "string" ? raw : String(raw ?? "");
6302
+ return { msg, score: msg.length };
6303
+ }).filter((item) => item.msg.trim().length > 0).sort((left, right) => right.score - left.score).slice(0, MAX_CONSOLE_ERRORS_TO_SHOW);
6304
+ if (scored.length) {
6305
+ out.push(ansi.dim(" Console errors:"));
6306
+ for (const item of scored) {
6307
+ out.push(` ${ansi.dim("\u2022")} ${item.msg}`);
6291
6308
  }
6309
+ out.push("");
6292
6310
  }
6293
- out.push("");
6294
6311
  return out;
6295
6312
  };
6296
- var formatJestOutputVitest = (raw, opts) => {
6297
- const showStacks = Boolean(env.TEST_CLI_STACKS);
6298
- const cwd = (opts?.cwd ?? process.cwd()).replace(/\\/g, "/");
6299
- const projectHint = new RegExp(
6300
- `(${cwd.replace(/[.*+?^${}()|[\\]\\\\]/g, "\\$&")})|(/gigworx-node/)`
6313
+ var buildFallbackMessageBlock = (messageLines, details) => {
6314
+ const normalize2 = (arr) => arr.map((lineText) => stripAnsiSimple(lineText)).filter((line) => line.trim().length > 0);
6315
+ const normalized = normalize2(messageLines);
6316
+ const informative = normalized.filter((line) => !/^\s*(?:Error|AssertionError):?\s*$/.test(line));
6317
+ if (informative.length > 0) {
6318
+ return [];
6319
+ }
6320
+ const errorIdx = normalized.findIndex(
6321
+ (line) => /(TypeError|ReferenceError|SyntaxError|RangeError|AssertionError|Error):?/.test(line)
6301
6322
  );
6302
- const onlyFailures = Boolean(opts?.onlyFailures);
6303
- const lines = raw.split(/\r?\n/);
6323
+ const collected = [];
6324
+ if (errorIdx >= 0) {
6325
+ for (let i = errorIdx; i < normalized.length && collected.length < 8; i += 1) {
6326
+ const ln = normalized[i];
6327
+ if (!ln.trim()) {
6328
+ break;
6329
+ }
6330
+ if (isStackLine(ln)) {
6331
+ break;
6332
+ }
6333
+ collected.push(ln);
6334
+ }
6335
+ }
6336
+ const fromDetails = collected.length > 0 ? [] : normalize2(details.messages).slice(0, 6);
6337
+ const linesToShow = collected.length > 0 ? collected : fromDetails;
6338
+ if (linesToShow.length === 0) {
6339
+ return [];
6340
+ }
6304
6341
  const out = [];
6305
- const seenFailures = /* @__PURE__ */ new Set();
6306
- const seenFiles = /* @__PURE__ */ new Set();
6307
- for (let lineIndex = 0; lineIndex < lines.length; ) {
6308
- const ln = stripAnsiSimple(lines[lineIndex]);
6309
- if (/^\s*●\s+/.test(ln)) {
6310
- const title = ln.replace(/^\s*●\s+/, "").trim();
6311
- const block = [lines[lineIndex]];
6312
- let scanIndex = lineIndex + 1;
6313
- while (scanIndex < lines.length) {
6314
- const scanLine = stripAnsiSimple(lines[scanIndex]);
6315
- const nextIsStart = /^\s*●\s+/.test(scanLine) || /^\s*(PASS|FAIL)\s/.test(scanLine) || /^\s*Test Suites:/.test(scanLine);
6316
- if (nextIsStart && stripAnsiSimple(lines[scanIndex - 1] ?? "").trim() === "") {
6317
- break;
6318
- }
6319
- block.push(lines[scanIndex]);
6320
- scanIndex += 1;
6342
+ out.push(` ${ansi.bold("Message:")}`);
6343
+ for (const lineText of linesToShow) {
6344
+ out.push(` ${ansi.yellow(lineText)}`);
6345
+ }
6346
+ out.push("");
6347
+ return out;
6348
+ };
6349
+ var buildThrownSection = (details) => {
6350
+ const toLines = (value) => {
6351
+ if (value == null) {
6352
+ return [];
6353
+ }
6354
+ if (typeof value === "string") {
6355
+ return value.split(/\r?\n/);
6356
+ }
6357
+ try {
6358
+ return JSON.stringify(value, null, 2).split(/\r?\n/);
6359
+ } catch {
6360
+ return [String(value)];
6361
+ }
6362
+ };
6363
+ const candidates = [];
6364
+ for (const d of details) {
6365
+ const obj = d && typeof d === "object" ? d : null;
6366
+ if (obj && obj.error && typeof obj.error === "object") {
6367
+ const err = obj.error;
6368
+ if (typeof err.name === "string") {
6369
+ candidates.push(`name: ${err.name}`);
6321
6370
  }
6322
- const codeFrameStart = block.findIndex(
6323
- (candidateLine) => /^\s*(>?\s*\d+\s*\|)/.test(stripAnsiSimple(candidateLine))
6324
- );
6325
- const location = firstTestLocation(block, projectHint);
6326
- const rel = location ? location.split(":")[0].replace(/\\/g, "/").replace(`${cwd}/`, "") : "";
6327
- const key = `${rel}|${title}`;
6328
- if (seenFailures.has(key)) {
6329
- lineIndex = scanIndex;
6330
- continue;
6371
+ if (typeof err.message === "string") {
6372
+ candidates.push(`message: ${err.message}`);
6331
6373
  }
6332
- seenFailures.add(key);
6333
- out.push(drawFailLine());
6334
- const header = `${colorTokens.fail("\xD7")} ${ansi.white(rel ? `${rel} > ${title}` : title)}`;
6335
- out.push(header);
6336
- const linesBlock = block.map(String);
6337
- const collapsedForSrc = collapseStacks(linesBlock.slice(0));
6338
- if (codeFrameStart >= 0) {
6339
- out.push("");
6340
- out.push(...renderCodeFrame(linesBlock, codeFrameStart));
6341
- out.push("");
6342
- } else if (showStacks) {
6343
- const deepestIdxForSrc = findLastProjectFrameIndex(collapsedForSrc, projectHint);
6344
- const locForSrc = deepestIdxForSrc >= 0 ? stackLocation(collapsedForSrc[deepestIdxForSrc]) : null;
6345
- if (locForSrc) {
6346
- out.push("");
6347
- out.push(...renderSourceCodeFrame(locForSrc.file, locForSrc.line));
6348
- out.push("");
6349
- }
6350
- }
6351
- const payload = extractExpectedReceived(void 0, linesBlock);
6352
- const hasPretty = payload.expected !== void 0 || payload.received !== void 0;
6353
- out.push(...renderPrettyDiff(payload));
6354
- const detailsForMsg = linesFromDetails(void 0);
6355
- const collapsedForTail = collapseStacks(linesBlock.slice(0));
6356
- const stackPreview = showStacks ? firstProjectFrames(collapsedForTail, projectHint, 2) : [];
6357
- out.push(
6358
- ...buildMessageSection(
6359
- linesBlock,
6360
- detailsForMsg,
6361
- { projectHint, editorCmd: opts?.editorCmd, showStacks },
6362
- { suppressDiff: hasPretty, stackPreview }
6363
- )
6364
- );
6365
- if (showStacks && stackPreview.length === 0) {
6366
- const collapsed = collapseStacks(linesBlock.slice(0));
6367
- out.push(
6368
- ...buildStackSection(collapsed, {
6369
- projectHint,
6370
- editorCmd: opts?.editorCmd,
6371
- showStacks
6372
- })
6373
- );
6374
+ if (typeof err.code === "string" || typeof err.code === "number") {
6375
+ candidates.push(`code: ${String(err.code)}`);
6376
+ }
6377
+ if (typeof err.cause === "string") {
6378
+ candidates.push(`cause: ${err.cause}`);
6379
+ }
6380
+ if (err.cause && typeof err.cause === "object") {
6381
+ candidates.push("cause:");
6382
+ candidates.push(...toLines(err.cause));
6383
+ }
6384
+ const rest = { ...err };
6385
+ delete rest.name;
6386
+ delete rest.message;
6387
+ delete rest.code;
6388
+ delete rest.stack;
6389
+ if (Object.keys(rest).length > 0) {
6390
+ candidates.push("details:");
6391
+ candidates.push(...toLines(rest));
6374
6392
  }
6375
- out.push(drawFailLine());
6376
- out.push("");
6377
- lineIndex = scanIndex;
6378
- continue;
6379
6393
  }
6380
- const passFail = ln.match(/^\s*(PASS|FAIL)\s+(.+)$/);
6381
- if (passFail) {
6382
- const badge = passFail[1];
6383
- const fileAbs = passFail[2];
6384
- const rel = fileAbs.replace(/\\/g, "/").replace(`${cwd}/`, "");
6394
+ }
6395
+ if (!candidates.length) {
6396
+ return [];
6397
+ }
6398
+ const out = [];
6399
+ out.push(` ${ansi.bold("Thrown:")}`);
6400
+ for (const line of candidates.slice(0, 50)) {
6401
+ out.push(` ${ansi.yellow(line)}`);
6402
+ }
6403
+ out.push("");
6404
+ return out;
6405
+ };
6406
+ var mkPrettyFns = () => ({
6407
+ drawRule,
6408
+ drawFailLine,
6409
+ renderRunLine,
6410
+ buildPerFileOverview,
6411
+ buildFileBadgeLine,
6412
+ extractBridgePath,
6413
+ buildCodeFrameSection,
6414
+ buildMessageSection,
6415
+ buildPrettyDiffSection,
6416
+ buildStackSection,
6417
+ deepestProjectLoc,
6418
+ findCodeFrameStart,
6419
+ linesFromDetails,
6420
+ buildFallbackMessageBlock,
6421
+ buildThrownSection
6422
+ });
6423
+
6424
+ // src/lib/formatter/render.ts
6425
+ var relPath = (abs, cwd) => abs.replace(/\\/g, "/").replace(`${cwd}/`, "");
6426
+ var renderChunks = (chunks, ctx, fns, opts) => {
6427
+ const out = [];
6428
+ const seenFiles = /* @__PURE__ */ new Set();
6429
+ const seenFailures = /* @__PURE__ */ new Set();
6430
+ const onlyFailures = Boolean(opts?.onlyFailures);
6431
+ let currentRelFile = null;
6432
+ const escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6433
+ for (const ch of chunks) {
6434
+ if (ch.tag === "PassFail") {
6435
+ const rel = relPath(ch.rel, ctx.cwd);
6385
6436
  if (seenFiles.has(rel)) {
6386
- lineIndex += 1;
6387
6437
  continue;
6388
6438
  }
6389
6439
  seenFiles.add(rel);
6390
- if (!(onlyFailures && badge === "PASS")) {
6391
- const pill = badge === "PASS" ? colorTokens.passPill("PASS") : colorTokens.failPill("FAIL");
6392
- out.push(`${pill} ${ansi.white(rel)}`);
6440
+ currentRelFile = rel;
6441
+ if (!(onlyFailures && ch.badge === "PASS")) {
6442
+ out.push(fns.buildFileBadgeLine(rel, ch.badge === "FAIL" ? 1 : 0));
6393
6443
  }
6394
- lineIndex += 1;
6395
6444
  continue;
6396
6445
  }
6397
- if (/^\s*(Test Suites:|Tests:|Snapshots:|Time:|Ran all)/.test(ln)) {
6398
- out.push(lines[lineIndex]);
6399
- lineIndex += 1;
6446
+ if (ch.tag === "FailureBlock") {
6447
+ out.push(fns.drawFailLine());
6448
+ const location = firstTestLocation(ch.lines, ctx.projectHint);
6449
+ const rel = location ? relPath(location.split(":")[0] ?? "", ctx.cwd) : "";
6450
+ const headerText = rel ? `${rel} > ${ch.title}` : ch.title;
6451
+ out.push(`${Colors.Failure("\xD7")} ${ansi.white(headerText)}`);
6452
+ const codeStart = fns.findCodeFrameStart(ch.lines);
6453
+ const collapsedForSrc = collapseStacks(ch.lines.slice(0));
6454
+ const deepestLoc = fns.deepestProjectLoc(collapsedForSrc, ctx.projectHint);
6455
+ let effectiveLoc = deepestLoc;
6456
+ if (!effectiveLoc && currentRelFile) {
6457
+ try {
6458
+ const abs = path9.resolve(ctx.cwd, currentRelFile);
6459
+ const source = ctx.readSource(abs);
6460
+ const testName = (() => {
6461
+ const parts = ch.title.split(">");
6462
+ return (parts[parts.length - 1] || ch.title).trim();
6463
+ })();
6464
+ const itRe = new RegExp(
6465
+ String.raw`\b(?:it|test)\s*\(\s*['\"]${escapeRegExp(testName)}['\"]`
6466
+ );
6467
+ let index = source.findIndex((line) => itRe.test(line));
6468
+ if (index < 0) {
6469
+ index = source.findIndex((line) => /\bexpect\s*\(/.test(line));
6470
+ } else {
6471
+ const windowEnd = Math.min(source.length, index + 80);
6472
+ for (let i = index; i < windowEnd; i += 1) {
6473
+ if (/\bexpect\s*\(/.test(source[i])) {
6474
+ index = i;
6475
+ break;
6476
+ }
6477
+ }
6478
+ }
6479
+ if (index >= 0) {
6480
+ effectiveLoc = { file: abs.replace(/\\/g, "/"), line: index + 1 };
6481
+ }
6482
+ } catch {
6483
+ }
6484
+ }
6485
+ if (codeStart >= 0) {
6486
+ out.push("", ...fns.buildCodeFrameSection(ch.lines, ctx, effectiveLoc), "");
6487
+ } else {
6488
+ out.push("", ...fns.buildCodeFrameSection(ch.lines, ctx, effectiveLoc), "");
6489
+ }
6490
+ const pretty = fns.buildPrettyDiffSection(void 0, ch.lines);
6491
+ out.push(...pretty);
6492
+ const hasPretty = pretty.length > 0;
6493
+ const details = fns.linesFromDetails(void 0);
6494
+ const minimal = (() => {
6495
+ const plain = ch.lines.map((ln) => stripAnsiSimple(ln));
6496
+ const hint = plain.findIndex(
6497
+ (lineText) => /expect\(.+?\)\.(?:to|not\.)/.test(lineText) || /\bError:?\b/.test(lineText)
6498
+ );
6499
+ const acc = [];
6500
+ const start = hint >= 0 ? hint : 0;
6501
+ for (let i = start; i < plain.length; i += 1) {
6502
+ const ln = plain[i];
6503
+ if (!ln.trim()) {
6504
+ break;
6505
+ }
6506
+ if (isStackLine(ln)) {
6507
+ break;
6508
+ }
6509
+ acc.push(ln);
6510
+ }
6511
+ return acc;
6512
+ })();
6513
+ const collapsedForTail = collapseStacks(ch.lines.slice(0));
6514
+ const stackPreview = ctx.showStacks ? collapsedForTail.filter((ln) => isStackLine(stripAnsiSimple(ln))).filter((ln) => ctx.projectHint.test(stripAnsiSimple(ln))).slice(0, 2).map((ln) => ` ${colorStackLine(String(ln), ctx.projectHint)}`) : [];
6515
+ out.push(
6516
+ ...fns.buildMessageSection(minimal.length ? minimal : ch.lines, details, ctx, {
6517
+ suppressDiff: hasPretty,
6518
+ stackPreview
6519
+ })
6520
+ );
6521
+ if (minimal.length === 0 && fns.buildFallbackMessageBlock) {
6522
+ out.push(...fns.buildFallbackMessageBlock(ch.lines, { messages: details.messages }));
6523
+ }
6524
+ const consoleInline = (() => {
6525
+ const plain = ch.lines.map((ln) => stripAnsiSimple(ln));
6526
+ const cand = plain.filter((ln) => /\bconsole\.(error|warn)\s*\(/i.test(ln) || /^\s*Error:/.test(ln)).map((ln) => ln.trim()).filter((ln) => ln.length > 0).sort((a, b) => b.length - a.length).slice(0, 3);
6527
+ return cand;
6528
+ })();
6529
+ if (consoleInline.length > 0) {
6530
+ out.push(ansi.dim(" Console errors:"), ...consoleInline.map((ln) => ` ${ln}`), "");
6531
+ }
6532
+ if (ctx.showStacks && fns.buildStackSection && stackPreview.length === 0) {
6533
+ const collapsed = collapseStacks(ch.lines.slice(0));
6534
+ out.push(...fns.buildStackSection(collapsed, ctx));
6535
+ }
6536
+ out.push(fns.drawFailLine(), "");
6537
+ if (rel) {
6538
+ seenFailures.add(`${rel}|${ch.title}`);
6539
+ }
6400
6540
  continue;
6401
6541
  }
6402
- if (isStackLine(ln)) {
6403
- if (showStacks) {
6404
- const kept = collapseStacks([lines[lineIndex]]);
6405
- out.push(...kept);
6542
+ if (ch.tag === "Summary") {
6543
+ out.push(ch.line);
6544
+ continue;
6545
+ }
6546
+ if (ch.tag === "Stack") {
6547
+ if (ctx.showStacks) {
6548
+ out.push(ch.line);
6406
6549
  }
6407
- lineIndex += 1;
6408
6550
  continue;
6409
6551
  }
6410
- out.push(lines[lineIndex]);
6411
- lineIndex += 1;
6552
+ if (!onlyFailures) {
6553
+ out.push(ch.line);
6554
+ }
6412
6555
  }
6413
- const rendered = out.join("\n");
6414
- const hadParsedTests = seenFiles.size > 0 || seenFailures.size > 0 || out.some((lineText) => /^(?:\s*)(PASS|FAIL)\b/.test(stripAnsiSimple(lineText)));
6415
- if (!hadParsedTests) {
6416
- const bridgePath = extractBridgePath(raw, cwd);
6417
- if (bridgePath && fs4.existsSync(bridgePath)) {
6418
- try {
6419
- const json = JSON.parse(fs4.readFileSync(bridgePath, "utf8"));
6420
- const bridge = coerceJestJsonToBridge(json);
6421
- const renderedFromJson = renderVitestFromJestJSON(bridge, opts);
6422
- const prefix = out.join("\n");
6423
- return prefix ? `${prefix}
6424
- ${renderedFromJson}` : renderedFromJson;
6425
- } catch {
6426
- }
6556
+ const hadParsed = seenFiles.size > 0 || seenFailures.size > 0 || out.some((lineText) => /^(?:\s*)(PASS|FAIL)\b/.test(stripAnsiSimple(lineText)));
6557
+ return { text: out.join("\n"), hadParsed };
6558
+ };
6559
+
6560
+ // src/lib/formatter/context.ts
6561
+ import * as fs5 from "node:fs";
6562
+ var makeCtx = (opts, showStacks = false) => {
6563
+ const cwd = (opts?.cwd ?? process.cwd()).replace(/\\/g, "/");
6564
+ const width = Math.max(
6565
+ 40,
6566
+ process.stdout && process.stdout.columns || 80
6567
+ );
6568
+ const projectHint = new RegExp(
6569
+ `(${cwd.replace(/[.*+?^${}()|[\\]\\\\]/g, "\\$&")})|(/gigworx-node/)`
6570
+ );
6571
+ const readSource2 = (file) => {
6572
+ try {
6573
+ return fs5.readFileSync(file.replace(/\\/g, "/"), "utf8").split(/\r?\n/);
6574
+ } catch {
6575
+ return [];
6427
6576
  }
6577
+ };
6578
+ return { cwd, width, showStacks, projectHint, editorCmd: opts?.editorCmd, readSource: readSource2 };
6579
+ };
6580
+
6581
+ // src/lib/formatter/bridge.ts
6582
+ var import_json52 = __toESM(require_lib(), 1);
6583
+ import * as fs6 from "node:fs";
6584
+ import * as path10 from "node:path";
6585
+ var colorTokens2 = {
6586
+ pass: Colors.Success,
6587
+ fail: Colors.Failure,
6588
+ skip: Colors.Skip,
6589
+ todo: Colors.Todo,
6590
+ passPill: (text) => BackgroundColors.Success(ansi.white(` ${text} `)),
6591
+ failPill: (text) => BackgroundColors.Failure(ansi.white(` ${text} `))
6592
+ };
6593
+ var by = (keySelector) => (left, right) => keySelector(left) - keySelector(right);
6594
+ var isObject = (candidateValue) => !!candidateValue && typeof candidateValue === "object";
6595
+ var asHttpList = (candidateValue) => Array.isArray(candidateValue) ? candidateValue : [];
6596
+ var summarizeUrl = (method, url, route) => {
6597
+ const base = route || url || "";
6598
+ const qs = url && url.includes("?") ? ` ? ${url.split("?")[1]}` : "";
6599
+ return [method || "", base, qs].filter(Boolean).join(" ").trim();
6600
+ };
6601
+ var stripBridgeEventsFromConsole = (maybeConsole) => {
6602
+ if (!Array.isArray(maybeConsole)) {
6603
+ return maybeConsole;
6428
6604
  }
6429
- try {
6430
- const preview = rendered.split("\n").slice(0, 2).join("\n");
6431
- console.info(`formatJestOutputVitest: produced ${out.length} lines; preview:
6432
- ${preview}`);
6433
- } catch {
6605
+ return maybeConsole.filter((entry) => {
6606
+ try {
6607
+ const raw = Array.isArray(entry.message) ? entry.message.map(String).join(" ") : String(entry.message ?? "");
6608
+ return !raw.includes("[JEST-BRIDGE-EVENT]");
6609
+ } catch {
6610
+ return true;
6611
+ }
6612
+ });
6613
+ };
6614
+ var extractBridgePath2 = (raw, cwd) => {
6615
+ const matches = Array.from(
6616
+ raw.matchAll(/Test results written to:\s+([^\n\r]+jest-bridge-[^\s'"]+\.json)/g)
6617
+ );
6618
+ if (!matches.length) {
6619
+ return null;
6434
6620
  }
6435
- return rendered;
6621
+ const jsonPath = (matches[matches.length - 1][1] ?? "").trim().replace(/^["'`]|["'`]$/g, "");
6622
+ return path10.isAbsolute(jsonPath) ? jsonPath : path10.resolve(cwd, jsonPath).replace(/\\/g, "/");
6623
+ };
6624
+ var isTransportError = (msg) => {
6625
+ const lowercaseMessage = (msg ?? "").toLowerCase();
6626
+ return /\bsocket hang up\b|\beconnreset\b|\betimedout\b|\beconnrefused\b|\bwrite epipe\b/.test(
6627
+ lowercaseMessage
6628
+ );
6436
6629
  };
6437
- var isBridgeJSONLike = (candidate) => {
6438
- const candidateValue = candidate;
6439
- return typeof candidateValue === "object" && candidateValue !== null && "aggregated" in candidateValue;
6630
+ var envNumber = (name, fallback) => {
6631
+ const parsed = Number(process.env[name]);
6632
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
6633
+ };
6634
+ var HEADLAMP_HTTP_WINDOW_MS = () => envNumber("HEADLAMP_HTTP_WINDOW_MS", 3e3);
6635
+ var HEADLAMP_HTTP_STRICT_WINDOW_MS = () => envNumber("HEADLAMP_HTTP_STRICT_WINDOW_MS", 600);
6636
+ var HEADLAMP_HTTP_MIN_SCORE = () => envNumber("HEADLAMP_HTTP_MIN_SCORE", 1200);
6637
+ var HEADLAMP_HTTP_DIFF_LIMIT = () => envNumber("HEADLAMP_HTTP_DIFF_LIMIT", 6);
6638
+ var HEADLAMP_HTTP_SHOW_MISS = () => process.env.HEADLAMP_HTTP_MISS === "1";
6639
+ var eventsNear = (http, ts, testPath, windowMs = HEADLAMP_HTTP_WINDOW_MS()) => {
6640
+ if (typeof ts !== "number" || !Number.isFinite(ts)) {
6641
+ return [];
6642
+ }
6643
+ return http.filter((e) => {
6644
+ const timeOk = typeof e.timestampMs === "number" && Math.abs(e.timestampMs - ts) <= windowMs;
6645
+ const pathOk = !testPath || e.testPath === testPath;
6646
+ return timeOk && pathOk;
6647
+ });
6648
+ };
6649
+ var parseMethodPathFromTitle = (title) => {
6650
+ if (!title) {
6651
+ return {};
6652
+ }
6653
+ const matchResult = title.match(/\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\s+([^\s)]+)/i);
6654
+ return matchResult ? { method: matchResult[1]?.toUpperCase(), path: matchResult[2] } : {};
6655
+ };
6656
+ var isHttpStatusNumber = (statusNumber) => typeof statusNumber === "number" && statusNumber >= 100 && statusNumber <= 599;
6657
+ var hasStatusSemantics = (assertionLike) => {
6658
+ if (!assertionLike) {
6659
+ return false;
6660
+ }
6661
+ if (isHttpStatusNumber(assertionLike.expectedNumber) || isHttpStatusNumber(assertionLike.receivedNumber)) {
6662
+ return true;
6663
+ }
6664
+ const combinedRaw = `${assertionLike.matcher ?? ""} ${assertionLike.message ?? ""}`;
6665
+ const combinedMessage = combinedRaw.toLowerCase();
6666
+ return /\bstatus(code)?\b|\btohaves(tatus|tatuscode)\b/.test(combinedMessage);
6667
+ };
6668
+ var fileSuggestsHttp = (relPath2) => /(?:^|\/)(routes?|api|controllers?|e2e|integration)(?:\/|\.test\.)/i.test(relPath2);
6669
+ var inferHttpNumbersFromText = (lines) => {
6670
+ const text = lines.join("\n");
6671
+ const match = text.match(/Expected:\s*(\d{3})[\s\S]*?Received:\s*(\d{3})/i);
6672
+ if (match) {
6673
+ return { expectedNumber: Number(match[1]), receivedNumber: Number(match[2]) };
6674
+ }
6675
+ return {};
6440
6676
  };
6441
- function coerceJestJsonToBridge(raw) {
6677
+ var titleSuggestsHttp = (title) => {
6678
+ const { method, path: parsedPath } = parseMethodPathFromTitle(title);
6679
+ return Boolean(method || parsedPath && parsedPath.startsWith("/"));
6680
+ };
6681
+ var isHttpRelevant = (ctx) => {
6682
+ const assertionCtx = ctx.assertion;
6683
+ return ctx.hasTransportSignal || ctx.httpCountInSameTest > 0 || titleSuggestsHttp(ctx.title) || hasStatusSemantics(assertionCtx) || fileSuggestsHttp(ctx.relPath);
6684
+ };
6685
+ var routeSimilarityScore = (hint, evt) => {
6686
+ if (!hint.path && !hint.method) {
6687
+ return 0;
6688
+ }
6689
+ const methodOk = hint.method && evt.method ? Number(hint.method === evt.method) : 0;
6690
+ const route = evt.route || evt.url || "";
6691
+ if (!route) {
6692
+ return methodOk * 10;
6693
+ }
6694
+ if (hint.path && route === hint.path) {
6695
+ return 500 + methodOk * 50;
6696
+ }
6697
+ if (hint.path && route.endsWith(hint.path)) {
6698
+ return 300 + methodOk * 50;
6699
+ }
6700
+ if (hint.path && route.includes(hint.path)) {
6701
+ return 200 + methodOk * 50;
6702
+ }
6703
+ return methodOk * 10;
6704
+ };
6705
+ var scoreHttpForAssertion = (assertion, titleHint) => (candidateEvent) => {
6706
+ const tsA = assertion.timestampMs;
6707
+ const tsH = candidateEvent.timestampMs;
6708
+ const window = isTransportError(assertion.message) ? HEADLAMP_HTTP_STRICT_WINDOW_MS() : HEADLAMP_HTTP_WINDOW_MS();
6709
+ const timeScore = typeof tsA === "number" && typeof tsH === "number" ? Math.max(0, window - Math.abs(tsA - tsH)) : 0;
6710
+ const statusScore = typeof assertion.receivedNumber === "number" && candidateEvent.statusCode === assertion.receivedNumber ? 1500 : typeof assertion.expectedNumber === "number" && candidateEvent.statusCode === assertion.expectedNumber ? 1200 : (candidateEvent.statusCode ?? 0) >= 400 ? 800 : 0;
6711
+ const routeScore = routeSimilarityScore(titleHint, candidateEvent);
6712
+ const specificity = candidateEvent.route ? 80 : candidateEvent.url ? 40 : 0;
6713
+ return timeScore + statusScore + routeScore + specificity;
6714
+ };
6715
+ var pickRelevantHttp = (assertion, http, ctx) => {
6716
+ const hint = parseMethodPathFromTitle(ctx.title);
6717
+ const nameMatches = (leftName, rightName) => !!leftName && !!rightName && (leftName === rightName || leftName.includes(rightName) || rightName.includes(leftName));
6718
+ const sameTest = (leftCtx, rightCtx) => !!leftCtx && !!rightCtx && leftCtx.testPath === rightCtx.testPath && nameMatches(leftCtx.currentTestName, rightCtx.currentTestName);
6719
+ const strictPool = http.filter(
6720
+ (httpEvent) => sameTest(assertion, httpEvent) || sameTest(ctx, httpEvent)
6721
+ );
6722
+ const windowMs = isTransportError(assertion.message) ? HEADLAMP_HTTP_STRICT_WINDOW_MS() : HEADLAMP_HTTP_WINDOW_MS();
6723
+ let pool = strictPool;
6724
+ if (!pool.length) {
6725
+ pool = http.filter(
6726
+ (e) => e.testPath === ctx.testPath && typeof assertion.timestampMs === "number" && typeof e.timestampMs === "number" && Math.abs(e.timestampMs - assertion.timestampMs) <= windowMs
6727
+ );
6728
+ }
6729
+ if (!pool.length) {
6730
+ pool = http.filter(
6731
+ (e) => typeof assertion.timestampMs === "number" && typeof e.timestampMs === "number" && Math.abs(e.timestampMs - assertion.timestampMs) <= windowMs
6732
+ );
6733
+ }
6734
+ if (!pool.length) {
6735
+ return void 0;
6736
+ }
6737
+ const scored = pool.map((httpEvent) => ({ h: httpEvent, s: scoreHttpForAssertion(assertion, hint)(httpEvent) })).sort((leftScore, rightScore) => rightScore.s - leftScore.s);
6738
+ const [best] = scored;
6739
+ const threshold = isTransportError(assertion.message) ? Math.max(HEADLAMP_HTTP_MIN_SCORE(), 1400) : HEADLAMP_HTTP_MIN_SCORE();
6740
+ return best && best.s >= threshold ? best.h : void 0;
6741
+ };
6742
+ var isBridgeJSONLike = (candidateValue) => !!candidateValue && typeof candidateValue === "object" && "aggregated" in candidateValue;
6743
+ var coerceJestJsonToBridge = (raw) => {
6442
6744
  if (isBridgeJSONLike(raw)) {
6443
6745
  return raw;
6444
6746
  }
@@ -6448,18 +6750,21 @@ function coerceJestJsonToBridge(raw) {
6448
6750
  }
6449
6751
  return {
6450
6752
  startTime: Number(j.startTime ?? Date.now()),
6451
- testResults: j.testResults.map((testFileResult) => ({
6452
- testFilePath: testFileResult.testFilePath || testFileResult.name || "",
6453
- status: testFileResult.status,
6454
- failureMessage: testFileResult.failureMessage || "",
6455
- failureDetails: testFileResult.failureDetails ?? [],
6456
- testResults: (testFileResult.assertionResults || []).map((assertion) => ({
6753
+ testResults: j.testResults.map((tr) => ({
6754
+ testFilePath: tr.testFilePath || tr.name || "",
6755
+ status: tr.status,
6756
+ failureMessage: tr.failureMessage || "",
6757
+ failureDetails: tr.failureDetails ?? [],
6758
+ testExecError: tr.testExecError ?? null,
6759
+ console: tr.console ?? null,
6760
+ testResults: (tr.assertionResults || []).map((assertion) => ({
6457
6761
  title: assertion.title,
6458
6762
  fullName: assertion.fullName || [...assertion.ancestorTitles || [], assertion.title].join(" "),
6459
6763
  status: assertion.status,
6460
6764
  duration: assertion.duration || 0,
6461
6765
  location: assertion.location ?? null,
6462
- failureMessages: assertion.failureMessages || []
6766
+ failureMessages: assertion.failureMessages || [],
6767
+ failureDetails: assertion.failureDetails || []
6463
6768
  }))
6464
6769
  })),
6465
6770
  aggregated: {
@@ -6475,21 +6780,20 @@ function coerceJestJsonToBridge(raw) {
6475
6780
  success: j.success
6476
6781
  }
6477
6782
  };
6478
- }
6479
- var vitestFooter = (agg, _startedAt, durationMs) => {
6783
+ };
6784
+ var vitestFooter = (agg, durationMs) => {
6480
6785
  const files = [
6481
- agg.numFailedTestSuites ? colorTokens.fail(`${agg.numFailedTestSuites} failed`) : "",
6482
- agg.numPassedTestSuites ? colorTokens.pass(`${agg.numPassedTestSuites} passed`) : "",
6483
- agg.numPendingTests ? colorTokens.skip(`${agg.numPendingTests} skipped`) : ""
6786
+ agg.numFailedTestSuites ? colorTokens2.fail(`${agg.numFailedTestSuites} failed`) : "",
6787
+ agg.numPassedTestSuites ? colorTokens2.pass(`${agg.numPassedTestSuites} passed`) : "",
6788
+ agg.numPendingTests ? colorTokens2.skip(`${agg.numPendingTests} skipped`) : ""
6484
6789
  ].filter(Boolean).join(ansi.dim(" | "));
6485
6790
  const tests = [
6486
- agg.numFailedTests ? colorTokens.fail(`${agg.numFailedTests} failed`) : "",
6487
- agg.numPassedTests ? colorTokens.pass(`${agg.numPassedTests} passed`) : "",
6488
- agg.numPendingTests ? colorTokens.skip(`${agg.numPendingTests} skipped`) : "",
6489
- agg.numTodoTests ? colorTokens.todo(`${agg.numTodoTests} todo`) : ""
6791
+ agg.numFailedTests ? colorTokens2.fail(`${agg.numFailedTests} failed`) : "",
6792
+ agg.numPassedTests ? colorTokens2.pass(`${agg.numPassedTests} passed`) : "",
6793
+ agg.numPendingTests ? colorTokens2.skip(`${agg.numPendingTests} skipped`) : "",
6794
+ agg.numTodoTests ? colorTokens2.todo(`${agg.numTodoTests} todo`) : ""
6490
6795
  ].filter(Boolean).join(ansi.dim(" | "));
6491
- const durMs = typeof durationMs === "number" ? durationMs : typeof agg.runTimeMs === "number" ? agg.runTimeMs : void 0;
6492
- const time = durMs != null ? `${Math.max(0, Math.round(durMs))}ms` : "";
6796
+ const time = durationMs != null ? `${Math.max(0, Math.round(durationMs))}ms` : typeof agg.runTimeMs === "number" ? `${Math.max(0, Math.round(agg.runTimeMs))}ms` : "";
6493
6797
  const thread = ansi.dim("(in thread 0ms, 0.00%)");
6494
6798
  return [
6495
6799
  `${ansi.bold("Test Files")} ${files} ${ansi.dim(`(${agg.numTotalTestSuites})`)}`,
@@ -6497,20 +6801,14 @@ var vitestFooter = (agg, _startedAt, durationMs) => {
6497
6801
  `${ansi.bold("Time")} ${time} ${thread}`
6498
6802
  ].join("\n");
6499
6803
  };
6500
- function renderVitestFromJestJSON(data, opts) {
6501
- const cwd = (opts?.cwd ?? process.cwd()).replace(/\\/g, "/");
6502
- const projectHint = new RegExp(
6503
- `(${cwd.replace(/[.*+?^${}()|[\\]\\\\]/g, "\\$&")})|(/gigworx-node/)`
6504
- );
6505
- const ctx = { projectHint, editorCmd: opts?.editorCmd, showStacks: true };
6506
- const onlyFailures = Boolean(opts?.onlyFailures);
6804
+ var renderVitestFromJestJSON = (data, ctx, opts) => {
6507
6805
  const out = [];
6806
+ const onlyFailures = Boolean(opts?.onlyFailures);
6508
6807
  if (!onlyFailures) {
6509
- out.push(renderRunLine(cwd));
6510
- out.push("");
6808
+ out.push(`${BackgroundColors.Run(ansi.white(" RUN "))} ${ansi.dim(ctx.cwd)}`, "");
6511
6809
  }
6512
6810
  for (const file of data.testResults) {
6513
- const rel = file.testFilePath.replace(/\\/g, "/").replace(`${cwd}/`, "");
6811
+ const rel = file.testFilePath.replace(/\\/g, "/").replace(`${ctx.cwd}/`, "");
6514
6812
  const failed = file.testResults.filter((assertion) => assertion.status === "failed");
6515
6813
  if (!onlyFailures) {
6516
6814
  out.push(...buildPerFileOverview(rel, file.testResults));
@@ -6518,91 +6816,842 @@ function renderVitestFromJestJSON(data, opts) {
6518
6816
  if (!(onlyFailures && failed.length === 0)) {
6519
6817
  out.push(buildFileBadgeLine(rel, failed.length));
6520
6818
  }
6521
- if (file.failureMessage && failed.length === 0) {
6819
+ let httpSorted = [];
6820
+ let assertionEvents = [];
6821
+ {
6822
+ const parseBridge = (consoleEntries) => {
6823
+ const http = [];
6824
+ const assertions = [];
6825
+ if (!Array.isArray(consoleEntries)) {
6826
+ return { http, assertions };
6827
+ }
6828
+ for (const entry of consoleEntries) {
6829
+ const rec = entry;
6830
+ const rawMsgVal = rec && typeof rec.message !== "undefined" ? rec.message : "";
6831
+ const raw = Array.isArray(rawMsgVal) ? rawMsgVal.map(String).join(" ") : String(rawMsgVal ?? "");
6832
+ if (!raw.includes("[JEST-BRIDGE-EVENT]")) {
6833
+ continue;
6834
+ }
6835
+ const jsonText = raw.split("[JEST-BRIDGE-EVENT]").pop()?.trim() ?? "";
6836
+ try {
6837
+ const evt = import_json52.default.parse(jsonText);
6838
+ const type = evt?.type;
6839
+ if (type === "httpResponse") {
6840
+ const timestampMs = Number(evt.timestampMs ?? Date.now());
6841
+ http.push({
6842
+ kind: "response",
6843
+ timestampMs,
6844
+ method: evt.method,
6845
+ url: evt.url,
6846
+ route: evt.route,
6847
+ statusCode: evt.statusCode,
6848
+ durationMs: evt.durationMs,
6849
+ contentType: evt.contentType,
6850
+ requestId: evt.requestId,
6851
+ json: evt.json,
6852
+ bodyPreview: evt.bodyPreview,
6853
+ testPath: evt.testPath,
6854
+ currentTestName: evt.currentTestName
6855
+ });
6856
+ } else if (type === "httpAbort") {
6857
+ http.push({
6858
+ kind: "abort",
6859
+ timestampMs: Number(evt.timestampMs ?? Date.now()),
6860
+ method: evt.method,
6861
+ url: evt.url,
6862
+ route: evt.route,
6863
+ durationMs: evt.durationMs,
6864
+ testPath: evt.testPath,
6865
+ currentTestName: evt.currentTestName
6866
+ });
6867
+ } else if (type === "httpResponseBatch") {
6868
+ const list = asHttpList(evt?.events);
6869
+ for (const item of list) {
6870
+ const anyItem = item;
6871
+ http.push({
6872
+ timestampMs: Number(anyItem.timestampMs ?? Date.now()),
6873
+ method: anyItem.method,
6874
+ url: anyItem.url,
6875
+ route: anyItem.route,
6876
+ statusCode: anyItem.statusCode,
6877
+ durationMs: anyItem.durationMs,
6878
+ contentType: anyItem.contentType,
6879
+ requestId: anyItem.requestId,
6880
+ json: anyItem.json,
6881
+ bodyPreview: anyItem.bodyPreview,
6882
+ testPath: evt.testPath,
6883
+ currentTestName: evt.currentTestName
6884
+ });
6885
+ }
6886
+ } else if (type === "assertionFailure") {
6887
+ assertions.push({
6888
+ timestampMs: typeof evt.timestampMs === "number" ? evt.timestampMs : void 0,
6889
+ matcher: evt.matcher,
6890
+ expectedNumber: typeof evt.expectedNumber === "number" ? evt.expectedNumber : void 0,
6891
+ receivedNumber: typeof evt.receivedNumber === "number" ? evt.receivedNumber : void 0,
6892
+ message: typeof evt.message === "string" ? evt.message : void 0,
6893
+ stack: typeof evt.stack === "string" ? evt.stack : void 0,
6894
+ testPath: evt.testPath,
6895
+ currentTestName: evt.currentTestName,
6896
+ expectedPreview: typeof evt.expectedPreview === "string" ? evt.expectedPreview : void 0,
6897
+ actualPreview: typeof evt.actualPreview === "string" ? evt.actualPreview : void 0
6898
+ });
6899
+ }
6900
+ } catch {
6901
+ }
6902
+ }
6903
+ return { http, assertions };
6904
+ };
6905
+ const parsed = parseBridge(file.console);
6906
+ httpSorted = [...parsed.http].sort(by((event) => event.timestampMs));
6907
+ assertionEvents = parsed.assertions;
6908
+ }
6909
+ const inSameCtx = (testPath, testName) => httpSorted.filter(
6910
+ (event) => event.testPath === testPath && event.currentTestName === testName
6911
+ );
6912
+ if (file.failureMessage || file.testExecError) {
6522
6913
  const lines = file.failureMessage.split(/\r?\n/);
6523
- const details = linesFromDetails(file.failureDetails);
6524
- const mergedForStack = collapseStacks([...lines, ...details.stacks]);
6525
- const synthLoc = deepestProjectLoc(mergedForStack, projectHint);
6914
+ const combinedDetails = (() => {
6915
+ const base = linesFromDetails(file.failureDetails);
6916
+ const exec = linesFromDetails(
6917
+ Array.isArray(file.testExecError) ? file.testExecError : [file.testExecError]
6918
+ );
6919
+ return {
6920
+ stacks: [...base.stacks, ...exec.stacks],
6921
+ messages: [...base.messages, ...exec.messages]
6922
+ };
6923
+ })();
6924
+ const mergedForStack = collapseStacks([...lines, ...combinedDetails.stacks]);
6925
+ const synthLoc = deepestProjectLoc(mergedForStack, ctx.projectHint);
6526
6926
  out.push(...buildCodeFrameSection(lines, ctx, synthLoc));
6527
- const payload = extractExpectedReceived(file.failureDetails, lines);
6528
- const hasPretty = payload.expected !== void 0 || payload.received !== void 0;
6529
- out.push(...renderPrettyDiff(payload));
6530
- const stackPreview = ctx.showStacks ? firstProjectFrames(mergedForStack, projectHint, 2) : [];
6927
+ const payloadPretty = buildPrettyDiffSection(file.failureDetails, lines);
6928
+ out.push(...payloadPretty);
6929
+ const hasPretty = payloadPretty.length > 0;
6930
+ const stackPreview = ctx.showStacks ? mergedForStack.filter((ln) => isStackLine(stripAnsiSimple(ln))).filter((ln) => ctx.projectHint.test(stripAnsiSimple(ln))).slice(0, 2).map((ln) => ` ${colorStackLine(String(ln), ctx.projectHint)}`) : [];
6531
6931
  out.push(
6532
- ...buildMessageSection(lines, details, ctx, {
6932
+ ...buildMessageSection(lines, combinedDetails, ctx, {
6533
6933
  suppressDiff: hasPretty,
6534
6934
  stackPreview
6535
6935
  })
6536
6936
  );
6537
- out.push(...buildConsoleSection(file.console ?? null));
6937
+ out.push(...buildConsoleSection(stripBridgeEventsFromConsole(file.console ?? null)));
6538
6938
  if (ctx.showStacks && stackPreview.length === 0) {
6539
- out.push(...buildStackSection(mergedForStack, ctx));
6939
+ const tail = mergedForStack.filter((ln) => isStackLine(stripAnsiSimple(ln))).slice(-4).map((ln) => ` ${colorStackLine(String(ln), ctx.projectHint)}`);
6940
+ if (tail.length) {
6941
+ out.push(ansi.dim(" Stack:"), ...tail, "");
6942
+ }
6540
6943
  }
6541
6944
  }
6542
- for (const failedAssertion of failed) {
6945
+ for (const assertion of failed) {
6543
6946
  out.push(drawFailLine());
6544
- const header = `${rel} > ${failedAssertion.fullName}`;
6545
- const messagesArray = failedAssertion.failureMessages.length > 0 ? failedAssertion.failureMessages : [""];
6546
- const details = linesFromDetails(file.failureDetails);
6947
+ const header = `${rel} > ${assertion.fullName}`;
6948
+ const messagesArray = (() => {
6949
+ if (assertion.failureMessages && assertion.failureMessages.length > 0) {
6950
+ return assertion.failureMessages;
6951
+ }
6952
+ if (file.failureMessage && file.failureMessage.trim().length > 0) {
6953
+ return file.failureMessage.split(/\r?\n/);
6954
+ }
6955
+ const linesFromMatcher = linesFromDetails(
6956
+ assertion.failureDetails || file.failureDetails
6957
+ ).messages;
6958
+ if (Array.isArray(linesFromMatcher) && linesFromMatcher.length > 0) {
6959
+ return linesFromMatcher;
6960
+ }
6961
+ return [""];
6962
+ })();
6963
+ const details = linesFromDetails(assertion.failureDetails || file.failureDetails);
6964
+ const matcherMsg = (() => {
6965
+ try {
6966
+ const arr = assertion.failureDetails || file.failureDetails;
6967
+ if (!arr) {
6968
+ return [];
6969
+ }
6970
+ for (const detailEntry of arr) {
6971
+ const obj = detailEntry && typeof detailEntry === "object" ? detailEntry : null;
6972
+ const mr = obj && obj.matcherResult && typeof obj.matcherResult === "object" ? obj.matcherResult : null;
6973
+ if (mr && typeof mr.message === "string" && mr.message.trim()) {
6974
+ const name = typeof mr.matcherName === "string" ? mr.matcherName : "";
6975
+ const matcherHeader = name ? ` ${ansi.bold("Matcher:")} ${ansi.yellow(name)}` : "";
6976
+ const bodyHeader = ` ${ansi.bold("Message:")}`;
6977
+ const body = String(mr.message).split(/\r?\n/).slice(0, 6).map((ln) => ` ${ansi.yellow(ln)}`);
6978
+ return [matcherHeader, bodyHeader, ...body, ""].filter(Boolean);
6979
+ }
6980
+ }
6981
+ } catch {
6982
+ }
6983
+ return [];
6984
+ })();
6547
6985
  const mergedForStack = collapseStacks([...messagesArray, ...details.stacks]);
6548
- const deepestLoc = deepestProjectLoc(mergedForStack, projectHint);
6549
- const locLink = deepestLoc && (() => {
6550
- const href = preferredEditorHref(deepestLoc.file, deepestLoc.line, opts?.editorCmd);
6551
- const base = `${path9.basename(deepestLoc.file)}:${deepestLoc.line}`;
6986
+ const deepestLoc = deepestProjectLoc(mergedForStack, ctx.projectHint);
6987
+ const locLink = deepestLoc ? (() => {
6988
+ const href = preferredEditorHref(deepestLoc.file, deepestLoc.line, ctx.editorCmd);
6989
+ const base = `${deepestLoc.file.split("/").pop()}:${deepestLoc.line}`;
6552
6990
  return osc8(base, href);
6553
- })();
6991
+ })() : void 0;
6992
+ const bullet = (text) => `${Colors.Failure("\xD7")} ${ansi.white(text)}`;
6554
6993
  const headerLine = `${ansi.white(header)}${locLink ? ` ${ansi.dim(`(${locLink})`)}` : ""}`;
6555
- const bullet = (text) => `${colorTokens.fail("\xD7")} ${ansi.white(text)}`;
6556
6994
  out.push(bullet(headerLine));
6557
6995
  const msgLines = messagesArray.join("\n").split("\n");
6558
- const assertFallback = deepestLoc || failedAssertion.location && {
6559
- file: file.testFilePath,
6560
- line: failedAssertion.location.line
6561
- };
6562
- out.push("", ...buildCodeFrameSection(msgLines, ctx, assertFallback), "");
6563
- const payload = extractExpectedReceived(file.failureDetails, msgLines);
6564
- const hasPretty = payload.expected !== void 0 || payload.received !== void 0;
6565
- out.push(...renderPrettyDiff(payload));
6566
- const stackPreview = ctx.showStacks ? firstProjectFrames(mergedForStack, projectHint, 2) : [];
6996
+ const assertFallback = deepestLoc || assertion.location && { file: file.testFilePath, line: assertion.location.line };
6997
+ out.push("", ...buildCodeFrameSection(msgLines, ctx, assertFallback || void 0), "");
6998
+ const pretty = buildPrettyDiffSection(
6999
+ assertion.failureDetails || file.failureDetails,
7000
+ msgLines
7001
+ );
7002
+ out.push(...pretty);
7003
+ const hasPretty = pretty.length > 0;
7004
+ const stackPreview = ctx.showStacks ? mergedForStack.filter((ln) => isStackLine(stripAnsiSimple(ln))).filter((ln) => ctx.projectHint.test(stripAnsiSimple(ln))).slice(0, 2).map((ln) => ` ${colorStackLine(String(ln), ctx.projectHint)}`) : [];
7005
+ if (matcherMsg.length) {
7006
+ out.push(...matcherMsg);
7007
+ }
6567
7008
  out.push(
6568
7009
  ...buildMessageSection(msgLines, details, ctx, { suppressDiff: hasPretty, stackPreview })
6569
7010
  );
6570
- if (ctx.showStacks && stackPreview.length === 0) {
6571
- out.push(
6572
- ...buildStackSection(
6573
- mergedForStack,
6574
- ctx,
6575
- failedAssertion.location ? { file: file.testFilePath, line: failedAssertion.location.line } : null
6576
- )
7011
+ {
7012
+ const HEADLAMP_HTTP_DIFF_LIMIT_LOCAL = () => HEADLAMP_HTTP_DIFF_LIMIT();
7013
+ const safeParseJSON = (text) => {
7014
+ try {
7015
+ return text ? import_json52.default.parse(text) : void 0;
7016
+ } catch {
7017
+ return void 0;
7018
+ }
7019
+ };
7020
+ const jsonDiff = (expected, actual, limit = HEADLAMP_HTTP_DIFF_LIMIT_LOCAL()) => {
7021
+ const outChanges = [];
7022
+ const queue = [];
7023
+ queue.push({
7024
+ pathSoFar: "$",
7025
+ expectedValue: expected,
7026
+ actualValue: actual
7027
+ });
7028
+ while (queue.length && outChanges.length < limit) {
7029
+ const { pathSoFar, expectedValue, actualValue } = queue.shift();
7030
+ const expectedIsObj = expectedValue && typeof expectedValue === "object";
7031
+ const actualIsObj = actualValue && typeof actualValue === "object";
7032
+ if (!expectedIsObj && !actualIsObj) {
7033
+ if (JSON.stringify(expectedValue) !== JSON.stringify(actualValue)) {
7034
+ outChanges.push({
7035
+ kind: "changed",
7036
+ path: pathSoFar,
7037
+ preview: `${String(expectedValue)} \u2192 ${String(actualValue)}`
7038
+ });
7039
+ }
7040
+ } else if (expectedIsObj && !actualIsObj) {
7041
+ outChanges.push({
7042
+ kind: "changed",
7043
+ path: pathSoFar,
7044
+ preview: "[object] \u2192 primitive"
7045
+ });
7046
+ } else if (!expectedIsObj && actualIsObj) {
7047
+ outChanges.push({
7048
+ kind: "changed",
7049
+ path: pathSoFar,
7050
+ preview: "primitive \u2192 [object]"
7051
+ });
7052
+ } else {
7053
+ const expectedKeys = new Set(Object.keys(expectedValue));
7054
+ const actualKeys = new Set(Object.keys(actualValue));
7055
+ for (const key of expectedKeys) {
7056
+ if (!actualKeys.has(key) && outChanges.length < limit) {
7057
+ outChanges.push({ kind: "removed", path: `${pathSoFar}.${key}` });
7058
+ }
7059
+ }
7060
+ for (const key of actualKeys) {
7061
+ if (!expectedKeys.has(key) && outChanges.length < limit) {
7062
+ outChanges.push({ kind: "added", path: `${pathSoFar}.${key}` });
7063
+ }
7064
+ }
7065
+ for (const key of expectedKeys) {
7066
+ if (actualKeys.has(key) && outChanges.length < limit) {
7067
+ queue.push({
7068
+ pathSoFar: `${pathSoFar}.${key}`,
7069
+ expectedValue: expectedValue[key],
7070
+ actualValue: actualValue[key]
7071
+ });
7072
+ }
7073
+ }
7074
+ }
7075
+ }
7076
+ return outChanges;
7077
+ };
7078
+ const importantMessages = (json) => {
7079
+ const msgs = [];
7080
+ try {
7081
+ const obj = isObject(json) ? json : {};
7082
+ const pushMaybe = (candidate) => {
7083
+ if (typeof candidate === "string" && candidate.trim()) {
7084
+ msgs.push(candidate);
7085
+ }
7086
+ };
7087
+ pushMaybe(obj.displayMessage);
7088
+ pushMaybe(obj.message);
7089
+ if (Array.isArray(obj.errors)) {
7090
+ for (const element of obj.errors) {
7091
+ pushMaybe(isObject(element) ? element.message : void 0);
7092
+ }
7093
+ }
7094
+ if (Array.isArray(obj.data)) {
7095
+ for (const element of obj.data) {
7096
+ pushMaybe(isObject(element) ? element.message : void 0);
7097
+ }
7098
+ }
7099
+ } catch {
7100
+ }
7101
+ return msgs.slice(0, 2);
7102
+ };
7103
+ const nameMatches = (leftName, rightName) => !!leftName && !!rightName && (leftName === rightName || leftName.includes(rightName) || rightName.includes(leftName));
7104
+ const corresponding = assertionEvents.find(
7105
+ (aevt) => aevt.testPath === file.testFilePath && nameMatches(aevt.currentTestName, assertion.title)
7106
+ ) ?? assertion;
7107
+ const perTestSlice = inSameCtx(file.testFilePath, assertion.title);
7108
+ const nearByTime = eventsNear(
7109
+ httpSorted,
7110
+ corresponding?.timestampMs,
7111
+ file.testFilePath
6577
7112
  );
7113
+ const hasAbort = perTestSlice.some((event) => event.kind === "abort");
7114
+ const hasTransport = isTransportError(corresponding?.message) || hasAbort;
7115
+ const httpLikely = isHttpRelevant({
7116
+ assertion: corresponding,
7117
+ title: assertion.fullName,
7118
+ relPath: rel,
7119
+ httpCountInSameTest: perTestSlice.length || nearByTime.length,
7120
+ hasTransportSignal: hasTransport
7121
+ });
7122
+ if (!httpLikely) {
7123
+ } else {
7124
+ const expPreview = corresponding?.expectedPreview;
7125
+ const actPreview = corresponding?.actualPreview;
7126
+ const parsedExpected = safeParseJSON(expPreview);
7127
+ const parsedActual = safeParseJSON(actPreview);
7128
+ let corr = corresponding;
7129
+ if (!isHttpStatusNumber(corr.expectedNumber) && !isHttpStatusNumber(corr.receivedNumber)) {
7130
+ const inferred = inferHttpNumbersFromText(msgLines);
7131
+ if (isHttpStatusNumber(inferred.expectedNumber) || isHttpStatusNumber(inferred.receivedNumber)) {
7132
+ corr = { ...corr, ...inferred };
7133
+ }
7134
+ }
7135
+ const relevant = pickRelevantHttp(
7136
+ {
7137
+ timestampMs: corr?.timestampMs,
7138
+ expectedNumber: corr?.expectedNumber,
7139
+ receivedNumber: corr?.receivedNumber,
7140
+ matcher: corr?.matcher,
7141
+ message: corr?.message,
7142
+ stack: corr?.stack,
7143
+ testPath: file.testFilePath,
7144
+ currentTestName: assertion.title
7145
+ },
7146
+ httpSorted,
7147
+ {
7148
+ testPath: file.testFilePath,
7149
+ currentTestName: assertion.title,
7150
+ title: assertion.fullName
7151
+ }
7152
+ );
7153
+ if (hasTransport) {
7154
+ const tsBase = corresponding?.timestampMs ?? 0;
7155
+ const abortCandidates = perTestSlice.filter((event) => event.kind === "abort").sort((leftEvent, rightEvent) => {
7156
+ const deltaLeft = Math.abs(tsBase - (leftEvent.timestampMs ?? 0));
7157
+ const deltaRight = Math.abs(tsBase - (rightEvent.timestampMs ?? 0));
7158
+ return deltaLeft - deltaRight;
7159
+ });
7160
+ const [nearestAbort] = abortCandidates;
7161
+ if (nearestAbort) {
7162
+ out.push(
7163
+ " HTTP:",
7164
+ `
7165
+ ${summarizeUrl(nearestAbort.method, nearestAbort.url, nearestAbort.route)} ${ansi.dim("->")} ${ansi.yellow("connection aborted")}`,
7166
+ (() => {
7167
+ const ms = nearestAbort.durationMs;
7168
+ return ms != null ? ` ${ansi.dim(`(${ms}ms)`)} ` : "";
7169
+ })(),
7170
+ "\n"
7171
+ );
7172
+ } else if (relevant) {
7173
+ } else if (HEADLAMP_HTTP_SHOW_MISS()) {
7174
+ out.push(
7175
+ " HTTP:",
7176
+ `
7177
+ ${ansi.dim("Transport error; no matching HTTP exchange in window.")}`,
7178
+ "\n"
7179
+ );
7180
+ }
7181
+ }
7182
+ if (!hasTransport && relevant) {
7183
+ const parts = [];
7184
+ const where = summarizeUrl(relevant.method, relevant.url, relevant.route);
7185
+ const line1 = [
7186
+ " HTTP:",
7187
+ `
7188
+ ${where} ${ansi.dim("->")} ${relevant.statusCode ?? "?"}`,
7189
+ (() => {
7190
+ const ms = relevant.durationMs;
7191
+ return typeof ms === "number" ? ` ${ansi.dim(`(${ms}ms)`)} ` : " ";
7192
+ })(),
7193
+ relevant.contentType ? ansi.dim(`(${relevant.contentType})`) : "",
7194
+ relevant.requestId ? ansi.dim(` reqId=${relevant.requestId}`) : ""
7195
+ ].join("");
7196
+ const expVsAct = (() => {
7197
+ if (typeof corresponding?.expectedNumber === "number" || typeof corresponding?.receivedNumber === "number") {
7198
+ const exp = corresponding?.expectedNumber != null ? String(corresponding.expectedNumber) : "?";
7199
+ const got = corresponding?.receivedNumber != null ? String(corresponding.receivedNumber) : String(relevant.statusCode ?? "?");
7200
+ return `
7201
+ Expected: ${ansi.yellow(exp)} Received: ${ansi.yellow(got)}`;
7202
+ }
7203
+ return "";
7204
+ })();
7205
+ const whyLines = importantMessages(relevant.json).map((msg) => `
7206
+ Why: ${ansi.white(msg)}`).slice(0, 1).join("");
7207
+ const diffLines = (() => {
7208
+ const rightActual = parsedActual ?? relevant.json;
7209
+ if (!parsedExpected || !rightActual) {
7210
+ return "";
7211
+ }
7212
+ const changes = jsonDiff(parsedExpected, rightActual);
7213
+ if (!changes.length) {
7214
+ return "";
7215
+ }
7216
+ const head = "\n Diff:";
7217
+ const body = changes.map((change) => {
7218
+ const marker = change.kind === "added" ? "+" : change.kind === "removed" ? "-" : "~";
7219
+ const previewText = change.preview ? `: ${ansi.dim(change.preview)}` : "";
7220
+ return `
7221
+ ${marker} ${change.path}${previewText}`;
7222
+ }).join("");
7223
+ return head + body;
7224
+ })();
7225
+ parts.push(line1, expVsAct, whyLines, diffLines, "\n");
7226
+ out.push(...parts.filter(Boolean));
7227
+ } else if (!hasTransport && !relevant && HEADLAMP_HTTP_SHOW_MISS()) {
7228
+ out.push(
7229
+ " HTTP:",
7230
+ `
7231
+ ${ansi.dim("No relevant HTTP exchange found. (HEADLAMP_HTTP_MISS=0 to hide)")}`,
7232
+ "\n"
7233
+ );
7234
+ }
7235
+ }
6578
7236
  }
6579
- out.push(drawFailLine());
6580
- out.push("");
7237
+ const minimalInfo = msgLines.every((ln) => !ln.trim());
7238
+ if (minimalInfo) {
7239
+ try {
7240
+ out.push(...buildThrownSection(assertion.failureDetails || []));
7241
+ } catch {
7242
+ }
7243
+ }
7244
+ out.push(...buildConsoleSection(stripBridgeEventsFromConsole(file.console ?? null)));
7245
+ if (ctx.showStacks && stackPreview.length === 0) {
7246
+ const tail = mergedForStack.filter((ln) => isStackLine(stripAnsiSimple(ln))).slice(-4).map((ln) => ` ${colorStackLine(String(ln), ctx.projectHint)}`);
7247
+ if (tail.length) {
7248
+ out.push(ansi.dim(" Stack:"), ...tail, "");
7249
+ }
7250
+ }
7251
+ out.push(drawFailLine(), "");
6581
7252
  }
6582
7253
  }
6583
7254
  const failedCount = data.aggregated.numFailedTests;
6584
- out.push(drawRule(colorTokens.failPill(` Failed Tests ${failedCount} `)));
7255
+ out.push(drawRule(BackgroundColors.Failure(ansi.white(` Failed Tests ${failedCount} `))));
6585
7256
  out.push("");
6586
- const footer = vitestFooter(
6587
- data.aggregated,
6588
- data.aggregated?.startTime ?? data.startTime,
6589
- data.aggregated?.runTimeMs
6590
- );
6591
- return `${out.join("\n")}
6592
- ${footer}`;
7257
+ out.push(vitestFooter(data.aggregated));
7258
+ return out.join("\n");
7259
+ };
7260
+ var tryBridgeFallback = (raw, ctx, opts) => {
7261
+ const bridgeJsonPath = extractBridgePath2(raw, ctx.cwd);
7262
+ if (!bridgeJsonPath || !fs6.existsSync(bridgeJsonPath)) {
7263
+ return null;
7264
+ }
7265
+ try {
7266
+ const json = import_json52.default.parse(fs6.readFileSync(bridgeJsonPath, "utf8"));
7267
+ const bridge = coerceJestJsonToBridge(json);
7268
+ return renderVitestFromJestJSON(bridge, ctx, opts);
7269
+ } catch {
7270
+ return null;
7271
+ }
7272
+ };
7273
+
7274
+ // src/lib/formatJestOutputVitest.ts
7275
+ var formatJestOutputVitest = (raw, opts) => pipe(
7276
+ { raw, opts },
7277
+ (state) => ({
7278
+ ...state,
7279
+ ctx: makeCtx(state.opts, /\bFAIL\b/.test(stripAnsiSimple(state.raw)))
7280
+ }),
7281
+ (state) => ({ ...state, chunks: parseChunks(state.raw) }),
7282
+ (state) => ({
7283
+ ...state,
7284
+ rendered: renderChunks(state.chunks, state.ctx, mkPrettyFns(), {
7285
+ onlyFailures: Boolean(state.opts?.onlyFailures)
7286
+ })
7287
+ }),
7288
+ (state) => {
7289
+ if (state.rendered.hadParsed) {
7290
+ return state.rendered.text;
7291
+ }
7292
+ const fallback = tryBridgeFallback(state.raw, state.ctx, {
7293
+ onlyFailures: Boolean(state.opts?.onlyFailures)
7294
+ });
7295
+ if (!fallback) {
7296
+ return state.rendered.text;
7297
+ }
7298
+ const prefix = state.rendered.text;
7299
+ return prefix ? `${prefix}
7300
+ ${fallback}` : fallback;
7301
+ }
7302
+ );
7303
+
7304
+ // src/lib/jest-reporter-source.ts
7305
+ var JEST_BRIDGE_REPORTER_SOURCE = `const fs = require('fs');
7306
+ const path = require('path');
7307
+
7308
+ const isObject = (v) => typeof v === 'object' && v !== null;
7309
+ const sanitizeError = (err) => {
7310
+ if (!isObject(err)) return err;
7311
+ const out = {};
7312
+ const name = err.name || (err.constructor && err.constructor.name) || undefined;
7313
+ if (name) out.name = String(name);
7314
+ if (typeof err.message === 'string') out.message = err.message;
7315
+ if (typeof err.stack === 'string') out.stack = err.stack;
7316
+ if (err.code !== undefined) out.code = err.code;
7317
+ if (err.expected !== undefined) out.expected = err.expected;
7318
+ if (err.received !== undefined) out.received = err.received;
7319
+ if (err.matcherResult && isObject(err.matcherResult)) {
7320
+ const mr = err.matcherResult;
7321
+ let messageText;
7322
+ try {
7323
+ messageText = typeof mr.message === 'function' ? String(mr.message()) : (typeof mr.message === 'string' ? mr.message : undefined);
7324
+ } catch {}
7325
+ out.matcherResult = {
7326
+ matcherName: typeof mr.matcherName === 'string' ? mr.matcherName : undefined,
7327
+ message: messageText,
7328
+ stack: typeof mr.stack === 'string' ? mr.stack : undefined,
7329
+ expected: mr.expected,
7330
+ received: mr.received,
7331
+ actual: mr.actual,
7332
+ pass: typeof mr.pass === 'boolean' ? mr.pass : undefined,
7333
+ };
7334
+ }
7335
+ if (err.cause) {
7336
+ out.cause = sanitizeError(err.cause);
7337
+ }
7338
+ // Copy own enumerable props to preserve custom data
7339
+ try {
7340
+ for (const key of Object.keys(err)) {
7341
+ if (!(key in out)) out[key] = err[key];
7342
+ }
7343
+ } catch {}
7344
+ return out;
7345
+ };
7346
+ const sanitizeDetail = (d) => {
7347
+ if (typeof d === 'string') return d;
7348
+ if (!isObject(d)) return d;
7349
+ // Common Jest detail shapes
7350
+ const out = {};
7351
+ if (d.message) out.message = d.message;
7352
+ if (d.stack) out.stack = d.stack;
7353
+ if (d.error) out.error = sanitizeError(d.error);
7354
+ if (d.matcherResult) out.matcherResult = sanitizeError({ matcherResult: d.matcherResult }).matcherResult;
7355
+ if (d.expected !== undefined) out.expected = d.expected;
7356
+ if (d.received !== undefined) out.received = d.received;
7357
+ // Copy the rest
7358
+ try {
7359
+ for (const key of Object.keys(d)) {
7360
+ if (!(key in out)) out[key] = d[key];
7361
+ }
7362
+ } catch {}
7363
+ return out;
7364
+ };
7365
+
7366
+ class BridgeReporter {
7367
+ constructor(globalConfig, options) {
7368
+ this.out = process.env.JEST_BRIDGE_OUT || (options && options.outFile) || path.join(process.cwd(), 'coverage', 'jest-run.json');
7369
+ this.buf = { startTime: Date.now(), testResults: [], aggregated: null };
7370
+ }
7371
+ onRunStart() { this.buf.startTime = Date.now(); }
7372
+ onTestResult(_test, tr) {
7373
+ const mapAssertion = (a) => ({
7374
+ title: a.title,
7375
+ fullName: a.fullName || [...(a.ancestorTitles || []), a.title].join(' '),
7376
+ status: a.status,
7377
+ duration: a.duration || 0,
7378
+ location: a.location || null,
7379
+ failureMessages: (a.failureMessages || []).map(String),
7380
+ failureDetails: (a.failureDetails || []).map(sanitizeDetail),
7381
+ });
7382
+ this.buf.testResults.push({
7383
+ testFilePath: tr.testFilePath,
7384
+ status: tr.numFailingTests ? 'failed' : 'passed',
7385
+ failureMessage: tr.failureMessage || '',
7386
+ failureDetails: (tr.failureDetails || []).map(sanitizeDetail),
7387
+ testExecError: tr.testExecError ? sanitizeError(tr.testExecError) : null,
7388
+ console: tr.console || null,
7389
+ perfStats: tr.perfStats || {},
7390
+ testResults: (tr.testResults || []).map(mapAssertion),
7391
+ });
7392
+ }
7393
+ onRunComplete(_contexts, agg) {
7394
+ this.buf.aggregated = {
7395
+ numTotalTestSuites: agg.numTotalTestSuites,
7396
+ numPassedTestSuites: agg.numPassedTestSuites,
7397
+ numFailedTestSuites: agg.numFailedTestSuites,
7398
+ numTotalTests: agg.numTotalTests,
7399
+ numPassedTests: agg.numPassedTests,
7400
+ numFailedTests: agg.numFailedTests,
7401
+ numPendingTests: agg.numPendingTests,
7402
+ numTodoTests: agg.numTodoTests,
7403
+ startTime: agg.startTime,
7404
+ success: agg.success,
7405
+ runTimeMs: agg.testResults.reduce((t, r) => t + Math.max(0, (r.perfStats?.end || 0) - (r.perfStats?.start || 0)), 0),
7406
+ };
7407
+ fs.mkdirSync(path.dirname(this.out), { recursive: true });
7408
+ fs.writeFileSync(this.out, JSON.stringify(this.buf), 'utf8');
7409
+ }
6593
7410
  }
7411
+ module.exports = BridgeReporter;`;
6594
7412
 
6595
7413
  // src/lib/program.ts
6596
7414
  init_env_utils();
6597
7415
  init_exec();
6598
7416
  init_args();
6599
- import * as path10 from "node:path";
7417
+ import * as path11 from "node:path";
6600
7418
  import * as os2 from "node:os";
6601
7419
  import * as fsSync3 from "node:fs";
6602
- import * as fs5 from "node:fs/promises";
7420
+ import * as fs7 from "node:fs/promises";
6603
7421
  import * as LibReport from "istanbul-lib-report";
6604
7422
  import * as Reports from "istanbul-reports";
6605
7423
  import { createCoverageMap as createCoverageMap2 } from "istanbul-lib-coverage";
7424
+
7425
+ // src/lib/jest-environment-source.ts
7426
+ var JEST_BRIDGE_ENV_SOURCE = `
7427
+ 'use strict';
7428
+
7429
+ const NodeEnvironment = require('jest-environment-node').TestEnvironment || require('jest-environment-node');
7430
+
7431
+ module.exports = class BridgeEnv extends NodeEnvironment {
7432
+ constructor(config, context) {
7433
+ super(config, context);
7434
+ const { AsyncLocalStorage } = require('node:async_hooks');
7435
+ this._als = new AsyncLocalStorage();
7436
+ this._cleanup = [];
7437
+ }
7438
+
7439
+ _ctx() {
7440
+ try { const s = this._als.getStore(); if (s) return s; } catch {}
7441
+ try {
7442
+ const st = this.global.expect && typeof this.global.expect.getState === 'function' ? this.global.expect.getState() : {};
7443
+ return { testPath: st.testPath, currentTestName: st.currentTestName };
7444
+ } catch { return {}; }
7445
+ }
7446
+
7447
+ async setup() {
7448
+ await super.setup();
7449
+
7450
+ try { Error.stackTraceLimit = Math.max(Error.stackTraceLimit || 10, 50); } catch {}
7451
+
7452
+ const print = (payload) => { try { this.global.console.error('[JEST-BRIDGE-EVENT]', JSON.stringify(payload)); } catch {} };
7453
+ const toErr = (x) => { try { return x instanceof Error ? x : new Error(String(x)); } catch { return new Error('unknown'); } };
7454
+
7455
+ const onRej = (reason) => {
7456
+ const e = toErr(reason);
7457
+ const c = this._ctx();
7458
+ print({ type: 'unhandledRejection', name: e.name, message: e.message, stack: e.stack, code: e.code ?? undefined, ...c });
7459
+ };
7460
+ const onExc = (error) => {
7461
+ const e = toErr(error);
7462
+ const c = this._ctx();
7463
+ print({ type: 'uncaughtException', name: e.name, message: e.message, stack: e.stack, code: e.code ?? undefined, ...c });
7464
+ };
7465
+
7466
+ this.global.process.on('unhandledRejection', onRej);
7467
+ this.global.process.on('uncaughtException', onExc);
7468
+ this._cleanup.push(() => {
7469
+ this.global.process.off('unhandledRejection', onRej);
7470
+ this.global.process.off('uncaughtException', onExc);
7471
+ });
7472
+
7473
+ // Signal environment readiness so we can confirm the custom env loaded
7474
+ try { const c = this._ctx(); print({ type: 'envReady', ...c }); } catch {}
7475
+
7476
+ try {
7477
+ const http = this.global.require ? this.global.require('http') : require('http');
7478
+ const originalEmit = http && http.Server && http.Server.prototype && http.Server.prototype.emit;
7479
+ if (originalEmit) {
7480
+ const MAX = 64 * 1024;
7481
+ const asString = (x) => { try { if (typeof x === 'string') return x; if (Buffer.isBuffer(x)) return x.toString('utf8'); return String(x); } catch { return ''; } };
7482
+
7483
+ const patched = function(eventName, req, res) {
7484
+ try {
7485
+ if (eventName === 'request' && req && res && typeof res.write === 'function' && typeof res.end === 'function') {
7486
+ const startAt = Date.now();
7487
+ const safeHeader = (k) => { try { return req && req.headers ? String((req.headers[k.toLowerCase()] ?? '')) : ''; } catch { return ''; } };
7488
+ const reqIdHeader = safeHeader('x-request-id');
7489
+ const chunks = [];
7490
+ const write = res.write.bind(res);
7491
+ const end = res.end.bind(res);
7492
+ const method = req.method ? String(req.method) : undefined;
7493
+ const url = (req.originalUrl || req.url) ? String(req.originalUrl || req.url) : undefined;
7494
+
7495
+ res.write = function(chunk, enc, cb) {
7496
+ try { const s = asString(chunk); if (s) chunks.push(s); } catch {}
7497
+ return write(chunk, enc, cb);
7498
+ };
7499
+ res.end = function(chunk, enc, cb) {
7500
+ try { const s = asString(chunk); if (s) chunks.push(s); } catch {}
7501
+ try {
7502
+ const preview = chunks.join('').slice(0, MAX);
7503
+ const statusCode = typeof res.statusCode === 'number' ? res.statusCode : undefined;
7504
+ const ct = (typeof res.getHeader === 'function' && res.getHeader('content-type')) || undefined;
7505
+ const routePath = (req && req.route && req.route.path) || (req && req.baseUrl && req.path ? (req.baseUrl + req.path) : undefined);
7506
+ const jsonParsed = (() => { try { return JSON.parse(preview); } catch { return undefined; } })();
7507
+ const requestId = reqIdHeader || (jsonParsed && typeof jsonParsed === 'object' ? (jsonParsed.requestId || jsonParsed.reqId || '') : '');
7508
+ const ctx = (global.__JEST_BRIDGE_ENV_REF && global.__JEST_BRIDGE_ENV_REF._ctx) ? global.__JEST_BRIDGE_ENV_REF._ctx() : {};
7509
+ const payload = {
7510
+ type: 'httpResponse',
7511
+ timestampMs: Date.now(),
7512
+ durationMs: Math.max(0, Date.now() - startAt),
7513
+ method, url, statusCode,
7514
+ route: routePath ? String(routePath) : undefined,
7515
+ contentType: ct ? String(ct) : undefined,
7516
+ headers: (typeof res.getHeaders === 'function') ? res.getHeaders() : undefined,
7517
+ requestId: requestId ? String(requestId) : undefined,
7518
+ bodyPreview: preview,
7519
+ json: jsonParsed,
7520
+ testPath: ctx.testPath, currentTestName: ctx.currentTestName,
7521
+ };
7522
+ try {
7523
+ if (!global.__JEST_HTTP_EVENTS__) global.__JEST_HTTP_EVENTS__ = [];
7524
+ const arr = global.__JEST_HTTP_EVENTS__;
7525
+ arr.push({ timestampMs: payload.timestampMs, durationMs: payload.durationMs, method: payload.method, url: payload.url, route: payload.route, statusCode: payload.statusCode, contentType: payload.contentType, requestId: payload.requestId, json: payload.json, bodyPreview: payload.bodyPreview });
7526
+ if (arr.length > 25) arr.splice(0, arr.length - 25);
7527
+ } catch {}
7528
+ try { console.error('[JEST-BRIDGE-EVENT]', JSON.stringify(payload)); } catch {}
7529
+ } catch {}
7530
+ return end(chunk, enc, cb);
7531
+ };
7532
+ try {
7533
+ res.on('close', function onClose() {
7534
+ try {
7535
+ const ended = typeof res.writableEnded === 'boolean' ? res.writableEnded : false;
7536
+ if (!ended) {
7537
+ const routePath = (req && req.route && req.route.path) || (req && req.baseUrl && req.path ? (req.baseUrl + req.path) : undefined);
7538
+ const ctx = (global.__JEST_BRIDGE_ENV_REF && global.__JEST_BRIDGE_ENV_REF._ctx) ? global.__JEST_BRIDGE_ENV_REF._ctx() : {};
7539
+ const payload = {
7540
+ type: 'httpAbort',
7541
+ timestampMs: Date.now(),
7542
+ durationMs: Math.max(0, Date.now() - startAt),
7543
+ method, url,
7544
+ route: routePath ? String(routePath) : undefined,
7545
+ testPath: ctx.testPath, currentTestName: ctx.currentTestName,
7546
+ };
7547
+ try { console.error('[JEST-BRIDGE-EVENT]', JSON.stringify(payload)); } catch {}
7548
+ }
7549
+ } catch {}
7550
+ });
7551
+ } catch {}
7552
+ }
7553
+ } catch {}
7554
+ return originalEmit.apply(this, arguments);
7555
+ };
7556
+
7557
+ try { this.global.__JEST_BRIDGE_ENV_REF = this; } catch {}
7558
+ http.Server.prototype.emit = patched;
7559
+
7560
+ this._cleanup.push(() => {
7561
+ try { if (http.Server && http.Server.prototype) http.Server.prototype.emit = originalEmit; } catch {}
7562
+ try { delete this.global.__JEST_BRIDGE_ENV_REF; } catch {}
7563
+ });
7564
+ }
7565
+ } catch {}
7566
+
7567
+ // Wrap test functions to emit rich assertion events on failures
7568
+ try {
7569
+ const g = this.global;
7570
+ const ctxFn = () => {
7571
+ try {
7572
+ const ref = g.__JEST_BRIDGE_ENV_REF;
7573
+ return ref && typeof ref._ctx === 'function' ? ref._ctx() : {};
7574
+ } catch { return {}; }
7575
+ };
7576
+ const emitAssertion = (err) => {
7577
+ try {
7578
+ const e = toErr(err);
7579
+ const mr = e && typeof e === 'object' && e.matcherResult ? e.matcherResult : undefined;
7580
+ const messageText = (() => { try { return mr && typeof mr.message === 'function' ? String(mr.message()) : (e.message || ''); } catch { return e.message || ''; } })();
7581
+ const expectedPreview = (() => { try { return mr && mr.expected !== undefined ? JSON.stringify(mr.expected, null, 2) : undefined; } catch { return undefined; } })();
7582
+ const actualPreview = (() => { try { return mr && mr.received !== undefined ? JSON.stringify(mr.received, null, 2) : undefined; } catch { return undefined; } })();
7583
+ const c = ctxFn();
7584
+ const expectedRaw = (() => { try { return mr?.expected; } catch { return undefined; } })();
7585
+ const receivedRaw = (() => { try { return mr?.received; } catch { return undefined; } })();
7586
+ print({
7587
+ type: 'assertionFailure',
7588
+ timestampMs: Date.now(),
7589
+ matcher: mr && typeof mr.matcherName === 'string' ? mr.matcherName : undefined,
7590
+ expectedPreview,
7591
+ actualPreview,
7592
+ expectedNumber: typeof expectedRaw === 'number' ? expectedRaw : undefined,
7593
+ receivedNumber: typeof receivedRaw === 'number' ? receivedRaw : undefined,
7594
+ message: messageText,
7595
+ stack: e.stack,
7596
+ ...c,
7597
+ });
7598
+ } catch {}
7599
+ };
7600
+ const wrap = (orig) => {
7601
+ if (!orig || typeof orig !== 'function') return orig;
7602
+ const wrapped = function(name, fn, timeout) {
7603
+ if (typeof fn !== 'function') return orig.call(this, name, fn, timeout);
7604
+ const run = function() {
7605
+ try {
7606
+ const res = fn.apply(this, arguments);
7607
+ if (res && typeof res.then === 'function') {
7608
+ return res.catch((err) => { emitAssertion(err); throw err; });
7609
+ }
7610
+ return res;
7611
+ } catch (err) {
7612
+ emitAssertion(err);
7613
+ throw err;
7614
+ }
7615
+ };
7616
+ return orig.call(this, name, run, timeout);
7617
+ };
7618
+ try { wrapped.only = orig.only && typeof orig.only === 'function' ? wrap(orig.only) : orig.only; } catch {}
7619
+ try { wrapped.skip = orig.skip && typeof orig.skip === 'function' ? wrap(orig.skip) : orig.skip; } catch {}
7620
+ return wrapped;
7621
+ };
7622
+ try { g.it = wrap(g.it); } catch {}
7623
+ try { g.test = wrap(g.test); } catch {}
7624
+ } catch {}
7625
+ }
7626
+
7627
+ async handleTestEvent(evt, state) {
7628
+ if (evt.name === 'test_start') {
7629
+ const store = { testPath: state.testPath, currentTestName: evt.test.name };
7630
+ try { this._als.enterWith(store); } catch {}
7631
+ } else if (evt.name === 'test_done') {
7632
+ try { this._als.enterWith({}); } catch {}
7633
+ try {
7634
+ const events = Array.isArray(global.__JEST_HTTP_EVENTS__) ? global.__JEST_HTTP_EVENTS__ : [];
7635
+ if (events.length) {
7636
+ const batch = events.slice(-10);
7637
+ const payload = { type: 'httpResponseBatch', events: batch, testPath: state.testPath, currentTestName: evt.test.name };
7638
+ try { this.global.console.error('[JEST-BRIDGE-EVENT]', JSON.stringify(payload)); } catch {}
7639
+ try { global.__JEST_HTTP_EVENTS__ = []; } catch {}
7640
+ }
7641
+ } catch {}
7642
+ }
7643
+ }
7644
+
7645
+ async teardown() {
7646
+ for (let i = this._cleanup.length - 1; i >= 0; i--) {
7647
+ try { this._cleanup[i](); } catch {}
7648
+ }
7649
+ await super.teardown();
7650
+ }
7651
+ };
7652
+ `;
7653
+
7654
+ // src/lib/program.ts
6606
7655
  var jestBin = "./node_modules/.bin/jest";
6607
7656
  var babelNodeBin = "./node_modules/.bin/babel-node";
6608
7657
  var registerSignalHandlersOnce = () => {
@@ -6645,7 +7694,7 @@ var mergeLcov = async () => {
6645
7694
  try {
6646
7695
  const entries = fsSync3.readdirSync(dir, { withFileTypes: true });
6647
7696
  for (const entry of entries) {
6648
- const full = path10.join(dir, entry.name);
7697
+ const full = path11.join(dir, entry.name);
6649
7698
  if (entry.isDirectory()) {
6650
7699
  out.push(...collectLcovs(full));
6651
7700
  } else if (entry.isFile() && entry.name === "lcov.info") {
@@ -6657,8 +7706,8 @@ var mergeLcov = async () => {
6657
7706
  return out;
6658
7707
  };
6659
7708
  try {
6660
- const jestRoot = path10.join("coverage", "jest");
6661
- const candidates = [path10.join(jestRoot, "lcov.info"), ...collectLcovs(jestRoot)].map((candidatePath) => path10.resolve(candidatePath)).filter((absolutePath, index, arr) => arr.indexOf(absolutePath) === index);
7709
+ const jestRoot = path11.join("coverage", "jest");
7710
+ const candidates = [path11.join(jestRoot, "lcov.info"), ...collectLcovs(jestRoot)].map((candidatePath) => path11.resolve(candidatePath)).filter((absolutePath, index, arr) => arr.indexOf(absolutePath) === index);
6662
7711
  for (const filePath of candidates) {
6663
7712
  try {
6664
7713
  const content = await readOrEmpty(filePath);
@@ -6698,7 +7747,7 @@ var emitMergedCoverage = async (ui, opts) => {
6698
7747
  try {
6699
7748
  const entries = fsSync3.readdirSync(dir, { withFileTypes: true });
6700
7749
  for (const entry of entries) {
6701
- const full = path10.join(dir, entry.name);
7750
+ const full = path11.join(dir, entry.name);
6702
7751
  if (entry.isDirectory()) {
6703
7752
  out.push(...listJsons(full));
6704
7753
  } else if (entry.isFile() && entry.name === "coverage-final.json") {
@@ -6709,11 +7758,11 @@ var emitMergedCoverage = async (ui, opts) => {
6709
7758
  }
6710
7759
  return out;
6711
7760
  };
6712
- const coverageRoot = path10.join("coverage", "jest");
7761
+ const coverageRoot = path11.join("coverage", "jest");
6713
7762
  const jsonCandidates = [
6714
- path10.join(coverageRoot, "coverage-final.json"),
7763
+ path11.join(coverageRoot, "coverage-final.json"),
6715
7764
  ...listJsons(coverageRoot)
6716
- ].map((candidatePath) => path10.resolve(candidatePath)).filter((absolutePath, index, arr) => {
7765
+ ].map((candidatePath) => path11.resolve(candidatePath)).filter((absolutePath, index, arr) => {
6717
7766
  const isFirst = arr.indexOf(absolutePath) === index;
6718
7767
  const exists = fsSync3.existsSync(absolutePath);
6719
7768
  return isFirst && exists;
@@ -6775,7 +7824,7 @@ var emitMergedCoverage = async (ui, opts) => {
6775
7824
  executedTests: opts.executedTests ?? []
6776
7825
  });
6777
7826
  const context = LibReport.createContext({
6778
- dir: path10.resolve("coverage", "merged"),
7827
+ dir: path11.resolve("coverage", "merged"),
6779
7828
  coverageMap: filteredMap,
6780
7829
  defaultSummarizer: "nested"
6781
7830
  });
@@ -6843,8 +7892,8 @@ var emitMergedCoverage = async (ui, opts) => {
6843
7892
  for (const reporter of reporters) {
6844
7893
  reporter.execute(context);
6845
7894
  }
6846
- const textPath = path10.resolve("coverage", "merged", "coverage.txt");
6847
- const summaryPath = path10.resolve("coverage", "merged", "coverage-summary.txt");
7895
+ const textPath = path11.resolve("coverage", "merged", "coverage.txt");
7896
+ const summaryPath = path11.resolve("coverage", "merged", "coverage-summary.txt");
6848
7897
  const filesToPrint = [];
6849
7898
  if (fsSync3.existsSync(textPath)) {
6850
7899
  filesToPrint.push(textPath);
@@ -6987,13 +8036,13 @@ var program = async () => {
6987
8036
  const rels2 = Array.from(
6988
8037
  /* @__PURE__ */ new Set([...branchDiff, ...stagedNow, ...unstagedNow, ...untrackedNow])
6989
8038
  );
6990
- return rels2.map((rel) => path10.resolve(cwd, rel).replace(/\\/g, "/")).filter((abs) => !abs.includes("/node_modules/") && !abs.includes("/coverage/"));
8039
+ return rels2.map((rel) => path11.resolve(cwd, rel).replace(/\\/g, "/")).filter((abs) => !abs.includes("/node_modules/") && !abs.includes("/coverage/"));
6991
8040
  }
6992
8041
  const staged = mode === "staged" || mode === "all" ? await collect("git", ["diff", "--name-only", "--diff-filter=ACMRTUXB", "--cached"]) : [];
6993
8042
  const unstagedTracked = mode === "unstaged" || mode === "all" ? await collect("git", ["diff", "--name-only", "--diff-filter=ACMRTUXB"]) : [];
6994
8043
  const untracked = mode === "unstaged" || mode === "all" ? await collect("git", ["ls-files", "--others", "--exclude-standard"]) : [];
6995
8044
  const rels = Array.from(/* @__PURE__ */ new Set([...staged, ...unstagedTracked, ...untracked]));
6996
- return rels.map((rel) => path10.resolve(cwd, rel).replace(/\\/g, "/")).filter((abs) => !abs.includes("/node_modules/") && !abs.includes("/coverage/"));
8045
+ return rels.map((rel) => path11.resolve(cwd, rel).replace(/\\/g, "/")).filter((abs) => !abs.includes("/node_modules/") && !abs.includes("/coverage/"));
6997
8046
  };
6998
8047
  const repoRootForChanged = workspaceRoot ?? await findRepoRoot();
6999
8048
  const changedSelectionAbs = changed ? await getChangedFiles(changed, repoRootForChanged) : [];
@@ -7018,18 +8067,18 @@ var program = async () => {
7018
8067
  if (!token) {
7019
8068
  continue;
7020
8069
  }
7021
- const isAbs = path10.isAbsolute(token);
8070
+ const isAbs = path11.isAbsolute(token);
7022
8071
  const looksLikeRelPath = /[\\/]/.test(token);
7023
8072
  let candidateFromRoot;
7024
8073
  if (token.startsWith("/")) {
7025
- candidateFromRoot = path10.join(repoRoot, token.slice(1));
8074
+ candidateFromRoot = path11.join(repoRoot, token.slice(1));
7026
8075
  } else if (looksLikeRelPath) {
7027
- candidateFromRoot = path10.join(repoRoot, token);
8076
+ candidateFromRoot = path11.join(repoRoot, token);
7028
8077
  } else {
7029
8078
  candidateFromRoot = void 0;
7030
8079
  }
7031
8080
  const tryPushIfProd = (absPath) => {
7032
- const norm = path10.resolve(absPath).replace(/\\/g, "/");
8081
+ const norm = path11.resolve(absPath).replace(/\\/g, "/");
7033
8082
  const isTest = /(^|\/)tests?\//i.test(norm) || /\.(test|spec)\.[tj]sx?$/i.test(norm);
7034
8083
  if (!isTest && fsSync3.existsSync(norm)) {
7035
8084
  results.add(norm);
@@ -7051,7 +8100,7 @@ var program = async () => {
7051
8100
  }),
7052
8101
  timeoutMs: 4e3
7053
8102
  });
7054
- const matches = out.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map((rel) => path10.resolve(repoRoot, rel).replace(/\\/g, "/")).filter(
8103
+ const matches = out.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map((rel) => path11.resolve(repoRoot, rel).replace(/\\/g, "/")).filter(
7055
8104
  (abs) => !abs.includes("/node_modules/") && !abs.includes("/coverage/") && !/(^|\/)tests?\//i.test(abs) && !/\.(test|spec)\.[tj]sx?$/i.test(abs)
7056
8105
  );
7057
8106
  matches.forEach((abs) => results.add(abs));
@@ -7072,8 +8121,8 @@ var program = async () => {
7072
8121
  const jestDiscoveryArgs = selectionIncludesProdPaths ? stripPathTokens(jest) : jest;
7073
8122
  const projectConfigs = [];
7074
8123
  try {
7075
- const baseCfg = path10.resolve("jest.config.js");
7076
- const tsCfg = path10.resolve("jest.ts.config.js");
8124
+ const baseCfg = path11.resolve("jest.config.js");
8125
+ const tsCfg = path11.resolve("jest.ts.config.js");
7077
8126
  if (fsSync3.existsSync(baseCfg)) {
7078
8127
  projectConfigs.push(baseCfg);
7079
8128
  }
@@ -7090,7 +8139,7 @@ var program = async () => {
7090
8139
  );
7091
8140
  const prodSelections2 = expandedProdSelections;
7092
8141
  for (const cfg of projectConfigs) {
7093
- const cfgCwd = path10.dirname(cfg);
8142
+ const cfgCwd = path11.dirname(cfg);
7094
8143
  const allTests = await discoverJestResilient([...jestDiscoveryArgs, "--config", cfg], {
7095
8144
  cwd: cfgCwd
7096
8145
  });
@@ -7103,7 +8152,7 @@ var program = async () => {
7103
8152
  });
7104
8153
  } catch (err) {
7105
8154
  if (isDebug()) {
7106
- console.warn(`direct selection failed for project ${path10.basename(cfg)}: ${String(err)}`);
8155
+ console.warn(`direct selection failed for project ${path11.basename(cfg)}: ${String(err)}`);
7107
8156
  }
7108
8157
  }
7109
8158
  perProjectFiles.set(cfg, directPerProject);
@@ -7115,7 +8164,7 @@ var program = async () => {
7115
8164
  )} | related=${selectionIncludesProdPaths} | cwd=${repoRootForDiscovery}`
7116
8165
  );
7117
8166
  for (const cfg of projectConfigs) {
7118
- const cfgCwd = path10.dirname(cfg);
8167
+ const cfgCwd = path11.dirname(cfg);
7119
8168
  const files = await discoverJestResilient([...jestDiscoveryArgs, "--config", cfg], {
7120
8169
  cwd: cfgCwd
7121
8170
  });
@@ -7130,13 +8179,13 @@ var program = async () => {
7130
8179
  );
7131
8180
  const candidates = selectionHasPaths && selectionLooksLikeTest ? selectionTestPaths : files;
7132
8181
  const absFiles = candidates.map(
7133
- (candidatePath) => path10.isAbsolute(candidatePath) ? candidatePath : path10.join(repoRootForDiscovery, candidatePath)
8182
+ (candidatePath) => path11.isAbsolute(candidatePath) ? candidatePath : path11.join(repoRootForDiscovery, candidatePath)
7134
8183
  ).map((absolutePath) => absolutePath.replace(/\\/g, "/"));
7135
8184
  const onlyOwned = await filterCandidatesForProject(
7136
8185
  cfg,
7137
8186
  jestDiscoveryArgs,
7138
8187
  absFiles,
7139
- path10.dirname(cfg)
8188
+ path11.dirname(cfg)
7140
8189
  );
7141
8190
  perProjectFiltered.set(cfg, onlyOwned);
7142
8191
  }
@@ -7148,7 +8197,7 @@ var program = async () => {
7148
8197
  if (selectionHasPaths && prodSelections.length > 0) {
7149
8198
  console.info(`rg related \u2192 prodSelections=${prodSelections.length} (starting)`);
7150
8199
  const repoRootForRefinement = workspaceRoot ?? await findRepoRoot();
7151
- const selectionKey = prodSelections.map((absPath) => path10.relative(repoRootForRefinement, absPath).replace(/\\/g, "/")).sort((firstPath, secondPath) => firstPath.localeCompare(secondPath)).join("|");
8200
+ const selectionKey = prodSelections.map((absPath) => path11.relative(repoRootForRefinement, absPath).replace(/\\/g, "/")).sort((firstPath, secondPath) => firstPath.localeCompare(secondPath)).join("|");
7152
8201
  const { cachedRelated: cachedRelated2, findRelatedTestsFast: findRelatedTestsFast2, DEFAULT_TEST_GLOBS: DEFAULT_TEST_GLOBS2 } = await Promise.resolve().then(() => (init_fast_related(), fast_related_exports));
7153
8202
  const { DEFAULT_EXCLUDE: DEFAULT_EXCLUDE2 } = await Promise.resolve().then(() => (init_args(), args_exports));
7154
8203
  const rgMatches = await cachedRelated2({
@@ -7178,7 +8227,7 @@ var program = async () => {
7178
8227
  cfg,
7179
8228
  jestDiscoveryArgs,
7180
8229
  rgCandidates,
7181
- path10.dirname(cfg)
8230
+ path11.dirname(cfg)
7182
8231
  );
7183
8232
  perProjectFromRg.set(cfg, owned);
7184
8233
  }
@@ -7193,9 +8242,9 @@ var program = async () => {
7193
8242
  } else {
7194
8243
  const repoRootForScan = repoRootForDiscovery;
7195
8244
  const toSeeds = (abs) => {
7196
- const rel = path10.relative(repoRootForScan, abs).replace(/\\/g, "/");
8245
+ const rel = path11.relative(repoRootForScan, abs).replace(/\\/g, "/");
7197
8246
  const withoutExt = rel.replace(/\.(m?[tj]sx?)$/i, "");
7198
- const base = path10.basename(withoutExt);
8247
+ const base = path11.basename(withoutExt);
7199
8248
  const segs = withoutExt.split("/");
7200
8249
  const tail2 = segs.slice(-2).join("/");
7201
8250
  return Array.from(new Set([withoutExt, base, tail2].filter(Boolean)));
@@ -7210,8 +8259,8 @@ var program = async () => {
7210
8259
  }
7211
8260
  };
7212
8261
  const resolveLocalImport = (fromFile, spec) => {
7213
- const baseDir = path10.dirname(fromFile);
7214
- const cand = path10.resolve(baseDir, spec);
8262
+ const baseDir = path11.dirname(fromFile);
8263
+ const cand = path11.resolve(baseDir, spec);
7215
8264
  const exts = ["", ".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
7216
8265
  for (const ext of exts) {
7217
8266
  const full = ext ? `${cand}${ext}` : cand;
@@ -7220,7 +8269,7 @@ var program = async () => {
7220
8269
  }
7221
8270
  }
7222
8271
  for (const ext of exts) {
7223
- const full = path10.join(cand, `index${ext}`);
8272
+ const full = path11.join(cand, `index${ext}`);
7224
8273
  if (fsSync3.existsSync(full)) {
7225
8274
  return full;
7226
8275
  }
@@ -7274,7 +8323,7 @@ var program = async () => {
7274
8323
  cfg,
7275
8324
  jestDiscoveryArgs,
7276
8325
  keptCandidates,
7277
- path10.dirname(cfg)
8326
+ path11.dirname(cfg)
7278
8327
  );
7279
8328
  perProjectFromScan.set(cfg, owned);
7280
8329
  }
@@ -7304,7 +8353,7 @@ var program = async () => {
7304
8353
  try {
7305
8354
  const allAcross = [];
7306
8355
  for (const cfg of projectConfigs) {
7307
- const cfgCwd = path10.dirname(cfg);
8356
+ const cfgCwd = path11.dirname(cfg);
7308
8357
  const listed = await discoverJestResilient([...jestDiscoveryArgs, "--config", cfg], {
7309
8358
  cwd: cfgCwd
7310
8359
  });
@@ -7318,23 +8367,23 @@ var program = async () => {
7318
8367
  }
7319
8368
  }
7320
8369
  const seeds = prodSelections.map(
7321
- (abs) => path10.relative(repoRoot, abs).replace(/\\/g, "/").replace(/\.(m?[tj]sx?)$/i, "")
8370
+ (abs) => path11.relative(repoRoot, abs).replace(/\\/g, "/").replace(/\.(m?[tj]sx?)$/i, "")
7322
8371
  ).flatMap((rel) => {
7323
- const base = path10.basename(rel);
8372
+ const base = path11.basename(rel);
7324
8373
  const segments = rel.split("/");
7325
8374
  return Array.from(new Set([rel, base, segments.slice(-2).join("/")].filter(Boolean)));
7326
8375
  });
7327
8376
  const includesSeed = (text) => seeds.some((seed) => text.includes(seed));
7328
8377
  const tryReadFile = async (absPath) => {
7329
8378
  try {
7330
- return await fs5.readFile(absPath, "utf8");
8379
+ return await fs7.readFile(absPath, "utf8");
7331
8380
  } catch {
7332
8381
  return "";
7333
8382
  }
7334
8383
  };
7335
8384
  const resolveLocalImport = (fromFile, spec) => {
7336
- const baseDir = path10.dirname(fromFile);
7337
- const candidate = path10.resolve(baseDir, spec);
8385
+ const baseDir = path11.dirname(fromFile);
8386
+ const candidate = path11.resolve(baseDir, spec);
7338
8387
  const extensions = ["", ".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts"];
7339
8388
  for (const ext of extensions) {
7340
8389
  const fullPath = ext ? `${candidate}${ext}` : candidate;
@@ -7343,7 +8392,7 @@ var program = async () => {
7343
8392
  }
7344
8393
  }
7345
8394
  for (const ext of extensions) {
7346
- const fullPath = path10.join(candidate, `index${ext}`);
8395
+ const fullPath = path11.join(candidate, `index${ext}`);
7347
8396
  if (fsSync3.existsSync(fullPath)) {
7348
8397
  return fullPath;
7349
8398
  }
@@ -7500,10 +8549,10 @@ var program = async () => {
7500
8549
  };
7501
8550
  const prodSeedsForRun = (() => {
7502
8551
  const changedAbs = (changedSelectionAbs ?? []).map(
7503
- (absPath) => path10.resolve(absPath).replace(/\\/g, "/")
8552
+ (absPath) => path11.resolve(absPath).replace(/\\/g, "/")
7504
8553
  );
7505
8554
  const selAbs = selectionPathsAugmented.map(
7506
- (pathToken) => path10.resolve(pathToken).replace(/\\/g, "/")
8555
+ (pathToken) => path11.resolve(pathToken).replace(/\\/g, "/")
7507
8556
  );
7508
8557
  return (changedAbs.length ? changedAbs : selAbs).filter(
7509
8558
  (abs) => /[\\/]/.test(abs) && !/(^|\/)tests?\//i.test(abs) && !/\.(test|spec)\.[tj]sx?$/i.test(abs)
@@ -7518,29 +8567,50 @@ var program = async () => {
7518
8567
  const cfg = projectsToRun[projIndex];
7519
8568
  const files = perProjectFiltered.get(cfg) ?? [];
7520
8569
  if (files.length === 0) {
7521
- console.info(`Project ${path10.basename(cfg)}: 0 matching tests after filter; skipping.`);
8570
+ console.info(`Project ${path11.basename(cfg)}: 0 matching tests after filter; skipping.`);
7522
8571
  continue;
7523
8572
  }
7524
8573
  files.forEach(
7525
- (absTestPath) => executedTestFilesSet.add(path10.resolve(absTestPath).replace(/\\/g, "/"))
8574
+ (absTestPath) => executedTestFilesSet.add(path11.resolve(absTestPath).replace(/\\/g, "/"))
7526
8575
  );
7527
- const outJson = path10.join(
8576
+ const outJson = path11.join(
7528
8577
  os2.tmpdir(),
7529
8578
  `jest-bridge-${Date.now()}-${Math.random().toString(36).slice(2)}.json`
7530
8579
  );
7531
- const reporterPath = path10.resolve("scripts/jest-vitest-bridge.cjs");
8580
+ const reporterPath = path11.resolve("scripts/jest-vitest-bridge.cjs");
7532
8581
  try {
7533
- if (!fsSync3.existsSync(reporterPath)) {
7534
- fsSync3.mkdirSync(path10.dirname(reporterPath), { recursive: true });
8582
+ const needsWrite = (() => {
8583
+ try {
8584
+ const existing = fsSync3.readFileSync(reporterPath, "utf8");
8585
+ return existing !== JEST_BRIDGE_REPORTER_SOURCE;
8586
+ } catch {
8587
+ return true;
8588
+ }
8589
+ })();
8590
+ if (needsWrite) {
8591
+ fsSync3.mkdirSync(path11.dirname(reporterPath), { recursive: true });
7535
8592
  fsSync3.writeFileSync(reporterPath, JEST_BRIDGE_REPORTER_SOURCE, "utf8");
7536
8593
  }
8594
+ const envPath = path11.resolve("scripts/jest-bridge-env.cjs");
8595
+ try {
8596
+ const existingEnv = fsSync3.readFileSync(envPath, "utf8");
8597
+ if (existingEnv !== JEST_BRIDGE_ENV_SOURCE) {
8598
+ fsSync3.writeFileSync(envPath, JEST_BRIDGE_ENV_SOURCE, "utf8");
8599
+ }
8600
+ } catch {
8601
+ try {
8602
+ fsSync3.mkdirSync(path11.dirname(envPath), { recursive: true });
8603
+ } catch {
8604
+ }
8605
+ fsSync3.writeFileSync(envPath, JEST_BRIDGE_ENV_SOURCE, "utf8");
8606
+ }
7537
8607
  } catch (ensureReporterError) {
7538
8608
  console.warn(`Unable to ensure jest bridge reporter: ${String(ensureReporterError)}`);
7539
8609
  }
7540
- const selectedFilesForCoverage = selectionPathsAugmented.filter((pathToken) => /[\\/]/.test(pathToken)).filter((pathToken) => !looksLikeTestPath(pathToken)).map((pathToken) => path10.relative(repoRootForDiscovery, pathToken).replace(/\\\\/g, "/")).filter((rel) => rel && !/^\.+\//.test(rel)).map((rel) => rel.startsWith("./") ? rel : `./${rel}`);
8610
+ const selectedFilesForCoverage = selectionPathsAugmented.filter((pathToken) => /[\\/]/.test(pathToken)).filter((pathToken) => !looksLikeTestPath(pathToken)).map((pathToken) => path11.relative(repoRootForDiscovery, pathToken).replace(/\\\\/g, "/")).filter((rel) => rel && !/^\.+\//.test(rel)).map((rel) => rel.startsWith("./") ? rel : `./${rel}`);
7541
8611
  const coverageFromArgs = [];
7542
- for (const relPath of selectedFilesForCoverage) {
7543
- coverageFromArgs.push("--collectCoverageFrom", relPath);
8612
+ for (const relPath2 of selectedFilesForCoverage) {
8613
+ coverageFromArgs.push("--collectCoverageFrom", relPath2);
7544
8614
  }
7545
8615
  const { code, output } = await runWithCapture(
7546
8616
  babelNodeBin,
@@ -7550,17 +8620,16 @@ var program = async () => {
7550
8620
  jestBin,
7551
8621
  "--config",
7552
8622
  cfg,
8623
+ "--testLocationInResults",
7553
8624
  "--runTestsByPath",
7554
8625
  `--reporters=${reporterPath}`,
7555
- "--silent",
7556
8626
  "--colors",
7557
- "--json",
7558
- "--outputFile",
7559
- outJson,
8627
+ "--env",
8628
+ path11.resolve("scripts/jest-bridge-env.cjs"),
7560
8629
  ...sanitizedJestRunArgs,
7561
8630
  ...collectCoverage ? [
7562
8631
  "--coverageDirectory",
7563
- path10.join("coverage", "jest", path10.basename(cfg).replace(/[^a-zA-Z0-9_.-]+/g, "_"))
8632
+ path11.join("coverage", "jest", path11.basename(cfg).replace(/[^a-zA-Z0-9_.-]+/g, "_"))
7564
8633
  ] : [],
7565
8634
  ...coverageFromArgs,
7566
8635
  "--passWithNoTests",
@@ -7593,17 +8662,23 @@ var program = async () => {
7593
8662
  ...bridge,
7594
8663
  testResults: sortTestResultsWithRank(fileRank, bridge.testResults).reverse()
7595
8664
  };
7596
- pretty = renderVitestFromJestJSON(reordered, {
7597
- cwd: repoRootForDiscovery,
7598
- ...editorCmd !== void 0 ? { editorCmd } : {},
7599
- onlyFailures
7600
- });
8665
+ pretty = renderVitestFromJestJSON(
8666
+ reordered,
8667
+ makeCtx(
8668
+ { cwd: repoRootForDiscovery, ...editorCmd !== void 0 ? { editorCmd } : {} },
8669
+ /\bFAIL\b/.test(stripAnsiSimple(output))
8670
+ ),
8671
+ { onlyFailures }
8672
+ );
7601
8673
  } catch {
7602
- pretty = renderVitestFromJestJSON(bridge, {
7603
- cwd: repoRootForDiscovery,
7604
- ...editorCmd !== void 0 ? { editorCmd } : {},
7605
- onlyFailures
7606
- });
8674
+ pretty = renderVitestFromJestJSON(
8675
+ bridge,
8676
+ makeCtx(
8677
+ { cwd: repoRootForDiscovery, ...editorCmd !== void 0 ? { editorCmd } : {} },
8678
+ /\bFAIL\b/.test(stripAnsiSimple(output))
8679
+ ),
8680
+ { onlyFailures }
8681
+ );
7607
8682
  }
7608
8683
  if (debug) {
7609
8684
  const preview = pretty.split("\n").slice(0, 3).join("\n");
@@ -7617,18 +8692,31 @@ ${preview}${pretty.includes("\n") ? "\n\u2026" : ""}`);
7617
8692
  console.info(String(jsonErr));
7618
8693
  console.info(`fallback: raw output lines=${output.split(/\r?\n/).length}`);
7619
8694
  }
7620
- const renderOpts = {
8695
+ pretty = formatJestOutputVitest(output, {
7621
8696
  cwd: repoRootForDiscovery,
7622
8697
  ...editorCmd !== void 0 ? { editorCmd } : {},
7623
8698
  onlyFailures
7624
- };
7625
- pretty = formatJestOutputVitest(output, renderOpts);
8699
+ });
7626
8700
  if (debug) {
7627
8701
  const preview = pretty.split("\n").slice(0, 3).join("\n");
7628
8702
  console.info(`pretty preview (text):
7629
8703
  ${preview}${pretty.includes("\n") ? "\n\u2026" : ""}`);
7630
8704
  }
7631
8705
  }
8706
+ try {
8707
+ const looksSparse = /\n\s*Error:\s*\n/.test(pretty) && !/(Message:|Thrown:|Events:|Console errors:)/.test(pretty);
8708
+ if (looksSparse) {
8709
+ const rawAlso = formatJestOutputVitest(output, {
8710
+ cwd: repoRootForDiscovery,
8711
+ ...editorCmd !== void 0 ? { editorCmd } : {},
8712
+ onlyFailures
8713
+ });
8714
+ const merged = `${stripFooter(pretty)}
8715
+ ${stripFooter(rawAlso)}`.trimEnd();
8716
+ pretty = merged;
8717
+ }
8718
+ } catch {
8719
+ }
7632
8720
  pretty = stripFooter(pretty);
7633
8721
  if (pretty.trim().length > 0) {
7634
8722
  process.stdout.write(pretty.endsWith("\n") ? pretty : `${pretty}
@@ -7667,10 +8755,10 @@ ${preview}${pretty.includes("\n") ? "\n\u2026" : ""}`);
7667
8755
  try {
7668
8756
  const prodSeeds = (() => {
7669
8757
  const changedAbs = (changedSelectionAbs ?? []).map(
7670
- (absPath) => path10.resolve(absPath).replace(/\\/g, "/")
8758
+ (absPath) => path11.resolve(absPath).replace(/\\/g, "/")
7671
8759
  );
7672
8760
  const selAbs = selectionPathsAugmented.map(
7673
- (pathToken) => path10.resolve(pathToken).replace(/\\/g, "/")
8761
+ (pathToken) => path11.resolve(pathToken).replace(/\\/g, "/")
7674
8762
  );
7675
8763
  return (changedAbs.length ? changedAbs : selAbs).filter(
7676
8764
  (abs) => /[\\/]/.test(abs) && !/(^|\/)tests?\//i.test(abs) && !/\.(test|spec)\.[tj]sx?$/i.test(abs)
@@ -7684,11 +8772,18 @@ ${preview}${pretty.includes("\n") ? "\n\u2026" : ""}`);
7684
8772
  unified.testResults = ordered;
7685
8773
  } catch {
7686
8774
  }
7687
- const text = renderVitestFromJestJSON(unified, {
7688
- cwd: repoRootForDiscovery,
7689
- ...editorCmd !== void 0 ? { editorCmd } : {},
7690
- onlyFailures
7691
- });
8775
+ const showStacks = Boolean(unified.aggregated?.numFailedTests > 0);
8776
+ let text = renderVitestFromJestJSON(
8777
+ unified,
8778
+ makeCtx(
8779
+ { cwd: repoRootForDiscovery, ...editorCmd !== void 0 ? { editorCmd } : {} },
8780
+ showStacks
8781
+ ),
8782
+ { onlyFailures }
8783
+ );
8784
+ if (onlyFailures) {
8785
+ text = text.split(/\r?\n/).filter((line) => !/^\s*PASS\b/.test(stripAnsiSimple(line))).join("\n");
8786
+ }
7692
8787
  if (text.trim().length > 0) {
7693
8788
  process.stdout.write(text.endsWith("\n") ? text : `${text}
7694
8789
  `);
@@ -7733,11 +8828,13 @@ export {
7733
8828
  barCell,
7734
8829
  buildCodeFrameSection,
7735
8830
  buildConsoleSection,
8831
+ buildFallbackMessageBlock,
7736
8832
  buildFileBadgeLine,
7737
8833
  buildMessageSection,
7738
8834
  buildPerFileOverview,
7739
8835
  buildPrettyDiffSection,
7740
8836
  buildStackSection,
8837
+ buildThrownSection,
7741
8838
  cell,
7742
8839
  coerceJestJsonToBridge,
7743
8840
  collapseStacks,
@@ -7752,32 +8849,30 @@ export {
7752
8849
  discoverJestResilient,
7753
8850
  discoverTargets,
7754
8851
  drawFailLine,
7755
- drawFailRule,
7756
8852
  drawRule,
7757
8853
  emitMergedCoverage,
7758
- extractAssertionMessage,
7759
- extractExpectedReceived,
7760
- extractFromUnifiedDiff,
7761
8854
  filterCandidatesForProject,
7762
8855
  filterCoverageMap,
7763
8856
  findCodeFrameStart,
7764
8857
  findRepoRoot,
7765
8858
  firstTestLocation,
7766
8859
  formatJestOutputVitest,
7767
- indentBlock,
7768
8860
  isFilesObject,
7769
8861
  isStackLine,
8862
+ isTransportError,
7770
8863
  isTruthy,
7771
- labelForMessage,
7772
8864
  linesFromDetails,
7773
8865
  linkifyPadded,
8866
+ makeCtx,
7774
8867
  mergeLcov,
7775
8868
  missedBranches,
7776
8869
  missedFunctions,
8870
+ mkPrettyFns,
7777
8871
  osc8,
7778
8872
  parseActionsFromTokens,
8873
+ parseMethodPathFromTitle,
8874
+ pickRelevantHttp,
7779
8875
  preferredEditorHref,
7780
- prettifyPrettyFormatBlock,
7781
8876
  printCompactCoverage,
7782
8877
  printDetailedCoverage,
7783
8878
  printPerFileCompositeTables,
@@ -7785,19 +8880,21 @@ export {
7785
8880
  readCoverageJson,
7786
8881
  registerSignalHandlersOnce,
7787
8882
  relativizeForMatch,
8883
+ renderCodeFrame,
7788
8884
  renderPerFileCompositeTable,
7789
8885
  renderRunLine,
7790
- renderSourceCodeFrame,
7791
8886
  renderTable,
7792
8887
  renderVitestFromJestJSON,
7793
8888
  resolveImportWithRoot,
8889
+ routeSimilarityScore,
7794
8890
  rule,
7795
8891
  runJestBootstrap,
7796
- stringifyPrettierish,
8892
+ scoreHttpForAssertion,
7797
8893
  stripAnsiSimple,
7798
8894
  supportsUnicode,
7799
8895
  tintPct,
7800
8896
  toPosix,
8897
+ tryBridgeFallback,
7801
8898
  tryResolveFile
7802
8899
  };
7803
8900
  //# sourceMappingURL=index.js.map