headlamp 0.1.6 → 0.1.8
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/README.md +30 -2
- package/dist/cli.cjs +391 -257
- package/dist/cli.cjs.map +4 -4
- package/dist/index.js +395 -258
- package/dist/index.js.map +4 -4
- package/package.json +10 -4
- package/scripts/build.mjs +117 -0
- package/scripts/postinstall.mjs +13 -0
- package/scripts/print-publish-log.mjs +29 -0
package/dist/index.js
CHANGED
|
@@ -67,7 +67,8 @@ var init_args = __esm({
|
|
|
67
67
|
coverageMode: (value) => ({ type: "coverageMode", value }),
|
|
68
68
|
coverageMaxFiles: (value) => ({ type: "coverageMaxFiles", value }),
|
|
69
69
|
coverageMaxHotspots: (value) => ({ type: "coverageMaxHotspots", value }),
|
|
70
|
-
coveragePageFit: (value) => ({ type: "coveragePageFit", value })
|
|
70
|
+
coveragePageFit: (value) => ({ type: "coveragePageFit", value }),
|
|
71
|
+
changed: (value) => ({ type: "changed", value })
|
|
71
72
|
};
|
|
72
73
|
Some = (value) => ({ _tag: "some", value });
|
|
73
74
|
None = { _tag: "none" };
|
|
@@ -264,6 +265,18 @@ var init_args = __esm({
|
|
|
264
265
|
"--coverage.root=",
|
|
265
266
|
(value) => step([ActionBuilders.coverageRoot((value.split("=")[1] ?? "").trim())])
|
|
266
267
|
),
|
|
268
|
+
// --changed flag: selects changed files via git (all|staged|unstaged)
|
|
269
|
+
rule.eq("--changed", () => step([ActionBuilders.changed("all")])),
|
|
270
|
+
rule.startsWith("--changed=", (value) => {
|
|
271
|
+
const raw = (value.split("=")[1] ?? "").trim().toLowerCase();
|
|
272
|
+
const mode = raw === "staged" ? "staged" : raw === "unstaged" ? "unstaged" : "all";
|
|
273
|
+
return step([ActionBuilders.changed(mode)]);
|
|
274
|
+
}),
|
|
275
|
+
rule.withLookahead("--changed", (_flag, lookahead) => {
|
|
276
|
+
const raw = String(lookahead).trim().toLowerCase();
|
|
277
|
+
const mode = raw === "staged" ? "staged" : raw === "unstaged" ? "unstaged" : "all";
|
|
278
|
+
return step([ActionBuilders.changed(mode)], true);
|
|
279
|
+
}),
|
|
267
280
|
rule.withLookahead(
|
|
268
281
|
"-t",
|
|
269
282
|
(flag, lookahead) => step(
|
|
@@ -366,6 +379,8 @@ var init_args = __esm({
|
|
|
366
379
|
return { vitest: [], jest: [], coverage: false, coverageMaxHotspots: action.value };
|
|
367
380
|
case "coveragePageFit":
|
|
368
381
|
return { vitest: [], jest: [], coverage: false, coveragePageFit: action.value };
|
|
382
|
+
case "changed":
|
|
383
|
+
return { vitest: [], jest: [], coverage: false, changed: action.value };
|
|
369
384
|
case "jestArg":
|
|
370
385
|
return { vitest: [], jest: [action.value], coverage: false };
|
|
371
386
|
case "vitestArg":
|
|
@@ -405,6 +420,7 @@ var init_args = __esm({
|
|
|
405
420
|
}
|
|
406
421
|
return {
|
|
407
422
|
...next,
|
|
423
|
+
...right.changed !== void 0 || left.changed !== void 0 ? { changed: right.changed ?? left.changed } : {},
|
|
408
424
|
...right.coverageAbortOnFailure !== void 0 || left.coverageAbortOnFailure !== void 0 ? { coverageAbortOnFailure: right.coverageAbortOnFailure ?? left.coverageAbortOnFailure } : {},
|
|
409
425
|
...right.coverageDetail !== void 0 || left.coverageDetail !== void 0 ? { coverageDetail: right.coverageDetail ?? left.coverageDetail } : {},
|
|
410
426
|
...right.coverageShowCode !== void 0 || left.coverageShowCode !== void 0 ? { coverageShowCode: right.coverageShowCode ?? left.coverageShowCode } : {},
|
|
@@ -490,7 +506,8 @@ var init_args = __esm({
|
|
|
490
506
|
...coverageMaxHotspotsLocal !== void 0 ? { coverageMaxHotspots: coverageMaxHotspotsLocal } : {},
|
|
491
507
|
coveragePageFit,
|
|
492
508
|
...contrib.editorCmd !== void 0 ? { editorCmd: contrib.editorCmd } : {},
|
|
493
|
-
...contrib.workspaceRoot !== void 0 ? { workspaceRoot: contrib.workspaceRoot } : {}
|
|
509
|
+
...contrib.workspaceRoot !== void 0 ? { workspaceRoot: contrib.workspaceRoot } : {},
|
|
510
|
+
...contrib.changed !== void 0 ? { changed: contrib.changed } : {}
|
|
494
511
|
};
|
|
495
512
|
return out;
|
|
496
513
|
};
|
|
@@ -557,7 +574,7 @@ var init_TimeoutError = __esm({
|
|
|
557
574
|
|
|
558
575
|
// node_modules/es-toolkit/dist/promise/delay.mjs
|
|
559
576
|
function delay(ms, { signal } = {}) {
|
|
560
|
-
return new Promise((
|
|
577
|
+
return new Promise((resolve9, reject) => {
|
|
561
578
|
const abortError = () => {
|
|
562
579
|
reject(new AbortError());
|
|
563
580
|
};
|
|
@@ -570,7 +587,7 @@ function delay(ms, { signal } = {}) {
|
|
|
570
587
|
}
|
|
571
588
|
const timeoutId = setTimeout(() => {
|
|
572
589
|
signal?.removeEventListener("abort", abortHandler);
|
|
573
|
-
|
|
590
|
+
resolve9();
|
|
574
591
|
}, ms);
|
|
575
592
|
signal?.addEventListener("abort", abortHandler, { once: true });
|
|
576
593
|
});
|
|
@@ -635,11 +652,11 @@ var init_exec = __esm({
|
|
|
635
652
|
child.stderr?.on("data", (chunk) => {
|
|
636
653
|
stderr += String(chunk);
|
|
637
654
|
});
|
|
638
|
-
const exec = new Promise((
|
|
655
|
+
const exec = new Promise((resolve9, reject) => {
|
|
639
656
|
child.on("error", reject);
|
|
640
657
|
child.on(
|
|
641
658
|
"close",
|
|
642
|
-
(code) => Number(code) === 0 ?
|
|
659
|
+
(code) => Number(code) === 0 ? resolve9(stdout) : reject(new Error(stderr || `exit ${code}`))
|
|
643
660
|
);
|
|
644
661
|
});
|
|
645
662
|
try {
|
|
@@ -659,7 +676,7 @@ var init_exec = __esm({
|
|
|
659
676
|
throw caughtError;
|
|
660
677
|
}
|
|
661
678
|
};
|
|
662
|
-
runExitCode = async (cmd, args, opts = {}) => new Promise((
|
|
679
|
+
runExitCode = async (cmd, args, opts = {}) => new Promise((resolve9, reject) => {
|
|
663
680
|
const child = spawn(cmd, [...args], {
|
|
664
681
|
cwd: opts.cwd,
|
|
665
682
|
env: opts.env,
|
|
@@ -668,9 +685,9 @@ var init_exec = __esm({
|
|
|
668
685
|
windowsHide: true
|
|
669
686
|
});
|
|
670
687
|
child.on("error", reject);
|
|
671
|
-
child.on("close", (code) =>
|
|
688
|
+
child.on("close", (code) => resolve9(Number(code)));
|
|
672
689
|
});
|
|
673
|
-
runWithCapture = async (cmd, args, opts) => new Promise((
|
|
690
|
+
runWithCapture = async (cmd, args, opts) => new Promise((resolve9, reject) => {
|
|
674
691
|
const child = spawn(cmd, [...args], {
|
|
675
692
|
cwd: opts.cwd,
|
|
676
693
|
env: opts.env,
|
|
@@ -686,7 +703,7 @@ var init_exec = __esm({
|
|
|
686
703
|
buf += String(chunk);
|
|
687
704
|
});
|
|
688
705
|
child.on("error", reject);
|
|
689
|
-
child.on("close", (code) =>
|
|
706
|
+
child.on("close", (code) => resolve9({ code: Number(code), output: buf }));
|
|
690
707
|
});
|
|
691
708
|
}
|
|
692
709
|
});
|
|
@@ -1097,8 +1114,8 @@ var require_utils = __commonJS({
|
|
|
1097
1114
|
}
|
|
1098
1115
|
return output;
|
|
1099
1116
|
};
|
|
1100
|
-
exports.basename = (
|
|
1101
|
-
const segs =
|
|
1117
|
+
exports.basename = (path11, { windows } = {}) => {
|
|
1118
|
+
const segs = path11.split(windows ? /[\\/]/ : "/");
|
|
1102
1119
|
const last = segs[segs.length - 1];
|
|
1103
1120
|
if (last === "") {
|
|
1104
1121
|
return segs[segs.length - 2];
|
|
@@ -4688,8 +4705,75 @@ var compositeBarPct = (summary, hotspots) => {
|
|
|
4688
4705
|
// src/lib/coverage-print.ts
|
|
4689
4706
|
init_env_utils();
|
|
4690
4707
|
init_exec();
|
|
4691
|
-
import * as
|
|
4708
|
+
import * as path8 from "node:path";
|
|
4692
4709
|
import * as fsSync2 from "node:fs";
|
|
4710
|
+
|
|
4711
|
+
// src/lib/relevance.ts
|
|
4712
|
+
init_args();
|
|
4713
|
+
init_fast_related();
|
|
4714
|
+
import * as path7 from "node:path";
|
|
4715
|
+
var normalizeAbs = (inputPath) => path7.resolve(inputPath).replace(/\\/g, "/");
|
|
4716
|
+
var compareBooleanDesc = (left, right) => {
|
|
4717
|
+
if (left === right) {
|
|
4718
|
+
return 0;
|
|
4719
|
+
}
|
|
4720
|
+
return right ? 1 : -1;
|
|
4721
|
+
};
|
|
4722
|
+
var compareNumberAsc = (left, right) => left - right;
|
|
4723
|
+
var compareStringAsc = (left, right) => left.localeCompare(right);
|
|
4724
|
+
var fileFailed = (file) => Boolean(
|
|
4725
|
+
(file.status ?? "") === "failed" || (file.testResults ?? []).some((assertion) => (assertion.status ?? "") === "failed")
|
|
4726
|
+
);
|
|
4727
|
+
var composeComparators = (...comparators) => (left, right) => {
|
|
4728
|
+
for (const cmp of comparators) {
|
|
4729
|
+
const result = cmp(left, right);
|
|
4730
|
+
if (result !== 0) {
|
|
4731
|
+
return result;
|
|
4732
|
+
}
|
|
4733
|
+
}
|
|
4734
|
+
return 0;
|
|
4735
|
+
};
|
|
4736
|
+
var comparatorForRank = (rankByPath) => {
|
|
4737
|
+
const rankOrInf = (absPath) => rankByPath.has(absPath) ? rankByPath.get(absPath) : Number.POSITIVE_INFINITY;
|
|
4738
|
+
return composeComparators(
|
|
4739
|
+
(left, right) => compareBooleanDesc(fileFailed(left), fileFailed(right)),
|
|
4740
|
+
(left, right) => compareNumberAsc(
|
|
4741
|
+
rankOrInf(normalizeAbs(left.testFilePath)),
|
|
4742
|
+
rankOrInf(normalizeAbs(right.testFilePath))
|
|
4743
|
+
),
|
|
4744
|
+
(left, right) => compareStringAsc(normalizeAbs(left.testFilePath), normalizeAbs(right.testFilePath))
|
|
4745
|
+
);
|
|
4746
|
+
};
|
|
4747
|
+
var computeDirectnessRank = async (opts) => {
|
|
4748
|
+
const selectionKey = opts.productionSeeds.map((abs) => path7.relative(opts.repoRoot, abs).replace(/\\/g, "/")).sort((left, right) => left.localeCompare(right)).join("|");
|
|
4749
|
+
const related = await cachedRelated({
|
|
4750
|
+
repoRoot: opts.repoRoot,
|
|
4751
|
+
selectionKey,
|
|
4752
|
+
compute: () => findRelatedTestsFast({
|
|
4753
|
+
repoRoot: opts.repoRoot,
|
|
4754
|
+
productionPaths: opts.productionSeeds,
|
|
4755
|
+
testGlobs: DEFAULT_TEST_GLOBS,
|
|
4756
|
+
excludeGlobs: opts.excludeGlobs ?? DEFAULT_EXCLUDE,
|
|
4757
|
+
timeoutMs: 1500
|
|
4758
|
+
})
|
|
4759
|
+
});
|
|
4760
|
+
const out = /* @__PURE__ */ new Map();
|
|
4761
|
+
related.forEach((abs, index) => {
|
|
4762
|
+
out.set(normalizeAbs(abs), index);
|
|
4763
|
+
});
|
|
4764
|
+
return out;
|
|
4765
|
+
};
|
|
4766
|
+
var sortTestResultsWithRank = (rankByPath, results) => results.slice().sort(comparatorForRank(rankByPath));
|
|
4767
|
+
var comparatorForPathRank = (rankByPath) => {
|
|
4768
|
+
const rankOrInf = (absPath) => rankByPath.has(absPath) ? rankByPath.get(absPath) : Number.POSITIVE_INFINITY;
|
|
4769
|
+
return composeComparators(
|
|
4770
|
+
(left, right) => compareNumberAsc(rankOrInf(normalizeAbs(left)), rankOrInf(normalizeAbs(right))),
|
|
4771
|
+
(left, right) => compareStringAsc(normalizeAbs(left), normalizeAbs(right))
|
|
4772
|
+
);
|
|
4773
|
+
};
|
|
4774
|
+
var sortPathsWithRank = (rankByPath, paths) => paths.slice().sort(comparatorForPathRank(rankByPath));
|
|
4775
|
+
|
|
4776
|
+
// src/lib/coverage-print.ts
|
|
4693
4777
|
var printDetailedCoverage = async (opts) => {
|
|
4694
4778
|
const files = opts.map.files().sort((fileA, fileB) => {
|
|
4695
4779
|
const summaryA = opts.map.fileCoverageFor(fileA).toSummary();
|
|
@@ -4699,7 +4783,7 @@ var printDetailedCoverage = async (opts) => {
|
|
|
4699
4783
|
for (const abs of files) {
|
|
4700
4784
|
const fc = opts.map.fileCoverageFor(abs);
|
|
4701
4785
|
const sum = fc.toSummary();
|
|
4702
|
-
const rel =
|
|
4786
|
+
const rel = path8.relative(opts.root, abs).replace(/\\/g, "/");
|
|
4703
4787
|
const blocks = computeUncoveredBlocks(fc);
|
|
4704
4788
|
const misses = missedBranches(fc);
|
|
4705
4789
|
const missFns = missedFunctions(fc);
|
|
@@ -4708,9 +4792,9 @@ var printDetailedCoverage = async (opts) => {
|
|
|
4708
4792
|
const branchesPctText = `${sum.branches.pct.toFixed(1)}%`;
|
|
4709
4793
|
const header = `${ansi.bold(rel)} lines ${tintPct(sum.lines.pct)(
|
|
4710
4794
|
linesPctText
|
|
4711
|
-
)} ${barCell(compositeBarPct(sum, blocks))("".padEnd(14))} funcs ${tintPct(
|
|
4712
|
-
|
|
4713
|
-
)
|
|
4795
|
+
)} ${barCell(compositeBarPct(sum, blocks))("".padEnd(14))} funcs ${tintPct(sum.functions.pct)(
|
|
4796
|
+
funcsPctText
|
|
4797
|
+
)} branches ${tintPct(sum.branches.pct)(branchesPctText)}`;
|
|
4714
4798
|
console.info(header);
|
|
4715
4799
|
const max = opts.limitPerFile === "all" ? Number.POSITIVE_INFINITY : opts.limitPerFile ?? 5;
|
|
4716
4800
|
const compareRangesByLengthDescThenStart = (firstRange, secondRange) => {
|
|
@@ -4737,10 +4821,8 @@ var printDetailedCoverage = async (opts) => {
|
|
|
4737
4821
|
abs,
|
|
4738
4822
|
block.start,
|
|
4739
4823
|
opts.editorCmd
|
|
4740
|
-
)}\x07${
|
|
4741
|
-
const label = ` ${ansi.yellow(`L${block.start}`)}\u2013${ansi.yellow(
|
|
4742
|
-
`L${block.end}`
|
|
4743
|
-
)} ${link}`;
|
|
4824
|
+
)}\x07${path8.basename(abs)}:${block.start}\x1B]8;;\x07`;
|
|
4825
|
+
const label = ` ${ansi.yellow(`L${block.start}`)}\u2013${ansi.yellow(`L${block.end}`)} ${link}`;
|
|
4744
4826
|
console.info(label);
|
|
4745
4827
|
if (opts.showCode && src.length) {
|
|
4746
4828
|
const lines = src.split(/\r?\n/);
|
|
@@ -4760,7 +4842,7 @@ var printDetailedCoverage = async (opts) => {
|
|
|
4760
4842
|
abs,
|
|
4761
4843
|
fn.line,
|
|
4762
4844
|
opts.editorCmd
|
|
4763
|
-
)}\x07${
|
|
4845
|
+
)}\x07${path8.basename(abs)}:${fn.line}\x1B]8;;\x07`;
|
|
4764
4846
|
console.info(` - ${fn.name} @ ${link}`);
|
|
4765
4847
|
}
|
|
4766
4848
|
}
|
|
@@ -4771,12 +4853,8 @@ var printDetailedCoverage = async (opts) => {
|
|
|
4771
4853
|
abs,
|
|
4772
4854
|
br.line,
|
|
4773
4855
|
opts.editorCmd
|
|
4774
|
-
)}\x07${
|
|
4775
|
-
console.info(
|
|
4776
|
-
` - branch#${br.id} @ ${link} missed paths: [${br.zeroPaths.join(
|
|
4777
|
-
", "
|
|
4778
|
-
)}]`
|
|
4779
|
-
);
|
|
4856
|
+
)}\x07${path8.basename(abs)}:${br.line}\x1B]8;;\x07`;
|
|
4857
|
+
console.info(` - branch#${br.id} @ ${link} missed paths: [${br.zeroPaths.join(", ")}]`);
|
|
4780
4858
|
}
|
|
4781
4859
|
}
|
|
4782
4860
|
console.info("");
|
|
@@ -4796,7 +4874,7 @@ var printCompactCoverage = async (opts) => {
|
|
|
4796
4874
|
for (const abs of files.slice(0, fileCap)) {
|
|
4797
4875
|
const fc = opts.map.fileCoverageFor(abs);
|
|
4798
4876
|
const sum = fc.toSummary();
|
|
4799
|
-
const rel =
|
|
4877
|
+
const rel = path8.relative(opts.root, abs).replace(/\\/g, "/");
|
|
4800
4878
|
const compareRangesByLengthDescThenStart = (firstRange, secondRange) => {
|
|
4801
4879
|
const secondLength = secondRange.end - secondRange.start;
|
|
4802
4880
|
const firstLength = firstRange.end - firstRange.start;
|
|
@@ -4810,9 +4888,9 @@ var printCompactCoverage = async (opts) => {
|
|
|
4810
4888
|
const branchesPctText = `${sum.branches.pct.toFixed(1)}%`;
|
|
4811
4889
|
const header = `${ansi.bold(rel)} lines ${tintPct(sum.lines.pct)(
|
|
4812
4890
|
linesPctText
|
|
4813
|
-
)} ${barCell(compositeBarPct(sum, blocks))("".padEnd(14))} funcs ${tintPct(
|
|
4814
|
-
|
|
4815
|
-
)
|
|
4891
|
+
)} ${barCell(compositeBarPct(sum, blocks))("".padEnd(14))} funcs ${tintPct(sum.functions.pct)(
|
|
4892
|
+
funcsPctText
|
|
4893
|
+
)} branches ${tintPct(sum.branches.pct)(branchesPctText)}`;
|
|
4816
4894
|
console.info(header);
|
|
4817
4895
|
const hotspots = blocks.slice(0, maxHotspotsDerived);
|
|
4818
4896
|
if (hotspots.length) {
|
|
@@ -4823,10 +4901,8 @@ var printCompactCoverage = async (opts) => {
|
|
|
4823
4901
|
abs,
|
|
4824
4902
|
hotspot.start,
|
|
4825
4903
|
opts.editorCmd
|
|
4826
|
-
)}\x07${
|
|
4827
|
-
console.info(
|
|
4828
|
-
` - L${hotspot.start}\u2013L${hotspot.end} (${len} lines) ${link}`
|
|
4829
|
-
);
|
|
4904
|
+
)}\x07${path8.basename(abs)}:${hotspot.start}\x1B]8;;\x07`;
|
|
4905
|
+
console.info(` - L${hotspot.start}\u2013L${hotspot.end} (${len} lines) ${link}`);
|
|
4830
4906
|
}
|
|
4831
4907
|
}
|
|
4832
4908
|
const functionsList = missFns.slice(0, maxFunctionsDerived);
|
|
@@ -4838,7 +4914,7 @@ var printCompactCoverage = async (opts) => {
|
|
|
4838
4914
|
abs,
|
|
4839
4915
|
fn.line,
|
|
4840
4916
|
opts.editorCmd
|
|
4841
|
-
)}\x07${
|
|
4917
|
+
)}\x07${path8.basename(abs)}:${fn.line}\x1B]8;;\x07`
|
|
4842
4918
|
);
|
|
4843
4919
|
}
|
|
4844
4920
|
}
|
|
@@ -4853,7 +4929,7 @@ var printCompactCoverage = async (opts) => {
|
|
|
4853
4929
|
abs,
|
|
4854
4930
|
br.line,
|
|
4855
4931
|
opts.editorCmd
|
|
4856
|
-
)}\x07${
|
|
4932
|
+
)}\x07${path8.basename(abs)}:${br.line}\x1B]8;;\x07`
|
|
4857
4933
|
);
|
|
4858
4934
|
}
|
|
4859
4935
|
}
|
|
@@ -4862,9 +4938,7 @@ var printCompactCoverage = async (opts) => {
|
|
|
4862
4938
|
const restBrs = Math.max(0, misses.length - branchesList.length);
|
|
4863
4939
|
if (restHs + restFns + restBrs > 0) {
|
|
4864
4940
|
console.info(
|
|
4865
|
-
ansi.dim(
|
|
4866
|
-
` \u2026 truncated: +${restHs} hotspots, +${restFns} funcs, +${restBrs} branches`
|
|
4867
|
-
)
|
|
4941
|
+
ansi.dim(` \u2026 truncated: +${restHs} hotspots, +${restFns} funcs, +${restBrs} branches`)
|
|
4868
4942
|
);
|
|
4869
4943
|
}
|
|
4870
4944
|
console.info("");
|
|
@@ -4901,7 +4975,7 @@ var shortenPathPreservingFilename = (relPath, maxWidth, opts) => {
|
|
|
4901
4975
|
return { stem: base.slice(0, -ending.length), ext: ending };
|
|
4902
4976
|
}
|
|
4903
4977
|
}
|
|
4904
|
-
const ext2 =
|
|
4978
|
+
const ext2 = path8.extname(base);
|
|
4905
4979
|
return { stem: base.slice(0, -ext2.length), ext: ext2 };
|
|
4906
4980
|
};
|
|
4907
4981
|
const sliceBalanced = (input, width) => {
|
|
@@ -4984,12 +5058,7 @@ var shortenPathPreservingFilename = (relPath, maxWidth, opts) => {
|
|
|
4984
5058
|
const tailParts = tailSrc.map((segment) => segment);
|
|
4985
5059
|
let hidAny = false;
|
|
4986
5060
|
const build = () => {
|
|
4987
|
-
const label2 = joinParts(
|
|
4988
|
-
headParts,
|
|
4989
|
-
tailParts,
|
|
4990
|
-
hideMiddle2 || hidAny,
|
|
4991
|
-
baseLabel
|
|
4992
|
-
);
|
|
5061
|
+
const label2 = joinParts(headParts, tailParts, hideMiddle2 || hidAny, baseLabel);
|
|
4993
5062
|
return { label: label2, width: visibleWidth(label2) };
|
|
4994
5063
|
};
|
|
4995
5064
|
let { label, width } = build();
|
|
@@ -5082,13 +5151,7 @@ var shortenPathPreservingFilename = (relPath, maxWidth, opts) => {
|
|
|
5082
5151
|
return { headRaw: headRaw2, tailRaw: tailRaw2, hideMiddle: hideMiddle2 };
|
|
5083
5152
|
};
|
|
5084
5153
|
let { headRaw, tailRaw, hideMiddle } = buildRaw(headCount, tailCount);
|
|
5085
|
-
let candidate = tryTrimDirsToFit(
|
|
5086
|
-
headRaw,
|
|
5087
|
-
tailRaw,
|
|
5088
|
-
hideMiddle,
|
|
5089
|
-
baseFull,
|
|
5090
|
-
maxWidth
|
|
5091
|
-
);
|
|
5154
|
+
let candidate = tryTrimDirsToFit(headRaw, tailRaw, hideMiddle, baseFull, maxWidth);
|
|
5092
5155
|
if (!candidate) {
|
|
5093
5156
|
return baseFull;
|
|
5094
5157
|
}
|
|
@@ -5097,13 +5160,7 @@ var shortenPathPreservingFilename = (relPath, maxWidth, opts) => {
|
|
|
5097
5160
|
if (headCount + tailCount < total) {
|
|
5098
5161
|
const tryTail = Math.min(tailCount + 1, total - headCount);
|
|
5099
5162
|
({ headRaw, tailRaw, hideMiddle } = buildRaw(headCount, tryTail));
|
|
5100
|
-
const candTail = tryTrimDirsToFit(
|
|
5101
|
-
headRaw,
|
|
5102
|
-
tailRaw,
|
|
5103
|
-
hideMiddle,
|
|
5104
|
-
baseFull,
|
|
5105
|
-
maxWidth
|
|
5106
|
-
);
|
|
5163
|
+
const candTail = tryTrimDirsToFit(headRaw, tailRaw, hideMiddle, baseFull, maxWidth);
|
|
5107
5164
|
if (candTail) {
|
|
5108
5165
|
tailCount = tryTail;
|
|
5109
5166
|
candidate = candTail;
|
|
@@ -5113,13 +5170,7 @@ var shortenPathPreservingFilename = (relPath, maxWidth, opts) => {
|
|
|
5113
5170
|
if (!advanced && headCount + tailCount < total) {
|
|
5114
5171
|
const tryHead = Math.min(headCount + 1, total - tailCount);
|
|
5115
5172
|
({ headRaw, tailRaw, hideMiddle } = buildRaw(tryHead, tailCount));
|
|
5116
|
-
const candHead = tryTrimDirsToFit(
|
|
5117
|
-
headRaw,
|
|
5118
|
-
tailRaw,
|
|
5119
|
-
hideMiddle,
|
|
5120
|
-
baseFull,
|
|
5121
|
-
maxWidth
|
|
5122
|
-
);
|
|
5173
|
+
const candHead = tryTrimDirsToFit(headRaw, tailRaw, hideMiddle, baseFull, maxWidth);
|
|
5123
5174
|
if (candHead) {
|
|
5124
5175
|
headCount = tryHead;
|
|
5125
5176
|
candidate = candHead;
|
|
@@ -5181,7 +5232,7 @@ var buildDistanceMapFromTests = async (executedTestsAbs, rootDir) => {
|
|
|
5181
5232
|
const queue = [];
|
|
5182
5233
|
const seen = /* @__PURE__ */ new Set();
|
|
5183
5234
|
for (const testAbs of executedTestsAbs) {
|
|
5184
|
-
const testPathNormalized =
|
|
5235
|
+
const testPathNormalized = path8.resolve(testAbs).replace(/\\/g, "/");
|
|
5185
5236
|
dist.set(testPathNormalized, 0);
|
|
5186
5237
|
queue.push([testPathNormalized, 0]);
|
|
5187
5238
|
}
|
|
@@ -5200,12 +5251,7 @@ var buildDistanceMapFromTests = async (executedTestsAbs, rootDir) => {
|
|
|
5200
5251
|
const specs = await extractImportSpecs2(currentFile, specsCache);
|
|
5201
5252
|
const nextDistance = currentDistance + 1;
|
|
5202
5253
|
for (const spec of specs) {
|
|
5203
|
-
const resolved = resolveImportWithRoot(
|
|
5204
|
-
currentFile,
|
|
5205
|
-
spec,
|
|
5206
|
-
rootDir,
|
|
5207
|
-
resolutionCache
|
|
5208
|
-
);
|
|
5254
|
+
const resolved = resolveImportWithRoot(currentFile, spec, rootDir, resolutionCache);
|
|
5209
5255
|
const usable = resolved && !resolved.includes("/node_modules/");
|
|
5210
5256
|
if (usable) {
|
|
5211
5257
|
const existing = dist.get(resolved);
|
|
@@ -5220,13 +5266,10 @@ var buildDistanceMapFromTests = async (executedTestsAbs, rootDir) => {
|
|
|
5220
5266
|
return dist;
|
|
5221
5267
|
};
|
|
5222
5268
|
var renderPerFileCompositeTable = async (opts) => {
|
|
5223
|
-
const rel =
|
|
5269
|
+
const rel = path8.relative(opts.root, opts.absPath).replace(/\\/g, "/");
|
|
5224
5270
|
const sum = opts.file.toSummary();
|
|
5225
5271
|
const rowsAvail = typeof process.stdout.rows === "number" && process.stdout.rows > 10 ? process.stdout.rows : 40;
|
|
5226
|
-
const tableBudget = Math.max(
|
|
5227
|
-
14,
|
|
5228
|
-
Math.min(opts.maxRows ?? rowsAvail - 1, rowsAvail + 8)
|
|
5229
|
-
);
|
|
5272
|
+
const tableBudget = Math.max(14, Math.min(opts.maxRows ?? rowsAvail - 1, rowsAvail + 8));
|
|
5230
5273
|
const rowBudget = Math.max(6, tableBudget - 6);
|
|
5231
5274
|
const blocks = computeUncoveredBlocks(opts.file).slice().sort((firstRange, secondRange) => {
|
|
5232
5275
|
const firstLength = firstRange.end - firstRange.start;
|
|
@@ -5270,9 +5313,7 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
5270
5313
|
rows.push([
|
|
5271
5314
|
cell(
|
|
5272
5315
|
rel,
|
|
5273
|
-
(padded) => ansi.dim(
|
|
5274
|
-
shortenPathPreservingFilename(rel, padded.length).padEnd(padded.length)
|
|
5275
|
-
)
|
|
5316
|
+
(padded) => ansi.dim(shortenPathPreservingFilename(rel, padded.length).padEnd(padded.length))
|
|
5276
5317
|
),
|
|
5277
5318
|
cell("Totals", ansi.dim),
|
|
5278
5319
|
cell("\u2014", ansi.dim),
|
|
@@ -5291,11 +5332,7 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
5291
5332
|
rows.push([
|
|
5292
5333
|
cell(
|
|
5293
5334
|
rel,
|
|
5294
|
-
(padded) => ansi.dim(
|
|
5295
|
-
shortenPathPreservingFilename(rel, padded.length).padEnd(
|
|
5296
|
-
padded.length
|
|
5297
|
-
)
|
|
5298
|
-
)
|
|
5335
|
+
(padded) => ansi.dim(shortenPathPreservingFilename(rel, padded.length).padEnd(padded.length))
|
|
5299
5336
|
),
|
|
5300
5337
|
cell("Hotspots", ansi.dim),
|
|
5301
5338
|
cell("", ansi.dim),
|
|
@@ -5309,14 +5346,8 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
5309
5346
|
rows.push([
|
|
5310
5347
|
cell(rel, (padded) => {
|
|
5311
5348
|
const width = padded.length;
|
|
5312
|
-
const display = shortenPathPreservingFilename(rel, width).padEnd(
|
|
5313
|
-
|
|
5314
|
-
);
|
|
5315
|
-
return linkifyPadded(
|
|
5316
|
-
opts.absPath,
|
|
5317
|
-
hotspotRange.start,
|
|
5318
|
-
opts.editorCmd
|
|
5319
|
-
)(display);
|
|
5349
|
+
const display = shortenPathPreservingFilename(rel, width).padEnd(width);
|
|
5350
|
+
return linkifyPadded(opts.absPath, hotspotRange.start, opts.editorCmd)(display);
|
|
5320
5351
|
}),
|
|
5321
5352
|
cell("Hotspot"),
|
|
5322
5353
|
cell(`L${hotspotRange.start}\u2013L${hotspotRange.end}`),
|
|
@@ -5333,11 +5364,7 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
5333
5364
|
rows.push([
|
|
5334
5365
|
cell(
|
|
5335
5366
|
rel,
|
|
5336
|
-
(padded) => ansi.dim(
|
|
5337
|
-
shortenPathPreservingFilename(rel, padded.length).padEnd(
|
|
5338
|
-
padded.length
|
|
5339
|
-
)
|
|
5340
|
-
)
|
|
5367
|
+
(padded) => ansi.dim(shortenPathPreservingFilename(rel, padded.length).padEnd(padded.length))
|
|
5341
5368
|
),
|
|
5342
5369
|
cell("Functions", ansi.dim),
|
|
5343
5370
|
cell("", ansi.dim),
|
|
@@ -5351,14 +5378,8 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
5351
5378
|
rows.push([
|
|
5352
5379
|
cell(rel, (padded) => {
|
|
5353
5380
|
const width = padded.length;
|
|
5354
|
-
const display = shortenPathPreservingFilename(rel, width).padEnd(
|
|
5355
|
-
|
|
5356
|
-
);
|
|
5357
|
-
return linkifyPadded(
|
|
5358
|
-
opts.absPath,
|
|
5359
|
-
missedFunction.line,
|
|
5360
|
-
opts.editorCmd
|
|
5361
|
-
)(display);
|
|
5381
|
+
const display = shortenPathPreservingFilename(rel, width).padEnd(width);
|
|
5382
|
+
return linkifyPadded(opts.absPath, missedFunction.line, opts.editorCmd)(display);
|
|
5362
5383
|
}),
|
|
5363
5384
|
cell("Func"),
|
|
5364
5385
|
cell(`L${missedFunction.line}`),
|
|
@@ -5375,11 +5396,7 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
5375
5396
|
rows.push([
|
|
5376
5397
|
cell(
|
|
5377
5398
|
rel,
|
|
5378
|
-
(padded) => ansi.dim(
|
|
5379
|
-
shortenPathPreservingFilename(rel, padded.length).padEnd(
|
|
5380
|
-
padded.length
|
|
5381
|
-
)
|
|
5382
|
-
)
|
|
5399
|
+
(padded) => ansi.dim(shortenPathPreservingFilename(rel, padded.length).padEnd(padded.length))
|
|
5383
5400
|
),
|
|
5384
5401
|
cell("Branches", ansi.dim),
|
|
5385
5402
|
cell("", ansi.dim),
|
|
@@ -5393,14 +5410,8 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
5393
5410
|
rows.push([
|
|
5394
5411
|
cell(rel, (padded) => {
|
|
5395
5412
|
const width = padded.length;
|
|
5396
|
-
const display = shortenPathPreservingFilename(rel, width).padEnd(
|
|
5397
|
-
|
|
5398
|
-
);
|
|
5399
|
-
return linkifyPadded(
|
|
5400
|
-
opts.absPath,
|
|
5401
|
-
missedBranch.line,
|
|
5402
|
-
opts.editorCmd
|
|
5403
|
-
)(display);
|
|
5413
|
+
const display = shortenPathPreservingFilename(rel, width).padEnd(width);
|
|
5414
|
+
return linkifyPadded(opts.absPath, missedBranch.line, opts.editorCmd)(display);
|
|
5404
5415
|
}),
|
|
5405
5416
|
cell("Branch"),
|
|
5406
5417
|
cell(`L${missedBranch.line}`),
|
|
@@ -5408,9 +5419,7 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
5408
5419
|
cell(""),
|
|
5409
5420
|
cell(""),
|
|
5410
5421
|
cell(""),
|
|
5411
|
-
cell(
|
|
5412
|
-
`#${missedBranch.id} missed [${missedBranch.zeroPaths.join(", ")}]`
|
|
5413
|
-
)
|
|
5422
|
+
cell(`#${missedBranch.id} missed [${missedBranch.zeroPaths.join(", ")}]`)
|
|
5414
5423
|
]);
|
|
5415
5424
|
}
|
|
5416
5425
|
}
|
|
@@ -5430,9 +5439,7 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
5430
5439
|
rows.push([
|
|
5431
5440
|
cell(rel, (padded) => {
|
|
5432
5441
|
const width = padded.length;
|
|
5433
|
-
const display = shortenPathPreservingFilename(rel, width).padEnd(
|
|
5434
|
-
width
|
|
5435
|
-
);
|
|
5442
|
+
const display = shortenPathPreservingFilename(rel, width).padEnd(width);
|
|
5436
5443
|
return linkifyPadded(opts.absPath, ln, opts.editorCmd)(display);
|
|
5437
5444
|
}),
|
|
5438
5445
|
cell("Line"),
|
|
@@ -5445,16 +5452,7 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
5445
5452
|
]);
|
|
5446
5453
|
}
|
|
5447
5454
|
while (rows.length < target) {
|
|
5448
|
-
rows.push([
|
|
5449
|
-
cell(""),
|
|
5450
|
-
cell(""),
|
|
5451
|
-
cell(""),
|
|
5452
|
-
cell(""),
|
|
5453
|
-
cell(""),
|
|
5454
|
-
cell(""),
|
|
5455
|
-
cell(""),
|
|
5456
|
-
cell("")
|
|
5457
|
-
]);
|
|
5455
|
+
rows.push([cell(""), cell(""), cell(""), cell(""), cell(""), cell(""), cell(""), cell("")]);
|
|
5458
5456
|
}
|
|
5459
5457
|
}
|
|
5460
5458
|
}
|
|
@@ -5462,20 +5460,17 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
5462
5460
|
console.info(table);
|
|
5463
5461
|
const sep = ansi.gray(
|
|
5464
5462
|
"\u2500".repeat(
|
|
5465
|
-
Math.max(
|
|
5466
|
-
20,
|
|
5467
|
-
typeof process.stdout.columns === "number" ? process.stdout.columns : 100
|
|
5468
|
-
)
|
|
5463
|
+
Math.max(20, typeof process.stdout.columns === "number" ? process.stdout.columns : 100)
|
|
5469
5464
|
)
|
|
5470
5465
|
);
|
|
5471
5466
|
console.info(sep);
|
|
5472
5467
|
};
|
|
5473
5468
|
var printPerFileCompositeTables = async (opts) => {
|
|
5474
5469
|
const selectionAbs = (opts.selectionPaths ?? []).map(
|
|
5475
|
-
(selPath) =>
|
|
5470
|
+
(selPath) => path8.resolve(selPath).replace(/\\/g, "/")
|
|
5476
5471
|
);
|
|
5477
5472
|
const changedAbs = (opts.changedFiles ?? []).map(
|
|
5478
|
-
(chgPath) =>
|
|
5473
|
+
(chgPath) => path8.resolve(chgPath).replace(/\\/g, "/")
|
|
5479
5474
|
);
|
|
5480
5475
|
const tokenizeForSimilarity = (filePathForTokens) => new Set(
|
|
5481
5476
|
filePathForTokens.toLowerCase().replace(/[^a-z0-9/_\-.]/g, " ").split(/[/_.-]+/).filter(Boolean)
|
|
@@ -5491,15 +5486,15 @@ var printPerFileCompositeTables = async (opts) => {
|
|
|
5491
5486
|
return intersectionCount / unionSize;
|
|
5492
5487
|
};
|
|
5493
5488
|
const isSameDirOrChild = (firstAbs, secondAbs) => {
|
|
5494
|
-
const dirA =
|
|
5495
|
-
const dirB =
|
|
5489
|
+
const dirA = path8.dirname(firstAbs).replace(/\\/g, "/");
|
|
5490
|
+
const dirB = path8.dirname(secondAbs).replace(/\\/g, "/");
|
|
5496
5491
|
return dirA === dirB || dirB.startsWith(`${dirA}/`) || dirA.startsWith(`${dirB}/`);
|
|
5497
5492
|
};
|
|
5498
5493
|
const selectionTokens = selectionAbs.map(tokenizeForSimilarity);
|
|
5499
5494
|
const changedTokens = changedAbs.map(tokenizeForSimilarity);
|
|
5500
|
-
const executedTestsAbs = (opts.executedTests ?? []).map((testPath) =>
|
|
5495
|
+
const executedTestsAbs = (opts.executedTests ?? []).map((testPath) => path8.resolve(testPath).replace(/\\/g, "/")).filter((absPath) => absPath.length > 0);
|
|
5501
5496
|
const testTokens = executedTestsAbs.map(tokenizeForSimilarity);
|
|
5502
|
-
const allMapFilesAbs = opts.map.files().map((absPath) =>
|
|
5497
|
+
const allMapFilesAbs = opts.map.files().map((absPath) => path8.resolve(absPath).replace(/\\/g, "/"));
|
|
5503
5498
|
const uncoveredCandidates = allMapFilesAbs.filter((absPath) => {
|
|
5504
5499
|
const sum = opts.map.fileCoverageFor(absPath).toSummary();
|
|
5505
5500
|
return !(sum.lines.pct >= 100 && sum.functions.pct >= 100 && sum.branches.pct >= 100);
|
|
@@ -5516,33 +5511,24 @@ var printPerFileCompositeTables = async (opts) => {
|
|
|
5516
5511
|
const selectionSetAbs = new Set(selectionAbs);
|
|
5517
5512
|
const scored = await Promise.all(
|
|
5518
5513
|
candidates.map(async (abs) => {
|
|
5519
|
-
const rel =
|
|
5514
|
+
const rel = path8.relative(opts.root, abs).replace(/\\/g, "/");
|
|
5520
5515
|
const sum = opts.map.fileCoverageFor(abs).toSummary();
|
|
5521
5516
|
const pct = Number.isFinite(sum.lines.pct) ? sum.lines.pct : 0;
|
|
5522
|
-
const absNorm =
|
|
5517
|
+
const absNorm = path8.resolve(abs).replace(/\\/g, "/");
|
|
5523
5518
|
const selfTokens = tokenizeForSimilarity(absNorm);
|
|
5524
5519
|
const selSim = Math.max(
|
|
5525
5520
|
0,
|
|
5526
|
-
...selectionTokens.map(
|
|
5527
|
-
(selectionTokenSet) => jaccard(selfTokens, selectionTokenSet)
|
|
5528
|
-
)
|
|
5521
|
+
...selectionTokens.map((selectionTokenSet) => jaccard(selfTokens, selectionTokenSet))
|
|
5529
5522
|
);
|
|
5530
5523
|
const chgSim = Math.max(
|
|
5531
5524
|
0,
|
|
5532
|
-
...changedTokens.map(
|
|
5533
|
-
(changedTokenSet) => jaccard(selfTokens, changedTokenSet)
|
|
5534
|
-
)
|
|
5535
|
-
);
|
|
5536
|
-
const tstSim = Math.max(
|
|
5537
|
-
0,
|
|
5538
|
-
...testTokens.map((tset) => jaccard(selfTokens, tset))
|
|
5525
|
+
...changedTokens.map((changedTokenSet) => jaccard(selfTokens, changedTokenSet))
|
|
5539
5526
|
);
|
|
5527
|
+
const tstSim = Math.max(0, ...testTokens.map((tset) => jaccard(selfTokens, tset)));
|
|
5540
5528
|
const nearSelection = selectionAbs.some(
|
|
5541
5529
|
(selectionPath) => isSameDirOrChild(absNorm, selectionPath)
|
|
5542
5530
|
);
|
|
5543
|
-
const nearChanged = changedAbs.some(
|
|
5544
|
-
(changedPath) => isSameDirOrChild(absNorm, changedPath)
|
|
5545
|
-
);
|
|
5531
|
+
const nearChanged = changedAbs.some((changedPath) => isSameDirOrChild(absNorm, changedPath));
|
|
5546
5532
|
const related = selSim > 0 || chgSim > 0 || nearSelection || nearChanged;
|
|
5547
5533
|
const distance = selectionSetAbs.has(absNorm) ? 0 : distFromTests.get(absNorm) ?? INF;
|
|
5548
5534
|
let group = 6;
|
|
@@ -5566,9 +5552,12 @@ var printPerFileCompositeTables = async (opts) => {
|
|
|
5566
5552
|
return { abs: absNorm, rel, linesPct: pct, group, score, distance };
|
|
5567
5553
|
})
|
|
5568
5554
|
);
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5555
|
+
const prodSeeds = selectionAbs.length > 0 ? selectionAbs : changedAbs;
|
|
5556
|
+
const rank = await computeDirectnessRank({ repoRoot: opts.root, productionSeeds: prodSeeds });
|
|
5557
|
+
let files = sortPathsWithRank(
|
|
5558
|
+
rank,
|
|
5559
|
+
scored.map((s) => s.abs)
|
|
5560
|
+
);
|
|
5572
5561
|
if (selectionAbs.length > 0) {
|
|
5573
5562
|
const selectionSet = new Set(selectionAbs);
|
|
5574
5563
|
const selectedHead = files.filter((filePath) => selectionSet.has(filePath));
|
|
@@ -5592,7 +5581,7 @@ var printPerFileCompositeTables = async (opts) => {
|
|
|
5592
5581
|
|
|
5593
5582
|
// src/lib/jest-bridge.ts
|
|
5594
5583
|
var import_json5 = __toESM(require_lib(), 1);
|
|
5595
|
-
import * as
|
|
5584
|
+
import * as path9 from "node:path";
|
|
5596
5585
|
import * as fs4 from "node:fs";
|
|
5597
5586
|
import * as util from "node:util";
|
|
5598
5587
|
var extractBridgePath = (raw, cwd) => {
|
|
@@ -5603,7 +5592,7 @@ var extractBridgePath = (raw, cwd) => {
|
|
|
5603
5592
|
return null;
|
|
5604
5593
|
}
|
|
5605
5594
|
const jsonPath = matches[matches.length - 1][1].trim().replace(/^["'`]|["'`]$/g, "");
|
|
5606
|
-
return
|
|
5595
|
+
return path9.isAbsolute(jsonPath) ? jsonPath : path9.resolve(cwd, jsonPath);
|
|
5607
5596
|
};
|
|
5608
5597
|
var drawRule = (label) => {
|
|
5609
5598
|
const width = Math.max(
|
|
@@ -6251,7 +6240,7 @@ var buildStackSection = (mergedForStack, ctx, fallbackLoc) => {
|
|
|
6251
6240
|
const loc = deepestProjectLoc(mergedForStack, ctx.projectHint);
|
|
6252
6241
|
if (loc) {
|
|
6253
6242
|
const href = preferredEditorHref(loc.file, loc.line, ctx.editorCmd);
|
|
6254
|
-
out.push(` ${ansi.dim("at")} ${osc8(`${
|
|
6243
|
+
out.push(` ${ansi.dim("at")} ${osc8(`${path9.basename(loc.file)}:${loc.line}`, href)}`);
|
|
6255
6244
|
}
|
|
6256
6245
|
out.push("");
|
|
6257
6246
|
return out;
|
|
@@ -6530,7 +6519,7 @@ function renderVitestFromJestJSON(data, opts) {
|
|
|
6530
6519
|
const deepestLoc = deepestProjectLoc(mergedForStack, projectHint);
|
|
6531
6520
|
const locLink = deepestLoc && (() => {
|
|
6532
6521
|
const href = preferredEditorHref(deepestLoc.file, deepestLoc.line, opts?.editorCmd);
|
|
6533
|
-
const base = `${
|
|
6522
|
+
const base = `${path9.basename(deepestLoc.file)}:${deepestLoc.line}`;
|
|
6534
6523
|
return osc8(base, href);
|
|
6535
6524
|
})();
|
|
6536
6525
|
const headerLine = `${ansi.white(header)}${locLink ? ` ${ansi.dim(`(${locLink})`)}` : ""}`;
|
|
@@ -6578,7 +6567,7 @@ ${footer}`;
|
|
|
6578
6567
|
init_env_utils();
|
|
6579
6568
|
init_exec();
|
|
6580
6569
|
init_args();
|
|
6581
|
-
import * as
|
|
6570
|
+
import * as path10 from "node:path";
|
|
6582
6571
|
import * as os2 from "node:os";
|
|
6583
6572
|
import * as fsSync3 from "node:fs";
|
|
6584
6573
|
import * as fs5 from "node:fs/promises";
|
|
@@ -6587,10 +6576,6 @@ import * as Reports from "istanbul-reports";
|
|
|
6587
6576
|
import { createCoverageMap as createCoverageMap2 } from "istanbul-lib-coverage";
|
|
6588
6577
|
var jestBin = "./node_modules/.bin/jest";
|
|
6589
6578
|
var babelNodeBin = "./node_modules/.bin/babel-node";
|
|
6590
|
-
var moduleSpecifierForRequire = (
|
|
6591
|
-
// @ts-ignore
|
|
6592
|
-
typeof __filename !== "undefined" ? __filename : import.meta.url
|
|
6593
|
-
);
|
|
6594
6579
|
var registerSignalHandlersOnce = () => {
|
|
6595
6580
|
let handled = false;
|
|
6596
6581
|
const on = (sig) => {
|
|
@@ -6608,7 +6593,6 @@ Received ${sig}, exiting...
|
|
|
6608
6593
|
};
|
|
6609
6594
|
var isDebug = () => Boolean(process.env.TEST_CLI_DEBUG);
|
|
6610
6595
|
var mergeLcov = async () => {
|
|
6611
|
-
const jestLcovPath = "coverage/jest/lcov.info";
|
|
6612
6596
|
const vitestLcovPath = "coverage/vitest/lcov.info";
|
|
6613
6597
|
const mergedOutPath = "coverage/lcov.info";
|
|
6614
6598
|
const readOrEmpty = async (filePath) => {
|
|
@@ -6619,7 +6603,7 @@ var mergeLcov = async () => {
|
|
|
6619
6603
|
}
|
|
6620
6604
|
};
|
|
6621
6605
|
let vitestContent = "";
|
|
6622
|
-
|
|
6606
|
+
const jestParts = [];
|
|
6623
6607
|
try {
|
|
6624
6608
|
vitestContent = await readOrEmpty(vitestLcovPath);
|
|
6625
6609
|
} catch (readVitestError) {
|
|
@@ -6627,20 +6611,46 @@ var mergeLcov = async () => {
|
|
|
6627
6611
|
console.info(`read vitest lcov failed: ${String(readVitestError)}`);
|
|
6628
6612
|
}
|
|
6629
6613
|
}
|
|
6614
|
+
const collectLcovs = (dir) => {
|
|
6615
|
+
const out = [];
|
|
6616
|
+
try {
|
|
6617
|
+
const entries = fsSync3.readdirSync(dir, { withFileTypes: true });
|
|
6618
|
+
for (const entry of entries) {
|
|
6619
|
+
const full = path10.join(dir, entry.name);
|
|
6620
|
+
if (entry.isDirectory()) {
|
|
6621
|
+
out.push(...collectLcovs(full));
|
|
6622
|
+
} else if (entry.isFile() && entry.name === "lcov.info") {
|
|
6623
|
+
out.push(full);
|
|
6624
|
+
}
|
|
6625
|
+
}
|
|
6626
|
+
} catch {
|
|
6627
|
+
}
|
|
6628
|
+
return out;
|
|
6629
|
+
};
|
|
6630
6630
|
try {
|
|
6631
|
-
|
|
6631
|
+
const jestRoot = path10.join("coverage", "jest");
|
|
6632
|
+
const candidates = [path10.join(jestRoot, "lcov.info"), ...collectLcovs(jestRoot)].map((candidatePath) => path10.resolve(candidatePath)).filter((absolutePath, index, arr) => arr.indexOf(absolutePath) === index);
|
|
6633
|
+
for (const filePath of candidates) {
|
|
6634
|
+
try {
|
|
6635
|
+
const content = await readOrEmpty(filePath);
|
|
6636
|
+
if (content.trim()) {
|
|
6637
|
+
jestParts.push(content.trim());
|
|
6638
|
+
}
|
|
6639
|
+
} catch {
|
|
6640
|
+
}
|
|
6641
|
+
}
|
|
6632
6642
|
} catch (readJestError) {
|
|
6633
6643
|
if (isDebug()) {
|
|
6634
|
-
console.info(`
|
|
6644
|
+
console.info(`scan jest lcov failed: ${String(readJestError)}`);
|
|
6635
6645
|
}
|
|
6636
6646
|
}
|
|
6637
|
-
if (!vitestContent &&
|
|
6647
|
+
if (!vitestContent && jestParts.length === 0) {
|
|
6638
6648
|
if (isDebug()) {
|
|
6639
6649
|
console.info("No coverage outputs found to merge.");
|
|
6640
6650
|
}
|
|
6641
6651
|
return;
|
|
6642
6652
|
}
|
|
6643
|
-
const merged = [vitestContent.trim(),
|
|
6653
|
+
const merged = [vitestContent.trim(), ...jestParts].filter(Boolean).join("\n");
|
|
6644
6654
|
if (merged.length > 0) {
|
|
6645
6655
|
await (await import("node:fs/promises")).mkdir("coverage", { recursive: true });
|
|
6646
6656
|
await (await import("node:fs/promises")).writeFile(mergedOutPath, `${merged}
|
|
@@ -6653,23 +6663,40 @@ var mergeLcov = async () => {
|
|
|
6653
6663
|
}
|
|
6654
6664
|
};
|
|
6655
6665
|
var emitMergedCoverage = async (ui, opts) => {
|
|
6656
|
-
const jestJson = path9.join("coverage", "jest", "coverage-final.json");
|
|
6657
|
-
const jSize = fsSync3.existsSync(jestJson) ? fsSync3.statSync(jestJson).size : -1;
|
|
6658
|
-
const jestSizeLabel = jSize >= 0 ? `${jSize} bytes` : "missing";
|
|
6659
|
-
if (isDebug()) {
|
|
6660
|
-
console.info(`Coverage JSON probe \u2192 jest: ${jestSizeLabel}`);
|
|
6661
|
-
}
|
|
6662
|
-
const jestData = await readCoverageJson(jestJson);
|
|
6663
|
-
const jestFilesCount = Object.keys(jestData).length;
|
|
6664
|
-
if (isDebug()) {
|
|
6665
|
-
console.info(`Decoded coverage entries \u2192 jest: ${jestFilesCount}`);
|
|
6666
|
-
}
|
|
6667
6666
|
const map = createCoverageMap2({});
|
|
6668
|
-
|
|
6667
|
+
const listJsons = (dir) => {
|
|
6668
|
+
const out = [];
|
|
6669
6669
|
try {
|
|
6670
|
-
|
|
6670
|
+
const entries = fsSync3.readdirSync(dir, { withFileTypes: true });
|
|
6671
|
+
for (const entry of entries) {
|
|
6672
|
+
const full = path10.join(dir, entry.name);
|
|
6673
|
+
if (entry.isDirectory()) {
|
|
6674
|
+
out.push(...listJsons(full));
|
|
6675
|
+
} else if (entry.isFile() && entry.name === "coverage-final.json") {
|
|
6676
|
+
out.push(full);
|
|
6677
|
+
}
|
|
6678
|
+
}
|
|
6679
|
+
} catch {
|
|
6680
|
+
}
|
|
6681
|
+
return out;
|
|
6682
|
+
};
|
|
6683
|
+
const coverageRoot = path10.join("coverage", "jest");
|
|
6684
|
+
const jsonCandidates = [
|
|
6685
|
+
path10.join(coverageRoot, "coverage-final.json"),
|
|
6686
|
+
...listJsons(coverageRoot)
|
|
6687
|
+
].map((candidatePath) => path10.resolve(candidatePath)).filter((absolutePath, index, arr) => {
|
|
6688
|
+
const isFirst = arr.indexOf(absolutePath) === index;
|
|
6689
|
+
const exists = fsSync3.existsSync(absolutePath);
|
|
6690
|
+
return isFirst && exists;
|
|
6691
|
+
});
|
|
6692
|
+
for (const jsonPath of jsonCandidates) {
|
|
6693
|
+
try {
|
|
6694
|
+
const data = await readCoverageJson(jsonPath);
|
|
6695
|
+
if (Object.keys(data).length) {
|
|
6696
|
+
map.merge(data);
|
|
6697
|
+
}
|
|
6671
6698
|
} catch (mergeJestError) {
|
|
6672
|
-
console.warn(`Failed merging jest coverage JSON: ${String(mergeJestError)}`);
|
|
6699
|
+
console.warn(`Failed merging jest coverage JSON @ ${jsonPath}: ${String(mergeJestError)}`);
|
|
6673
6700
|
}
|
|
6674
6701
|
}
|
|
6675
6702
|
if (map.files().length === 0) {
|
|
@@ -6719,7 +6746,7 @@ var emitMergedCoverage = async (ui, opts) => {
|
|
|
6719
6746
|
executedTests: opts.executedTests ?? []
|
|
6720
6747
|
});
|
|
6721
6748
|
const context = LibReport.createContext({
|
|
6722
|
-
dir:
|
|
6749
|
+
dir: path10.resolve("coverage", "merged"),
|
|
6723
6750
|
coverageMap: filteredMap,
|
|
6724
6751
|
defaultSummarizer: "nested"
|
|
6725
6752
|
});
|
|
@@ -6787,8 +6814,8 @@ var emitMergedCoverage = async (ui, opts) => {
|
|
|
6787
6814
|
for (const reporter of reporters) {
|
|
6788
6815
|
reporter.execute(context);
|
|
6789
6816
|
}
|
|
6790
|
-
const textPath =
|
|
6791
|
-
const summaryPath =
|
|
6817
|
+
const textPath = path10.resolve("coverage", "merged", "coverage.txt");
|
|
6818
|
+
const summaryPath = path10.resolve("coverage", "merged", "coverage-summary.txt");
|
|
6792
6819
|
const filesToPrint = [];
|
|
6793
6820
|
if (fsSync3.existsSync(textPath)) {
|
|
6794
6821
|
filesToPrint.push(textPath);
|
|
@@ -6870,17 +6897,43 @@ var program = async () => {
|
|
|
6870
6897
|
coverageMode,
|
|
6871
6898
|
coverageMaxFiles: coverageMaxFilesArg,
|
|
6872
6899
|
coverageMaxHotspots: coverageMaxHotspotsArg,
|
|
6873
|
-
coveragePageFit
|
|
6900
|
+
coveragePageFit,
|
|
6901
|
+
changed
|
|
6874
6902
|
} = deriveArgs(argv);
|
|
6875
|
-
|
|
6903
|
+
const getChangedFiles = async (mode, cwd) => {
|
|
6904
|
+
const collect = async (cmd, args) => {
|
|
6905
|
+
try {
|
|
6906
|
+
const out = await runText(cmd, args, {
|
|
6907
|
+
cwd,
|
|
6908
|
+
env: safeEnv(process.env, {}),
|
|
6909
|
+
timeoutMs: 4e3
|
|
6910
|
+
});
|
|
6911
|
+
return out.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
6912
|
+
} catch {
|
|
6913
|
+
return [];
|
|
6914
|
+
}
|
|
6915
|
+
};
|
|
6916
|
+
const staged = mode === "staged" || mode === "all" ? await collect("git", ["diff", "--name-only", "--diff-filter=ACMRTUXB", "--cached"]) : [];
|
|
6917
|
+
const unstagedTracked = mode === "unstaged" || mode === "all" ? await collect("git", ["diff", "--name-only", "--diff-filter=ACMRTUXB"]) : [];
|
|
6918
|
+
const untracked = mode === "unstaged" || mode === "all" ? await collect("git", ["ls-files", "--others", "--exclude-standard"]) : [];
|
|
6919
|
+
const rels = Array.from(/* @__PURE__ */ new Set([...staged, ...unstagedTracked, ...untracked]));
|
|
6920
|
+
return rels.map((rel) => path10.resolve(cwd, rel).replace(/\\/g, "/")).filter((abs) => !abs.includes("/node_modules/") && !abs.includes("/coverage/"));
|
|
6921
|
+
};
|
|
6922
|
+
const repoRootForChanged = workspaceRoot ?? await findRepoRoot();
|
|
6923
|
+
const changedSelectionAbs = changed ? await getChangedFiles(changed, repoRootForChanged) : [];
|
|
6924
|
+
const selectionPathsAugmented = changedSelectionAbs.length ? Array.from(/* @__PURE__ */ new Set([...selectionPaths, ...changedSelectionAbs])) : selectionPaths;
|
|
6925
|
+
const selectionSpecifiedAugmented = Boolean(selectionSpecified || changedSelectionAbs.length > 0);
|
|
6926
|
+
console.info(
|
|
6927
|
+
`Selection \u2192 specified=${selectionSpecifiedAugmented} paths=${selectionPathsAugmented.length}`
|
|
6928
|
+
);
|
|
6876
6929
|
const { jest } = argsForDiscovery(["run"], jestArgs);
|
|
6877
|
-
const selectionLooksLikeTest =
|
|
6930
|
+
const selectionLooksLikeTest = selectionPathsAugmented.some(
|
|
6878
6931
|
(pathText) => /\.(test|spec)\.[tj]sx?$/i.test(pathText) || /(^|\/)tests?\//i.test(pathText)
|
|
6879
6932
|
);
|
|
6880
|
-
const selectionLooksLikePath =
|
|
6933
|
+
const selectionLooksLikePath = selectionPathsAugmented.some(
|
|
6881
6934
|
(pathText) => /[\\/]/.test(pathText) || /\.(m?[tj]sx?)$/i.test(pathText)
|
|
6882
6935
|
);
|
|
6883
|
-
const selectionHasPaths =
|
|
6936
|
+
const selectionHasPaths = selectionPathsAugmented.length > 0;
|
|
6884
6937
|
const repoRootForDiscovery = workspaceRoot ?? await findRepoRoot();
|
|
6885
6938
|
const expandProductionSelections = async (tokens, repoRoot) => {
|
|
6886
6939
|
const results = /* @__PURE__ */ new Set();
|
|
@@ -6889,18 +6942,18 @@ var program = async () => {
|
|
|
6889
6942
|
if (!token) {
|
|
6890
6943
|
continue;
|
|
6891
6944
|
}
|
|
6892
|
-
const isAbs =
|
|
6945
|
+
const isAbs = path10.isAbsolute(token);
|
|
6893
6946
|
const looksLikeRelPath = /[\\/]/.test(token);
|
|
6894
6947
|
let candidateFromRoot;
|
|
6895
6948
|
if (token.startsWith("/")) {
|
|
6896
|
-
candidateFromRoot =
|
|
6949
|
+
candidateFromRoot = path10.join(repoRoot, token.slice(1));
|
|
6897
6950
|
} else if (looksLikeRelPath) {
|
|
6898
|
-
candidateFromRoot =
|
|
6951
|
+
candidateFromRoot = path10.join(repoRoot, token);
|
|
6899
6952
|
} else {
|
|
6900
6953
|
candidateFromRoot = void 0;
|
|
6901
6954
|
}
|
|
6902
6955
|
const tryPushIfProd = (absPath) => {
|
|
6903
|
-
const norm =
|
|
6956
|
+
const norm = path10.resolve(absPath).replace(/\\/g, "/");
|
|
6904
6957
|
const isTest = /(^|\/)tests?\//i.test(norm) || /\.(test|spec)\.[tj]sx?$/i.test(norm);
|
|
6905
6958
|
if (!isTest && fsSync3.existsSync(norm)) {
|
|
6906
6959
|
results.add(norm);
|
|
@@ -6922,7 +6975,7 @@ var program = async () => {
|
|
|
6922
6975
|
}),
|
|
6923
6976
|
timeoutMs: 4e3
|
|
6924
6977
|
});
|
|
6925
|
-
const matches = out.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map((rel) =>
|
|
6978
|
+
const matches = out.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map((rel) => path10.resolve(repoRoot, rel).replace(/\\/g, "/")).filter(
|
|
6926
6979
|
(abs) => !abs.includes("/node_modules/") && !abs.includes("/coverage/") && !/(^|\/)tests?\//i.test(abs) && !/\.(test|spec)\.[tj]sx?$/i.test(abs)
|
|
6927
6980
|
);
|
|
6928
6981
|
matches.forEach((abs) => results.add(abs));
|
|
@@ -6931,20 +6984,20 @@ var program = async () => {
|
|
|
6931
6984
|
}
|
|
6932
6985
|
return Array.from(results);
|
|
6933
6986
|
};
|
|
6934
|
-
const initialProdSelections =
|
|
6987
|
+
const initialProdSelections = selectionPathsAugmented.filter(
|
|
6935
6988
|
(pathText) => (/[\\/]/.test(pathText) || /\.(m?[tj]sx?)$/i.test(pathText)) && !/(^|\/)tests?\//i.test(pathText) && !/\.(test|spec)\.[tj]sx?$/i.test(pathText)
|
|
6936
6989
|
);
|
|
6937
|
-
const expandedProdSelections = initialProdSelections.length ? initialProdSelections : await expandProductionSelections(
|
|
6990
|
+
const expandedProdSelections = initialProdSelections.length ? initialProdSelections : await expandProductionSelections(selectionPathsAugmented, repoRootForDiscovery);
|
|
6938
6991
|
const selectionIncludesProdPaths = expandedProdSelections.length > 0;
|
|
6939
6992
|
console.info(
|
|
6940
6993
|
`Selection classify \u2192 looksLikePath=${selectionLooksLikePath} looksLikeTest=${selectionLooksLikeTest} prodPaths=${selectionIncludesProdPaths}`
|
|
6941
6994
|
);
|
|
6942
|
-
const stripPathTokens = (args) => args.filter((token) => !
|
|
6995
|
+
const stripPathTokens = (args) => args.filter((token) => !selectionPathsAugmented.includes(token));
|
|
6943
6996
|
const jestDiscoveryArgs = selectionIncludesProdPaths ? stripPathTokens(jest) : jest;
|
|
6944
6997
|
const projectConfigs = [];
|
|
6945
6998
|
try {
|
|
6946
|
-
const baseCfg =
|
|
6947
|
-
const tsCfg =
|
|
6999
|
+
const baseCfg = path10.resolve("jest.config.js");
|
|
7000
|
+
const tsCfg = path10.resolve("jest.ts.config.js");
|
|
6948
7001
|
if (fsSync3.existsSync(baseCfg)) {
|
|
6949
7002
|
projectConfigs.push(baseCfg);
|
|
6950
7003
|
}
|
|
@@ -6961,7 +7014,7 @@ var program = async () => {
|
|
|
6961
7014
|
);
|
|
6962
7015
|
const prodSelections2 = expandedProdSelections;
|
|
6963
7016
|
for (const cfg of projectConfigs) {
|
|
6964
|
-
const cfgCwd =
|
|
7017
|
+
const cfgCwd = path10.dirname(cfg);
|
|
6965
7018
|
const allTests = await discoverJestResilient([...jestDiscoveryArgs, "--config", cfg], {
|
|
6966
7019
|
cwd: cfgCwd
|
|
6967
7020
|
});
|
|
@@ -6974,7 +7027,7 @@ var program = async () => {
|
|
|
6974
7027
|
});
|
|
6975
7028
|
} catch (err) {
|
|
6976
7029
|
if (isDebug()) {
|
|
6977
|
-
console.warn(`direct selection failed for project ${
|
|
7030
|
+
console.warn(`direct selection failed for project ${path10.basename(cfg)}: ${String(err)}`);
|
|
6978
7031
|
}
|
|
6979
7032
|
}
|
|
6980
7033
|
perProjectFiles.set(cfg, directPerProject);
|
|
@@ -6986,7 +7039,7 @@ var program = async () => {
|
|
|
6986
7039
|
)} | related=${selectionIncludesProdPaths} | cwd=${repoRootForDiscovery}`
|
|
6987
7040
|
);
|
|
6988
7041
|
for (const cfg of projectConfigs) {
|
|
6989
|
-
const cfgCwd =
|
|
7042
|
+
const cfgCwd = path10.dirname(cfg);
|
|
6990
7043
|
const files = await discoverJestResilient([...jestDiscoveryArgs, "--config", cfg], {
|
|
6991
7044
|
cwd: cfgCwd
|
|
6992
7045
|
});
|
|
@@ -6996,18 +7049,18 @@ var program = async () => {
|
|
|
6996
7049
|
const perProjectFiltered = /* @__PURE__ */ new Map();
|
|
6997
7050
|
for (const cfg of projectConfigs) {
|
|
6998
7051
|
const files = perProjectFiles.get(cfg) ?? [];
|
|
6999
|
-
const selectionTestPaths =
|
|
7052
|
+
const selectionTestPaths = selectionPathsAugmented.filter(
|
|
7000
7053
|
(pathToken) => /\.(test|spec)\.[tj]sx?$/i.test(pathToken) || /(^|\/)tests?\//i.test(pathToken)
|
|
7001
7054
|
);
|
|
7002
7055
|
const candidates = selectionHasPaths && selectionLooksLikeTest ? selectionTestPaths : files;
|
|
7003
7056
|
const absFiles = candidates.map(
|
|
7004
|
-
(candidatePath) =>
|
|
7057
|
+
(candidatePath) => path10.isAbsolute(candidatePath) ? candidatePath : path10.join(repoRootForDiscovery, candidatePath)
|
|
7005
7058
|
).map((absolutePath) => absolutePath.replace(/\\/g, "/"));
|
|
7006
7059
|
const onlyOwned = await filterCandidatesForProject(
|
|
7007
7060
|
cfg,
|
|
7008
7061
|
jestDiscoveryArgs,
|
|
7009
7062
|
absFiles,
|
|
7010
|
-
|
|
7063
|
+
path10.dirname(cfg)
|
|
7011
7064
|
);
|
|
7012
7065
|
perProjectFiltered.set(cfg, onlyOwned);
|
|
7013
7066
|
}
|
|
@@ -7019,7 +7072,7 @@ var program = async () => {
|
|
|
7019
7072
|
if (selectionHasPaths && prodSelections.length > 0) {
|
|
7020
7073
|
console.info(`rg related \u2192 prodSelections=${prodSelections.length} (starting)`);
|
|
7021
7074
|
const repoRootForRefinement = workspaceRoot ?? await findRepoRoot();
|
|
7022
|
-
const selectionKey = prodSelections.map((absPath) =>
|
|
7075
|
+
const selectionKey = prodSelections.map((absPath) => path10.relative(repoRootForRefinement, absPath).replace(/\\/g, "/")).sort((firstPath, secondPath) => firstPath.localeCompare(secondPath)).join("|");
|
|
7023
7076
|
const { cachedRelated: cachedRelated2, findRelatedTestsFast: findRelatedTestsFast2, DEFAULT_TEST_GLOBS: DEFAULT_TEST_GLOBS2 } = await Promise.resolve().then(() => (init_fast_related(), fast_related_exports));
|
|
7024
7077
|
const { DEFAULT_EXCLUDE: DEFAULT_EXCLUDE2 } = await Promise.resolve().then(() => (init_args(), args_exports));
|
|
7025
7078
|
const rgMatches = await cachedRelated2({
|
|
@@ -7049,7 +7102,7 @@ var program = async () => {
|
|
|
7049
7102
|
cfg,
|
|
7050
7103
|
jestDiscoveryArgs,
|
|
7051
7104
|
rgCandidates,
|
|
7052
|
-
|
|
7105
|
+
path10.dirname(cfg)
|
|
7053
7106
|
);
|
|
7054
7107
|
perProjectFromRg.set(cfg, owned);
|
|
7055
7108
|
}
|
|
@@ -7064,9 +7117,9 @@ var program = async () => {
|
|
|
7064
7117
|
} else {
|
|
7065
7118
|
const repoRootForScan = repoRootForDiscovery;
|
|
7066
7119
|
const toSeeds = (abs) => {
|
|
7067
|
-
const rel =
|
|
7120
|
+
const rel = path10.relative(repoRootForScan, abs).replace(/\\/g, "/");
|
|
7068
7121
|
const withoutExt = rel.replace(/\.(m?[tj]sx?)$/i, "");
|
|
7069
|
-
const base =
|
|
7122
|
+
const base = path10.basename(withoutExt);
|
|
7070
7123
|
const segs = withoutExt.split("/");
|
|
7071
7124
|
const tail2 = segs.slice(-2).join("/");
|
|
7072
7125
|
return Array.from(new Set([withoutExt, base, tail2].filter(Boolean)));
|
|
@@ -7081,8 +7134,8 @@ var program = async () => {
|
|
|
7081
7134
|
}
|
|
7082
7135
|
};
|
|
7083
7136
|
const resolveLocalImport = (fromFile, spec) => {
|
|
7084
|
-
const baseDir =
|
|
7085
|
-
const cand =
|
|
7137
|
+
const baseDir = path10.dirname(fromFile);
|
|
7138
|
+
const cand = path10.resolve(baseDir, spec);
|
|
7086
7139
|
const exts = ["", ".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
7087
7140
|
for (const ext of exts) {
|
|
7088
7141
|
const full = ext ? `${cand}${ext}` : cand;
|
|
@@ -7091,7 +7144,7 @@ var program = async () => {
|
|
|
7091
7144
|
}
|
|
7092
7145
|
}
|
|
7093
7146
|
for (const ext of exts) {
|
|
7094
|
-
const full =
|
|
7147
|
+
const full = path10.join(cand, `index${ext}`);
|
|
7095
7148
|
if (fsSync3.existsSync(full)) {
|
|
7096
7149
|
return full;
|
|
7097
7150
|
}
|
|
@@ -7145,7 +7198,7 @@ var program = async () => {
|
|
|
7145
7198
|
cfg,
|
|
7146
7199
|
jestDiscoveryArgs,
|
|
7147
7200
|
keptCandidates,
|
|
7148
|
-
|
|
7201
|
+
path10.dirname(cfg)
|
|
7149
7202
|
);
|
|
7150
7203
|
perProjectFromScan.set(cfg, owned);
|
|
7151
7204
|
}
|
|
@@ -7172,9 +7225,9 @@ var program = async () => {
|
|
|
7172
7225
|
if (effectiveJestFiles.length === 0) {
|
|
7173
7226
|
const repoRoot = repoRootForRefinement;
|
|
7174
7227
|
const seeds = prodSelections.map(
|
|
7175
|
-
(abs) =>
|
|
7228
|
+
(abs) => path10.relative(repoRoot, abs).replace(/\\/g, "/").replace(/\.(m?[tj]sx?)$/i, "")
|
|
7176
7229
|
).flatMap((rel) => {
|
|
7177
|
-
const base =
|
|
7230
|
+
const base = path10.basename(rel);
|
|
7178
7231
|
const segments = rel.split("/");
|
|
7179
7232
|
return Array.from(new Set([rel, base, segments.slice(-2).join("/")].filter(Boolean)));
|
|
7180
7233
|
});
|
|
@@ -7187,8 +7240,8 @@ var program = async () => {
|
|
|
7187
7240
|
}
|
|
7188
7241
|
};
|
|
7189
7242
|
const resolveLocalImport = (fromFile, spec) => {
|
|
7190
|
-
const baseDir =
|
|
7191
|
-
const candidate =
|
|
7243
|
+
const baseDir = path10.dirname(fromFile);
|
|
7244
|
+
const candidate = path10.resolve(baseDir, spec);
|
|
7192
7245
|
const extensions = ["", ".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts"];
|
|
7193
7246
|
for (const ext of extensions) {
|
|
7194
7247
|
const fullPath = ext ? `${candidate}${ext}` : candidate;
|
|
@@ -7197,7 +7250,7 @@ var program = async () => {
|
|
|
7197
7250
|
}
|
|
7198
7251
|
}
|
|
7199
7252
|
for (const ext of extensions) {
|
|
7200
|
-
const fullPath =
|
|
7253
|
+
const fullPath = path10.join(candidate, `index${ext}`);
|
|
7201
7254
|
if (fsSync3.existsSync(fullPath)) {
|
|
7202
7255
|
return fullPath;
|
|
7203
7256
|
}
|
|
@@ -7316,8 +7369,8 @@ var program = async () => {
|
|
|
7316
7369
|
}
|
|
7317
7370
|
}
|
|
7318
7371
|
const jestDecision = decideShouldRunJest([], effectiveJestFiles, {
|
|
7319
|
-
selectionSpecified,
|
|
7320
|
-
selectionPaths
|
|
7372
|
+
selectionSpecified: selectionSpecifiedAugmented,
|
|
7373
|
+
selectionPaths: selectionPathsAugmented
|
|
7321
7374
|
});
|
|
7322
7375
|
const { shouldRunJest } = jestDecision;
|
|
7323
7376
|
const jestCount = effectiveJestFiles.length;
|
|
@@ -7335,45 +7388,63 @@ var program = async () => {
|
|
|
7335
7388
|
}
|
|
7336
7389
|
console.info(`Run plan \u2192 Jest maybe=${shouldRunJest} (projects=${projectConfigs.length})`);
|
|
7337
7390
|
let jestExitCode = 0;
|
|
7391
|
+
const allBridgeJson = [];
|
|
7338
7392
|
const executedTestFilesSet = /* @__PURE__ */ new Set();
|
|
7339
7393
|
if (shouldRunJest) {
|
|
7340
7394
|
console.info("Starting Jest (no Vitest targets)\u2026");
|
|
7341
7395
|
await runJestBootstrap();
|
|
7342
7396
|
const jestRunArgs = selectionIncludesProdPaths ? stripPathTokens(jestArgs) : jestArgs;
|
|
7397
|
+
const sanitizedJestRunArgs = jestRunArgs.filter(
|
|
7398
|
+
(arg) => !/^--coverageDirectory(?:=|$)/.test(String(arg))
|
|
7399
|
+
);
|
|
7343
7400
|
const projectsToRun = projectConfigs.filter(
|
|
7344
7401
|
(cfg) => (perProjectFiltered.get(cfg) ?? []).length > 0
|
|
7345
7402
|
);
|
|
7346
|
-
const totalProjectsToRun = projectsToRun.length;
|
|
7347
7403
|
const stripFooter = (text) => {
|
|
7348
7404
|
const lines = text.split("\n");
|
|
7349
7405
|
const idx = lines.findIndex((ln) => /^Test Files\s/.test(stripAnsiSimple(ln)));
|
|
7350
7406
|
return idx >= 0 ? lines.slice(0, idx).join("\n").trimEnd() : text;
|
|
7351
7407
|
};
|
|
7408
|
+
const prodSeedsForRun = (() => {
|
|
7409
|
+
const changedAbs = (changedSelectionAbs ?? []).map(
|
|
7410
|
+
(absPath) => path10.resolve(absPath).replace(/\\/g, "/")
|
|
7411
|
+
);
|
|
7412
|
+
const selAbs = selectionPathsAugmented.map(
|
|
7413
|
+
(pathToken) => path10.resolve(pathToken).replace(/\\/g, "/")
|
|
7414
|
+
);
|
|
7415
|
+
return (changedAbs.length ? changedAbs : selAbs).filter(
|
|
7416
|
+
(abs) => /[\\/]/.test(abs) && !/(^|\/)tests?\//i.test(abs) && !/\.(test|spec)\.[tj]sx?$/i.test(abs)
|
|
7417
|
+
);
|
|
7418
|
+
})();
|
|
7419
|
+
const repoRootForRank = repoRootForDiscovery;
|
|
7420
|
+
const fileRank = await computeDirectnessRank({
|
|
7421
|
+
repoRoot: repoRootForRank,
|
|
7422
|
+
productionSeeds: prodSeedsForRun
|
|
7423
|
+
});
|
|
7352
7424
|
for (let projIndex = 0; projIndex < projectsToRun.length; projIndex += 1) {
|
|
7353
7425
|
const cfg = projectsToRun[projIndex];
|
|
7354
|
-
const isLastProject = projIndex === totalProjectsToRun - 1;
|
|
7355
7426
|
const files = perProjectFiltered.get(cfg) ?? [];
|
|
7356
7427
|
if (files.length === 0) {
|
|
7357
|
-
console.info(`Project ${
|
|
7428
|
+
console.info(`Project ${path10.basename(cfg)}: 0 matching tests after filter; skipping.`);
|
|
7358
7429
|
continue;
|
|
7359
7430
|
}
|
|
7360
7431
|
files.forEach(
|
|
7361
|
-
(absTestPath) => executedTestFilesSet.add(
|
|
7432
|
+
(absTestPath) => executedTestFilesSet.add(path10.resolve(absTestPath).replace(/\\/g, "/"))
|
|
7362
7433
|
);
|
|
7363
|
-
const outJson =
|
|
7434
|
+
const outJson = path10.join(
|
|
7364
7435
|
os2.tmpdir(),
|
|
7365
7436
|
`jest-bridge-${Date.now()}-${Math.random().toString(36).slice(2)}.json`
|
|
7366
7437
|
);
|
|
7367
|
-
const reporterPath =
|
|
7438
|
+
const reporterPath = path10.resolve("scripts/jest-vitest-bridge.cjs");
|
|
7368
7439
|
try {
|
|
7369
7440
|
if (!fsSync3.existsSync(reporterPath)) {
|
|
7370
|
-
fsSync3.mkdirSync(
|
|
7441
|
+
fsSync3.mkdirSync(path10.dirname(reporterPath), { recursive: true });
|
|
7371
7442
|
fsSync3.writeFileSync(reporterPath, JEST_BRIDGE_REPORTER_SOURCE, "utf8");
|
|
7372
7443
|
}
|
|
7373
7444
|
} catch (ensureReporterError) {
|
|
7374
7445
|
console.warn(`Unable to ensure jest bridge reporter: ${String(ensureReporterError)}`);
|
|
7375
7446
|
}
|
|
7376
|
-
const selectedFilesForCoverage =
|
|
7447
|
+
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}`);
|
|
7377
7448
|
const coverageFromArgs = [];
|
|
7378
7449
|
for (const relPath of selectedFilesForCoverage) {
|
|
7379
7450
|
coverageFromArgs.push("--collectCoverageFrom", relPath);
|
|
@@ -7387,14 +7458,17 @@ var program = async () => {
|
|
|
7387
7458
|
"--config",
|
|
7388
7459
|
cfg,
|
|
7389
7460
|
"--runTestsByPath",
|
|
7390
|
-
|
|
7391
|
-
reporterPath,
|
|
7461
|
+
`--reporters=${reporterPath}`,
|
|
7392
7462
|
"--silent",
|
|
7393
7463
|
"--colors",
|
|
7394
7464
|
"--json",
|
|
7395
7465
|
"--outputFile",
|
|
7396
7466
|
outJson,
|
|
7397
|
-
...
|
|
7467
|
+
...sanitizedJestRunArgs,
|
|
7468
|
+
...collectCoverage ? [
|
|
7469
|
+
"--coverageDirectory",
|
|
7470
|
+
path10.join("coverage", "jest", path10.basename(cfg).replace(/[^a-zA-Z0-9_.-]+/g, "_"))
|
|
7471
|
+
] : [],
|
|
7398
7472
|
...coverageFromArgs,
|
|
7399
7473
|
"--passWithNoTests",
|
|
7400
7474
|
...files
|
|
@@ -7420,10 +7494,22 @@ var program = async () => {
|
|
|
7420
7494
|
const jsonText = fsSync3.readFileSync(outJson, "utf8");
|
|
7421
7495
|
const parsed = JSON.parse(jsonText);
|
|
7422
7496
|
const bridge = coerceJestJsonToBridge(parsed);
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
|
|
7426
|
-
|
|
7497
|
+
allBridgeJson.push(bridge);
|
|
7498
|
+
try {
|
|
7499
|
+
const reordered = {
|
|
7500
|
+
...bridge,
|
|
7501
|
+
testResults: sortTestResultsWithRank(fileRank, bridge.testResults).reverse()
|
|
7502
|
+
};
|
|
7503
|
+
pretty = renderVitestFromJestJSON(reordered, {
|
|
7504
|
+
cwd: repoRootForDiscovery,
|
|
7505
|
+
...editorCmd !== void 0 ? { editorCmd } : {}
|
|
7506
|
+
});
|
|
7507
|
+
} catch {
|
|
7508
|
+
pretty = renderVitestFromJestJSON(bridge, {
|
|
7509
|
+
cwd: repoRootForDiscovery,
|
|
7510
|
+
...editorCmd !== void 0 ? { editorCmd } : {}
|
|
7511
|
+
});
|
|
7512
|
+
}
|
|
7427
7513
|
if (debug) {
|
|
7428
7514
|
const preview = pretty.split("\n").slice(0, 3).join("\n");
|
|
7429
7515
|
console.info(`pretty preview (json):
|
|
@@ -7447,9 +7533,7 @@ ${preview}${pretty.includes("\n") ? "\n\u2026" : ""}`);
|
|
|
7447
7533
|
${preview}${pretty.includes("\n") ? "\n\u2026" : ""}`);
|
|
7448
7534
|
}
|
|
7449
7535
|
}
|
|
7450
|
-
|
|
7451
|
-
pretty = stripFooter(pretty);
|
|
7452
|
-
}
|
|
7536
|
+
pretty = stripFooter(pretty);
|
|
7453
7537
|
if (pretty.trim().length > 0) {
|
|
7454
7538
|
process.stdout.write(pretty.endsWith("\n") ? pretty : `${pretty}
|
|
7455
7539
|
`);
|
|
@@ -7461,15 +7545,69 @@ ${preview}${pretty.includes("\n") ? "\n\u2026" : ""}`);
|
|
|
7461
7545
|
} else {
|
|
7462
7546
|
console.info("Jest run skipped based on selection and thresholds.");
|
|
7463
7547
|
}
|
|
7464
|
-
if (
|
|
7465
|
-
|
|
7548
|
+
if (allBridgeJson.length > 0) {
|
|
7549
|
+
const agg = allBridgeJson.map((bridge) => bridge.aggregated);
|
|
7550
|
+
const sum = (select) => agg.reduce((total, item) => total + (select(item) || 0), 0);
|
|
7551
|
+
const startTime = Math.min(
|
|
7552
|
+
...allBridgeJson.map((bridge) => Number(bridge.startTime || Date.now()))
|
|
7553
|
+
);
|
|
7554
|
+
const unified = {
|
|
7555
|
+
startTime,
|
|
7556
|
+
testResults: allBridgeJson.flatMap((bridge) => bridge.testResults),
|
|
7557
|
+
aggregated: {
|
|
7558
|
+
numTotalTestSuites: sum((item) => item.numTotalTestSuites),
|
|
7559
|
+
numPassedTestSuites: sum((item) => item.numPassedTestSuites),
|
|
7560
|
+
numFailedTestSuites: sum((item) => item.numFailedTestSuites),
|
|
7561
|
+
numTotalTests: sum((item) => item.numTotalTests),
|
|
7562
|
+
numPassedTests: sum((item) => item.numPassedTests),
|
|
7563
|
+
numFailedTests: sum((item) => item.numFailedTests),
|
|
7564
|
+
numPendingTests: sum((item) => item.numPendingTests),
|
|
7565
|
+
numTodoTests: sum((item) => item.numTodoTests),
|
|
7566
|
+
startTime,
|
|
7567
|
+
success: agg.every((item) => Boolean(item.success)),
|
|
7568
|
+
runTimeMs: sum((item) => Number(item.runTimeMs ?? 0))
|
|
7569
|
+
}
|
|
7570
|
+
};
|
|
7571
|
+
try {
|
|
7572
|
+
const prodSeeds = (() => {
|
|
7573
|
+
const changedAbs = (changedSelectionAbs ?? []).map(
|
|
7574
|
+
(absPath) => path10.resolve(absPath).replace(/\\/g, "/")
|
|
7575
|
+
);
|
|
7576
|
+
const selAbs = selectionPathsAugmented.map(
|
|
7577
|
+
(pathToken) => path10.resolve(pathToken).replace(/\\/g, "/")
|
|
7578
|
+
);
|
|
7579
|
+
return (changedAbs.length ? changedAbs : selAbs).filter(
|
|
7580
|
+
(abs) => /[\\/]/.test(abs) && !/(^|\/)tests?\//i.test(abs) && !/\.(test|spec)\.[tj]sx?$/i.test(abs)
|
|
7581
|
+
);
|
|
7582
|
+
})();
|
|
7583
|
+
const unifiedRank = await computeDirectnessRank({
|
|
7584
|
+
repoRoot: repoRootForDiscovery,
|
|
7585
|
+
productionSeeds: prodSeeds
|
|
7586
|
+
});
|
|
7587
|
+
const ordered = sortTestResultsWithRank(unifiedRank, unified.testResults).reverse();
|
|
7588
|
+
unified.testResults = ordered;
|
|
7589
|
+
} catch {
|
|
7590
|
+
}
|
|
7591
|
+
const text = renderVitestFromJestJSON(unified, {
|
|
7592
|
+
cwd: repoRootForDiscovery,
|
|
7593
|
+
...editorCmd !== void 0 ? { editorCmd } : {}
|
|
7594
|
+
});
|
|
7595
|
+
if (text.trim().length > 0) {
|
|
7596
|
+
process.stdout.write(text.endsWith("\n") ? text : `${text}
|
|
7597
|
+
`);
|
|
7598
|
+
}
|
|
7599
|
+
}
|
|
7600
|
+
const finalExitCode = jestExitCode;
|
|
7601
|
+
if (collectCoverage && shouldRunJest && coverageAbortOnFailure && finalExitCode !== 0) {
|
|
7602
|
+
process.exit(finalExitCode);
|
|
7603
|
+
return;
|
|
7466
7604
|
}
|
|
7467
7605
|
if (collectCoverage && shouldRunJest) {
|
|
7468
7606
|
await mergeLcov();
|
|
7469
7607
|
const repoRoot = workspaceRoot ?? await findRepoRoot();
|
|
7470
7608
|
const mergedOptsBase = {
|
|
7471
|
-
selectionSpecified,
|
|
7472
|
-
selectionPaths,
|
|
7609
|
+
selectionSpecified: selectionSpecifiedAugmented,
|
|
7610
|
+
selectionPaths: selectionPathsAugmented,
|
|
7473
7611
|
includeGlobs,
|
|
7474
7612
|
excludeGlobs,
|
|
7475
7613
|
workspaceRoot: repoRoot,
|
|
@@ -7484,7 +7622,6 @@ ${preview}${pretty.includes("\n") ? "\n\u2026" : ""}`);
|
|
|
7484
7622
|
};
|
|
7485
7623
|
await emitMergedCoverage(coverageUi, mergedOptsBase);
|
|
7486
7624
|
}
|
|
7487
|
-
const finalExitCode = jestExitCode;
|
|
7488
7625
|
process.exit(finalExitCode);
|
|
7489
7626
|
};
|
|
7490
7627
|
export {
|