headlamp 0.1.6 → 0.1.9
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 +47 -2
- package/dist/cli.cjs +432 -264
- package/dist/cli.cjs.map +4 -4
- package/dist/index.js +436 -265
- 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/cli.cjs
CHANGED
|
@@ -93,7 +93,7 @@ var init_TimeoutError = __esm({
|
|
|
93
93
|
|
|
94
94
|
// node_modules/es-toolkit/dist/promise/delay.mjs
|
|
95
95
|
function delay(ms, { signal } = {}) {
|
|
96
|
-
return new Promise((
|
|
96
|
+
return new Promise((resolve9, reject) => {
|
|
97
97
|
const abortError = () => {
|
|
98
98
|
reject(new AbortError());
|
|
99
99
|
};
|
|
@@ -106,7 +106,7 @@ function delay(ms, { signal } = {}) {
|
|
|
106
106
|
}
|
|
107
107
|
const timeoutId = setTimeout(() => {
|
|
108
108
|
signal?.removeEventListener("abort", abortHandler);
|
|
109
|
-
|
|
109
|
+
resolve9();
|
|
110
110
|
}, ms);
|
|
111
111
|
signal?.addEventListener("abort", abortHandler, { once: true });
|
|
112
112
|
});
|
|
@@ -171,11 +171,11 @@ var init_exec = __esm({
|
|
|
171
171
|
child.stderr?.on("data", (chunk) => {
|
|
172
172
|
stderr += String(chunk);
|
|
173
173
|
});
|
|
174
|
-
const exec = new Promise((
|
|
174
|
+
const exec = new Promise((resolve9, reject) => {
|
|
175
175
|
child.on("error", reject);
|
|
176
176
|
child.on(
|
|
177
177
|
"close",
|
|
178
|
-
(code) => Number(code) === 0 ?
|
|
178
|
+
(code) => Number(code) === 0 ? resolve9(stdout) : reject(new Error(stderr || `exit ${code}`))
|
|
179
179
|
);
|
|
180
180
|
});
|
|
181
181
|
try {
|
|
@@ -195,7 +195,7 @@ var init_exec = __esm({
|
|
|
195
195
|
throw caughtError;
|
|
196
196
|
}
|
|
197
197
|
};
|
|
198
|
-
runExitCode = async (cmd, args, opts = {}) => new Promise((
|
|
198
|
+
runExitCode = async (cmd, args, opts = {}) => new Promise((resolve9, reject) => {
|
|
199
199
|
const child = (0, import_node_child_process.spawn)(cmd, [...args], {
|
|
200
200
|
cwd: opts.cwd,
|
|
201
201
|
env: opts.env,
|
|
@@ -204,9 +204,9 @@ var init_exec = __esm({
|
|
|
204
204
|
windowsHide: true
|
|
205
205
|
});
|
|
206
206
|
child.on("error", reject);
|
|
207
|
-
child.on("close", (code) =>
|
|
207
|
+
child.on("close", (code) => resolve9(Number(code)));
|
|
208
208
|
});
|
|
209
|
-
runWithCapture = async (cmd, args, opts) => new Promise((
|
|
209
|
+
runWithCapture = async (cmd, args, opts) => new Promise((resolve9, reject) => {
|
|
210
210
|
const child = (0, import_node_child_process.spawn)(cmd, [...args], {
|
|
211
211
|
cwd: opts.cwd,
|
|
212
212
|
env: opts.env,
|
|
@@ -222,7 +222,7 @@ var init_exec = __esm({
|
|
|
222
222
|
buf += String(chunk);
|
|
223
223
|
});
|
|
224
224
|
child.on("error", reject);
|
|
225
|
-
child.on("close", (code) =>
|
|
225
|
+
child.on("close", (code) => resolve9({ code: Number(code), output: buf }));
|
|
226
226
|
});
|
|
227
227
|
}
|
|
228
228
|
});
|
|
@@ -248,6 +248,7 @@ var init_args = __esm({
|
|
|
248
248
|
coverage: (coverageValue) => ({ type: "coverage", coverageValue }),
|
|
249
249
|
coverageUi: (value) => ({ type: "coverageUi", value }),
|
|
250
250
|
coverageAbortOnFailure: (value) => ({ type: "coverageAbortOnFailure", value }),
|
|
251
|
+
onlyFailures: (value) => ({ type: "onlyFailures", value }),
|
|
251
252
|
jestArg: (value) => ({ type: "jestArg", value }),
|
|
252
253
|
jestArgs: (values) => ({ type: "jestArgs", values }),
|
|
253
254
|
vitestArg: (value) => ({ type: "vitestArg", value }),
|
|
@@ -263,7 +264,8 @@ var init_args = __esm({
|
|
|
263
264
|
coverageMode: (value) => ({ type: "coverageMode", value }),
|
|
264
265
|
coverageMaxFiles: (value) => ({ type: "coverageMaxFiles", value }),
|
|
265
266
|
coverageMaxHotspots: (value) => ({ type: "coverageMaxHotspots", value }),
|
|
266
|
-
coveragePageFit: (value) => ({ type: "coveragePageFit", value })
|
|
267
|
+
coveragePageFit: (value) => ({ type: "coveragePageFit", value }),
|
|
268
|
+
changed: (value) => ({ type: "changed", value })
|
|
267
269
|
};
|
|
268
270
|
Some = (value) => ({ _tag: "some", value });
|
|
269
271
|
None = { _tag: "none" };
|
|
@@ -400,6 +402,18 @@ var init_args = __esm({
|
|
|
400
402
|
"--coverage.pageFit",
|
|
401
403
|
(_flag, lookahead) => step([ActionBuilders.coveragePageFit(isTruthy(String(lookahead)))], true)
|
|
402
404
|
),
|
|
405
|
+
// --onlyFailures flag (boolean)
|
|
406
|
+
rule.eq("--onlyFailures", () => step([ActionBuilders.onlyFailures(true)])),
|
|
407
|
+
rule.startsWith(
|
|
408
|
+
"--onlyFailures=",
|
|
409
|
+
(value) => step([
|
|
410
|
+
ActionBuilders.onlyFailures(isTruthy((value.split("=")[1] ?? "").trim().toLowerCase()))
|
|
411
|
+
])
|
|
412
|
+
),
|
|
413
|
+
rule.withLookahead(
|
|
414
|
+
"--onlyFailures",
|
|
415
|
+
(_flag, lookahead) => step([ActionBuilders.onlyFailures(isTruthy(String(lookahead)))], true)
|
|
416
|
+
),
|
|
403
417
|
rule.withLookahead(
|
|
404
418
|
"--testPathPattern",
|
|
405
419
|
(flag, lookahead) => step([ActionBuilders.jestArgs([flag, lookahead])], true)
|
|
@@ -460,6 +474,18 @@ var init_args = __esm({
|
|
|
460
474
|
"--coverage.root=",
|
|
461
475
|
(value) => step([ActionBuilders.coverageRoot((value.split("=")[1] ?? "").trim())])
|
|
462
476
|
),
|
|
477
|
+
// --changed flag: selects changed files via git (all|staged|unstaged)
|
|
478
|
+
rule.eq("--changed", () => step([ActionBuilders.changed("all")])),
|
|
479
|
+
rule.startsWith("--changed=", (value) => {
|
|
480
|
+
const raw = (value.split("=")[1] ?? "").trim().toLowerCase();
|
|
481
|
+
const mode = raw === "staged" ? "staged" : raw === "unstaged" ? "unstaged" : "all";
|
|
482
|
+
return step([ActionBuilders.changed(mode)]);
|
|
483
|
+
}),
|
|
484
|
+
rule.withLookahead("--changed", (_flag, lookahead) => {
|
|
485
|
+
const raw = String(lookahead).trim().toLowerCase();
|
|
486
|
+
const mode = raw === "staged" ? "staged" : raw === "unstaged" ? "unstaged" : "all";
|
|
487
|
+
return step([ActionBuilders.changed(mode)], true);
|
|
488
|
+
}),
|
|
463
489
|
rule.withLookahead(
|
|
464
490
|
"-t",
|
|
465
491
|
(flag, lookahead) => step(
|
|
@@ -534,6 +560,8 @@ var init_args = __esm({
|
|
|
534
560
|
return { vitest: [], jest: [], coverage: false, coverageUi: action.value };
|
|
535
561
|
case "coverageAbortOnFailure":
|
|
536
562
|
return { vitest: [], jest: [], coverage: false, coverageAbortOnFailure: action.value };
|
|
563
|
+
case "onlyFailures":
|
|
564
|
+
return { vitest: [], jest: [], coverage: false, onlyFailures: action.value };
|
|
537
565
|
case "jestArgs":
|
|
538
566
|
return { vitest: [], jest: action.values, coverage: false };
|
|
539
567
|
case "selectionHint":
|
|
@@ -562,6 +590,8 @@ var init_args = __esm({
|
|
|
562
590
|
return { vitest: [], jest: [], coverage: false, coverageMaxHotspots: action.value };
|
|
563
591
|
case "coveragePageFit":
|
|
564
592
|
return { vitest: [], jest: [], coverage: false, coveragePageFit: action.value };
|
|
593
|
+
case "changed":
|
|
594
|
+
return { vitest: [], jest: [], coverage: false, changed: action.value };
|
|
565
595
|
case "jestArg":
|
|
566
596
|
return { vitest: [], jest: [action.value], coverage: false };
|
|
567
597
|
case "vitestArg":
|
|
@@ -601,7 +631,9 @@ var init_args = __esm({
|
|
|
601
631
|
}
|
|
602
632
|
return {
|
|
603
633
|
...next,
|
|
634
|
+
...right.changed !== void 0 || left.changed !== void 0 ? { changed: right.changed ?? left.changed } : {},
|
|
604
635
|
...right.coverageAbortOnFailure !== void 0 || left.coverageAbortOnFailure !== void 0 ? { coverageAbortOnFailure: right.coverageAbortOnFailure ?? left.coverageAbortOnFailure } : {},
|
|
636
|
+
...right.onlyFailures !== void 0 || left.onlyFailures !== void 0 ? { onlyFailures: right.onlyFailures ?? left.onlyFailures } : {},
|
|
605
637
|
...right.coverageDetail !== void 0 || left.coverageDetail !== void 0 ? { coverageDetail: right.coverageDetail ?? left.coverageDetail } : {},
|
|
606
638
|
...right.coverageShowCode !== void 0 || left.coverageShowCode !== void 0 ? { coverageShowCode: right.coverageShowCode ?? left.coverageShowCode } : {},
|
|
607
639
|
...right.coverageMode !== void 0 || left.coverageMode !== void 0 ? { coverageMode: right.coverageMode ?? left.coverageMode } : {},
|
|
@@ -625,6 +657,7 @@ var init_args = __esm({
|
|
|
625
657
|
let collectCoverage = false;
|
|
626
658
|
let coverageUi = "both";
|
|
627
659
|
let coverageAbortOnFailure = false;
|
|
660
|
+
let onlyFailures = false;
|
|
628
661
|
let coverageShowCode = Boolean(process.stdout.isTTY);
|
|
629
662
|
let coverageMode = "auto";
|
|
630
663
|
const coverageMaxFilesLocalInit = void 0;
|
|
@@ -642,6 +675,7 @@ var init_args = __esm({
|
|
|
642
675
|
collectCoverage ||= contrib.coverage;
|
|
643
676
|
coverageUi = contrib.coverageUi ?? coverageUi;
|
|
644
677
|
coverageAbortOnFailure = contrib.coverageAbortOnFailure ?? coverageAbortOnFailure;
|
|
678
|
+
onlyFailures = contrib.onlyFailures ?? onlyFailures;
|
|
645
679
|
coverageShowCode = contrib.coverageShowCode ?? coverageShowCode;
|
|
646
680
|
const coverageDetailComputed = contrib.coverageDetail ?? (contrib.selection ? "auto" : void 0);
|
|
647
681
|
coverageMode = contrib.coverageMode ?? (contrib.selection ? "compact" : "auto");
|
|
@@ -675,6 +709,7 @@ var init_args = __esm({
|
|
|
675
709
|
collectCoverage,
|
|
676
710
|
coverageUi,
|
|
677
711
|
coverageAbortOnFailure,
|
|
712
|
+
onlyFailures,
|
|
678
713
|
selectionSpecified: Boolean(contrib.selection),
|
|
679
714
|
selectionPaths: [...contrib.selectionPaths ?? []],
|
|
680
715
|
includeGlobs,
|
|
@@ -686,7 +721,8 @@ var init_args = __esm({
|
|
|
686
721
|
...coverageMaxHotspotsLocal !== void 0 ? { coverageMaxHotspots: coverageMaxHotspotsLocal } : {},
|
|
687
722
|
coveragePageFit,
|
|
688
723
|
...contrib.editorCmd !== void 0 ? { editorCmd: contrib.editorCmd } : {},
|
|
689
|
-
...contrib.workspaceRoot !== void 0 ? { workspaceRoot: contrib.workspaceRoot } : {}
|
|
724
|
+
...contrib.workspaceRoot !== void 0 ? { workspaceRoot: contrib.workspaceRoot } : {},
|
|
725
|
+
...contrib.changed !== void 0 ? { changed: contrib.changed } : {}
|
|
690
726
|
};
|
|
691
727
|
return out;
|
|
692
728
|
};
|
|
@@ -1960,7 +1996,7 @@ var require_lib = __commonJS({
|
|
|
1960
1996
|
});
|
|
1961
1997
|
|
|
1962
1998
|
// src/lib/program.ts
|
|
1963
|
-
var
|
|
1999
|
+
var path10 = __toESM(require("node:path"), 1);
|
|
1964
2000
|
var os2 = __toESM(require("node:os"), 1);
|
|
1965
2001
|
var fsSync3 = __toESM(require("node:fs"), 1);
|
|
1966
2002
|
var fs5 = __toESM(require("node:fs/promises"), 1);
|
|
@@ -2921,7 +2957,7 @@ var compositeBarPct = (summary, hotspots) => {
|
|
|
2921
2957
|
};
|
|
2922
2958
|
|
|
2923
2959
|
// src/lib/coverage-print.ts
|
|
2924
|
-
var
|
|
2960
|
+
var path8 = __toESM(require("node:path"), 1);
|
|
2925
2961
|
var fsSync2 = __toESM(require("node:fs"), 1);
|
|
2926
2962
|
init_env_utils();
|
|
2927
2963
|
init_exec();
|
|
@@ -3091,6 +3127,71 @@ var renderTable = (columns, rows) => {
|
|
|
3091
3127
|
};
|
|
3092
3128
|
var barCell = (pct) => (padded) => bar(pct, padded.length);
|
|
3093
3129
|
|
|
3130
|
+
// src/lib/relevance.ts
|
|
3131
|
+
var path7 = __toESM(require("node:path"), 1);
|
|
3132
|
+
init_args();
|
|
3133
|
+
init_fast_related();
|
|
3134
|
+
var normalizeAbs = (inputPath) => path7.resolve(inputPath).replace(/\\/g, "/");
|
|
3135
|
+
var compareBooleanDesc = (left, right) => {
|
|
3136
|
+
if (left === right) {
|
|
3137
|
+
return 0;
|
|
3138
|
+
}
|
|
3139
|
+
return right ? 1 : -1;
|
|
3140
|
+
};
|
|
3141
|
+
var compareNumberAsc = (left, right) => left - right;
|
|
3142
|
+
var compareStringAsc = (left, right) => left.localeCompare(right);
|
|
3143
|
+
var fileFailed = (file) => Boolean(
|
|
3144
|
+
(file.status ?? "") === "failed" || (file.testResults ?? []).some((assertion) => (assertion.status ?? "") === "failed")
|
|
3145
|
+
);
|
|
3146
|
+
var composeComparators = (...comparators) => (left, right) => {
|
|
3147
|
+
for (const cmp of comparators) {
|
|
3148
|
+
const result = cmp(left, right);
|
|
3149
|
+
if (result !== 0) {
|
|
3150
|
+
return result;
|
|
3151
|
+
}
|
|
3152
|
+
}
|
|
3153
|
+
return 0;
|
|
3154
|
+
};
|
|
3155
|
+
var comparatorForRank = (rankByPath) => {
|
|
3156
|
+
const rankOrInf = (absPath) => rankByPath.has(absPath) ? rankByPath.get(absPath) : Number.POSITIVE_INFINITY;
|
|
3157
|
+
return composeComparators(
|
|
3158
|
+
(left, right) => compareBooleanDesc(fileFailed(left), fileFailed(right)),
|
|
3159
|
+
(left, right) => compareNumberAsc(
|
|
3160
|
+
rankOrInf(normalizeAbs(left.testFilePath)),
|
|
3161
|
+
rankOrInf(normalizeAbs(right.testFilePath))
|
|
3162
|
+
),
|
|
3163
|
+
(left, right) => compareStringAsc(normalizeAbs(left.testFilePath), normalizeAbs(right.testFilePath))
|
|
3164
|
+
);
|
|
3165
|
+
};
|
|
3166
|
+
var computeDirectnessRank = async (opts) => {
|
|
3167
|
+
const selectionKey = opts.productionSeeds.map((abs) => path7.relative(opts.repoRoot, abs).replace(/\\/g, "/")).sort((left, right) => left.localeCompare(right)).join("|");
|
|
3168
|
+
const related = await cachedRelated({
|
|
3169
|
+
repoRoot: opts.repoRoot,
|
|
3170
|
+
selectionKey,
|
|
3171
|
+
compute: () => findRelatedTestsFast({
|
|
3172
|
+
repoRoot: opts.repoRoot,
|
|
3173
|
+
productionPaths: opts.productionSeeds,
|
|
3174
|
+
testGlobs: DEFAULT_TEST_GLOBS,
|
|
3175
|
+
excludeGlobs: opts.excludeGlobs ?? DEFAULT_EXCLUDE,
|
|
3176
|
+
timeoutMs: 1500
|
|
3177
|
+
})
|
|
3178
|
+
});
|
|
3179
|
+
const out = /* @__PURE__ */ new Map();
|
|
3180
|
+
related.forEach((abs, index) => {
|
|
3181
|
+
out.set(normalizeAbs(abs), index);
|
|
3182
|
+
});
|
|
3183
|
+
return out;
|
|
3184
|
+
};
|
|
3185
|
+
var sortTestResultsWithRank = (rankByPath, results) => results.slice().sort(comparatorForRank(rankByPath));
|
|
3186
|
+
var comparatorForPathRank = (rankByPath) => {
|
|
3187
|
+
const rankOrInf = (absPath) => rankByPath.has(absPath) ? rankByPath.get(absPath) : Number.POSITIVE_INFINITY;
|
|
3188
|
+
return composeComparators(
|
|
3189
|
+
(left, right) => compareNumberAsc(rankOrInf(normalizeAbs(left)), rankOrInf(normalizeAbs(right))),
|
|
3190
|
+
(left, right) => compareStringAsc(normalizeAbs(left), normalizeAbs(right))
|
|
3191
|
+
);
|
|
3192
|
+
};
|
|
3193
|
+
var sortPathsWithRank = (rankByPath, paths) => paths.slice().sort(comparatorForPathRank(rankByPath));
|
|
3194
|
+
|
|
3094
3195
|
// src/lib/coverage-print.ts
|
|
3095
3196
|
var printDetailedCoverage = async (opts) => {
|
|
3096
3197
|
const files = opts.map.files().sort((fileA, fileB) => {
|
|
@@ -3101,7 +3202,7 @@ var printDetailedCoverage = async (opts) => {
|
|
|
3101
3202
|
for (const abs of files) {
|
|
3102
3203
|
const fc = opts.map.fileCoverageFor(abs);
|
|
3103
3204
|
const sum = fc.toSummary();
|
|
3104
|
-
const rel =
|
|
3205
|
+
const rel = path8.relative(opts.root, abs).replace(/\\/g, "/");
|
|
3105
3206
|
const blocks = computeUncoveredBlocks(fc);
|
|
3106
3207
|
const misses = missedBranches(fc);
|
|
3107
3208
|
const missFns = missedFunctions(fc);
|
|
@@ -3110,9 +3211,9 @@ var printDetailedCoverage = async (opts) => {
|
|
|
3110
3211
|
const branchesPctText = `${sum.branches.pct.toFixed(1)}%`;
|
|
3111
3212
|
const header = `${ansi.bold(rel)} lines ${tintPct(sum.lines.pct)(
|
|
3112
3213
|
linesPctText
|
|
3113
|
-
)} ${barCell(compositeBarPct(sum, blocks))("".padEnd(14))} funcs ${tintPct(
|
|
3114
|
-
|
|
3115
|
-
)
|
|
3214
|
+
)} ${barCell(compositeBarPct(sum, blocks))("".padEnd(14))} funcs ${tintPct(sum.functions.pct)(
|
|
3215
|
+
funcsPctText
|
|
3216
|
+
)} branches ${tintPct(sum.branches.pct)(branchesPctText)}`;
|
|
3116
3217
|
console.info(header);
|
|
3117
3218
|
const max = opts.limitPerFile === "all" ? Number.POSITIVE_INFINITY : opts.limitPerFile ?? 5;
|
|
3118
3219
|
const compareRangesByLengthDescThenStart = (firstRange, secondRange) => {
|
|
@@ -3139,10 +3240,8 @@ var printDetailedCoverage = async (opts) => {
|
|
|
3139
3240
|
abs,
|
|
3140
3241
|
block.start,
|
|
3141
3242
|
opts.editorCmd
|
|
3142
|
-
)}\x07${
|
|
3143
|
-
const label = ` ${ansi.yellow(`L${block.start}`)}\u2013${ansi.yellow(
|
|
3144
|
-
`L${block.end}`
|
|
3145
|
-
)} ${link}`;
|
|
3243
|
+
)}\x07${path8.basename(abs)}:${block.start}\x1B]8;;\x07`;
|
|
3244
|
+
const label = ` ${ansi.yellow(`L${block.start}`)}\u2013${ansi.yellow(`L${block.end}`)} ${link}`;
|
|
3146
3245
|
console.info(label);
|
|
3147
3246
|
if (opts.showCode && src.length) {
|
|
3148
3247
|
const lines = src.split(/\r?\n/);
|
|
@@ -3162,7 +3261,7 @@ var printDetailedCoverage = async (opts) => {
|
|
|
3162
3261
|
abs,
|
|
3163
3262
|
fn.line,
|
|
3164
3263
|
opts.editorCmd
|
|
3165
|
-
)}\x07${
|
|
3264
|
+
)}\x07${path8.basename(abs)}:${fn.line}\x1B]8;;\x07`;
|
|
3166
3265
|
console.info(` - ${fn.name} @ ${link}`);
|
|
3167
3266
|
}
|
|
3168
3267
|
}
|
|
@@ -3173,12 +3272,8 @@ var printDetailedCoverage = async (opts) => {
|
|
|
3173
3272
|
abs,
|
|
3174
3273
|
br.line,
|
|
3175
3274
|
opts.editorCmd
|
|
3176
|
-
)}\x07${
|
|
3177
|
-
console.info(
|
|
3178
|
-
` - branch#${br.id} @ ${link} missed paths: [${br.zeroPaths.join(
|
|
3179
|
-
", "
|
|
3180
|
-
)}]`
|
|
3181
|
-
);
|
|
3275
|
+
)}\x07${path8.basename(abs)}:${br.line}\x1B]8;;\x07`;
|
|
3276
|
+
console.info(` - branch#${br.id} @ ${link} missed paths: [${br.zeroPaths.join(", ")}]`);
|
|
3182
3277
|
}
|
|
3183
3278
|
}
|
|
3184
3279
|
console.info("");
|
|
@@ -3198,7 +3293,7 @@ var printCompactCoverage = async (opts) => {
|
|
|
3198
3293
|
for (const abs of files.slice(0, fileCap)) {
|
|
3199
3294
|
const fc = opts.map.fileCoverageFor(abs);
|
|
3200
3295
|
const sum = fc.toSummary();
|
|
3201
|
-
const rel =
|
|
3296
|
+
const rel = path8.relative(opts.root, abs).replace(/\\/g, "/");
|
|
3202
3297
|
const compareRangesByLengthDescThenStart = (firstRange, secondRange) => {
|
|
3203
3298
|
const secondLength = secondRange.end - secondRange.start;
|
|
3204
3299
|
const firstLength = firstRange.end - firstRange.start;
|
|
@@ -3212,9 +3307,9 @@ var printCompactCoverage = async (opts) => {
|
|
|
3212
3307
|
const branchesPctText = `${sum.branches.pct.toFixed(1)}%`;
|
|
3213
3308
|
const header = `${ansi.bold(rel)} lines ${tintPct(sum.lines.pct)(
|
|
3214
3309
|
linesPctText
|
|
3215
|
-
)} ${barCell(compositeBarPct(sum, blocks))("".padEnd(14))} funcs ${tintPct(
|
|
3216
|
-
|
|
3217
|
-
)
|
|
3310
|
+
)} ${barCell(compositeBarPct(sum, blocks))("".padEnd(14))} funcs ${tintPct(sum.functions.pct)(
|
|
3311
|
+
funcsPctText
|
|
3312
|
+
)} branches ${tintPct(sum.branches.pct)(branchesPctText)}`;
|
|
3218
3313
|
console.info(header);
|
|
3219
3314
|
const hotspots = blocks.slice(0, maxHotspotsDerived);
|
|
3220
3315
|
if (hotspots.length) {
|
|
@@ -3225,10 +3320,8 @@ var printCompactCoverage = async (opts) => {
|
|
|
3225
3320
|
abs,
|
|
3226
3321
|
hotspot.start,
|
|
3227
3322
|
opts.editorCmd
|
|
3228
|
-
)}\x07${
|
|
3229
|
-
console.info(
|
|
3230
|
-
` - L${hotspot.start}\u2013L${hotspot.end} (${len} lines) ${link}`
|
|
3231
|
-
);
|
|
3323
|
+
)}\x07${path8.basename(abs)}:${hotspot.start}\x1B]8;;\x07`;
|
|
3324
|
+
console.info(` - L${hotspot.start}\u2013L${hotspot.end} (${len} lines) ${link}`);
|
|
3232
3325
|
}
|
|
3233
3326
|
}
|
|
3234
3327
|
const functionsList = missFns.slice(0, maxFunctionsDerived);
|
|
@@ -3240,7 +3333,7 @@ var printCompactCoverage = async (opts) => {
|
|
|
3240
3333
|
abs,
|
|
3241
3334
|
fn.line,
|
|
3242
3335
|
opts.editorCmd
|
|
3243
|
-
)}\x07${
|
|
3336
|
+
)}\x07${path8.basename(abs)}:${fn.line}\x1B]8;;\x07`
|
|
3244
3337
|
);
|
|
3245
3338
|
}
|
|
3246
3339
|
}
|
|
@@ -3255,7 +3348,7 @@ var printCompactCoverage = async (opts) => {
|
|
|
3255
3348
|
abs,
|
|
3256
3349
|
br.line,
|
|
3257
3350
|
opts.editorCmd
|
|
3258
|
-
)}\x07${
|
|
3351
|
+
)}\x07${path8.basename(abs)}:${br.line}\x1B]8;;\x07`
|
|
3259
3352
|
);
|
|
3260
3353
|
}
|
|
3261
3354
|
}
|
|
@@ -3264,9 +3357,7 @@ var printCompactCoverage = async (opts) => {
|
|
|
3264
3357
|
const restBrs = Math.max(0, misses.length - branchesList.length);
|
|
3265
3358
|
if (restHs + restFns + restBrs > 0) {
|
|
3266
3359
|
console.info(
|
|
3267
|
-
ansi.dim(
|
|
3268
|
-
` \u2026 truncated: +${restHs} hotspots, +${restFns} funcs, +${restBrs} branches`
|
|
3269
|
-
)
|
|
3360
|
+
ansi.dim(` \u2026 truncated: +${restHs} hotspots, +${restFns} funcs, +${restBrs} branches`)
|
|
3270
3361
|
);
|
|
3271
3362
|
}
|
|
3272
3363
|
console.info("");
|
|
@@ -3303,7 +3394,7 @@ var shortenPathPreservingFilename = (relPath, maxWidth, opts) => {
|
|
|
3303
3394
|
return { stem: base.slice(0, -ending.length), ext: ending };
|
|
3304
3395
|
}
|
|
3305
3396
|
}
|
|
3306
|
-
const ext2 =
|
|
3397
|
+
const ext2 = path8.extname(base);
|
|
3307
3398
|
return { stem: base.slice(0, -ext2.length), ext: ext2 };
|
|
3308
3399
|
};
|
|
3309
3400
|
const sliceBalanced = (input, width) => {
|
|
@@ -3386,12 +3477,7 @@ var shortenPathPreservingFilename = (relPath, maxWidth, opts) => {
|
|
|
3386
3477
|
const tailParts = tailSrc.map((segment) => segment);
|
|
3387
3478
|
let hidAny = false;
|
|
3388
3479
|
const build = () => {
|
|
3389
|
-
const label2 = joinParts(
|
|
3390
|
-
headParts,
|
|
3391
|
-
tailParts,
|
|
3392
|
-
hideMiddle2 || hidAny,
|
|
3393
|
-
baseLabel
|
|
3394
|
-
);
|
|
3480
|
+
const label2 = joinParts(headParts, tailParts, hideMiddle2 || hidAny, baseLabel);
|
|
3395
3481
|
return { label: label2, width: visibleWidth(label2) };
|
|
3396
3482
|
};
|
|
3397
3483
|
let { label, width } = build();
|
|
@@ -3484,13 +3570,7 @@ var shortenPathPreservingFilename = (relPath, maxWidth, opts) => {
|
|
|
3484
3570
|
return { headRaw: headRaw2, tailRaw: tailRaw2, hideMiddle: hideMiddle2 };
|
|
3485
3571
|
};
|
|
3486
3572
|
let { headRaw, tailRaw, hideMiddle } = buildRaw(headCount, tailCount);
|
|
3487
|
-
let candidate = tryTrimDirsToFit(
|
|
3488
|
-
headRaw,
|
|
3489
|
-
tailRaw,
|
|
3490
|
-
hideMiddle,
|
|
3491
|
-
baseFull,
|
|
3492
|
-
maxWidth
|
|
3493
|
-
);
|
|
3573
|
+
let candidate = tryTrimDirsToFit(headRaw, tailRaw, hideMiddle, baseFull, maxWidth);
|
|
3494
3574
|
if (!candidate) {
|
|
3495
3575
|
return baseFull;
|
|
3496
3576
|
}
|
|
@@ -3499,13 +3579,7 @@ var shortenPathPreservingFilename = (relPath, maxWidth, opts) => {
|
|
|
3499
3579
|
if (headCount + tailCount < total) {
|
|
3500
3580
|
const tryTail = Math.min(tailCount + 1, total - headCount);
|
|
3501
3581
|
({ headRaw, tailRaw, hideMiddle } = buildRaw(headCount, tryTail));
|
|
3502
|
-
const candTail = tryTrimDirsToFit(
|
|
3503
|
-
headRaw,
|
|
3504
|
-
tailRaw,
|
|
3505
|
-
hideMiddle,
|
|
3506
|
-
baseFull,
|
|
3507
|
-
maxWidth
|
|
3508
|
-
);
|
|
3582
|
+
const candTail = tryTrimDirsToFit(headRaw, tailRaw, hideMiddle, baseFull, maxWidth);
|
|
3509
3583
|
if (candTail) {
|
|
3510
3584
|
tailCount = tryTail;
|
|
3511
3585
|
candidate = candTail;
|
|
@@ -3515,13 +3589,7 @@ var shortenPathPreservingFilename = (relPath, maxWidth, opts) => {
|
|
|
3515
3589
|
if (!advanced && headCount + tailCount < total) {
|
|
3516
3590
|
const tryHead = Math.min(headCount + 1, total - tailCount);
|
|
3517
3591
|
({ headRaw, tailRaw, hideMiddle } = buildRaw(tryHead, tailCount));
|
|
3518
|
-
const candHead = tryTrimDirsToFit(
|
|
3519
|
-
headRaw,
|
|
3520
|
-
tailRaw,
|
|
3521
|
-
hideMiddle,
|
|
3522
|
-
baseFull,
|
|
3523
|
-
maxWidth
|
|
3524
|
-
);
|
|
3592
|
+
const candHead = tryTrimDirsToFit(headRaw, tailRaw, hideMiddle, baseFull, maxWidth);
|
|
3525
3593
|
if (candHead) {
|
|
3526
3594
|
headCount = tryHead;
|
|
3527
3595
|
candidate = candHead;
|
|
@@ -3583,7 +3651,7 @@ var buildDistanceMapFromTests = async (executedTestsAbs, rootDir) => {
|
|
|
3583
3651
|
const queue = [];
|
|
3584
3652
|
const seen = /* @__PURE__ */ new Set();
|
|
3585
3653
|
for (const testAbs of executedTestsAbs) {
|
|
3586
|
-
const testPathNormalized =
|
|
3654
|
+
const testPathNormalized = path8.resolve(testAbs).replace(/\\/g, "/");
|
|
3587
3655
|
dist.set(testPathNormalized, 0);
|
|
3588
3656
|
queue.push([testPathNormalized, 0]);
|
|
3589
3657
|
}
|
|
@@ -3602,12 +3670,7 @@ var buildDistanceMapFromTests = async (executedTestsAbs, rootDir) => {
|
|
|
3602
3670
|
const specs = await extractImportSpecs2(currentFile, specsCache);
|
|
3603
3671
|
const nextDistance = currentDistance + 1;
|
|
3604
3672
|
for (const spec of specs) {
|
|
3605
|
-
const resolved = resolveImportWithRoot(
|
|
3606
|
-
currentFile,
|
|
3607
|
-
spec,
|
|
3608
|
-
rootDir,
|
|
3609
|
-
resolutionCache
|
|
3610
|
-
);
|
|
3673
|
+
const resolved = resolveImportWithRoot(currentFile, spec, rootDir, resolutionCache);
|
|
3611
3674
|
const usable = resolved && !resolved.includes("/node_modules/");
|
|
3612
3675
|
if (usable) {
|
|
3613
3676
|
const existing = dist.get(resolved);
|
|
@@ -3622,13 +3685,10 @@ var buildDistanceMapFromTests = async (executedTestsAbs, rootDir) => {
|
|
|
3622
3685
|
return dist;
|
|
3623
3686
|
};
|
|
3624
3687
|
var renderPerFileCompositeTable = async (opts) => {
|
|
3625
|
-
const rel =
|
|
3688
|
+
const rel = path8.relative(opts.root, opts.absPath).replace(/\\/g, "/");
|
|
3626
3689
|
const sum = opts.file.toSummary();
|
|
3627
3690
|
const rowsAvail = typeof process.stdout.rows === "number" && process.stdout.rows > 10 ? process.stdout.rows : 40;
|
|
3628
|
-
const tableBudget = Math.max(
|
|
3629
|
-
14,
|
|
3630
|
-
Math.min(opts.maxRows ?? rowsAvail - 1, rowsAvail + 8)
|
|
3631
|
-
);
|
|
3691
|
+
const tableBudget = Math.max(14, Math.min(opts.maxRows ?? rowsAvail - 1, rowsAvail + 8));
|
|
3632
3692
|
const rowBudget = Math.max(6, tableBudget - 6);
|
|
3633
3693
|
const blocks = computeUncoveredBlocks(opts.file).slice().sort((firstRange, secondRange) => {
|
|
3634
3694
|
const firstLength = firstRange.end - firstRange.start;
|
|
@@ -3672,9 +3732,7 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
3672
3732
|
rows.push([
|
|
3673
3733
|
cell(
|
|
3674
3734
|
rel,
|
|
3675
|
-
(padded) => ansi.dim(
|
|
3676
|
-
shortenPathPreservingFilename(rel, padded.length).padEnd(padded.length)
|
|
3677
|
-
)
|
|
3735
|
+
(padded) => ansi.dim(shortenPathPreservingFilename(rel, padded.length).padEnd(padded.length))
|
|
3678
3736
|
),
|
|
3679
3737
|
cell("Totals", ansi.dim),
|
|
3680
3738
|
cell("\u2014", ansi.dim),
|
|
@@ -3693,11 +3751,7 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
3693
3751
|
rows.push([
|
|
3694
3752
|
cell(
|
|
3695
3753
|
rel,
|
|
3696
|
-
(padded) => ansi.dim(
|
|
3697
|
-
shortenPathPreservingFilename(rel, padded.length).padEnd(
|
|
3698
|
-
padded.length
|
|
3699
|
-
)
|
|
3700
|
-
)
|
|
3754
|
+
(padded) => ansi.dim(shortenPathPreservingFilename(rel, padded.length).padEnd(padded.length))
|
|
3701
3755
|
),
|
|
3702
3756
|
cell("Hotspots", ansi.dim),
|
|
3703
3757
|
cell("", ansi.dim),
|
|
@@ -3711,14 +3765,8 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
3711
3765
|
rows.push([
|
|
3712
3766
|
cell(rel, (padded) => {
|
|
3713
3767
|
const width = padded.length;
|
|
3714
|
-
const display = shortenPathPreservingFilename(rel, width).padEnd(
|
|
3715
|
-
|
|
3716
|
-
);
|
|
3717
|
-
return linkifyPadded(
|
|
3718
|
-
opts.absPath,
|
|
3719
|
-
hotspotRange.start,
|
|
3720
|
-
opts.editorCmd
|
|
3721
|
-
)(display);
|
|
3768
|
+
const display = shortenPathPreservingFilename(rel, width).padEnd(width);
|
|
3769
|
+
return linkifyPadded(opts.absPath, hotspotRange.start, opts.editorCmd)(display);
|
|
3722
3770
|
}),
|
|
3723
3771
|
cell("Hotspot"),
|
|
3724
3772
|
cell(`L${hotspotRange.start}\u2013L${hotspotRange.end}`),
|
|
@@ -3735,11 +3783,7 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
3735
3783
|
rows.push([
|
|
3736
3784
|
cell(
|
|
3737
3785
|
rel,
|
|
3738
|
-
(padded) => ansi.dim(
|
|
3739
|
-
shortenPathPreservingFilename(rel, padded.length).padEnd(
|
|
3740
|
-
padded.length
|
|
3741
|
-
)
|
|
3742
|
-
)
|
|
3786
|
+
(padded) => ansi.dim(shortenPathPreservingFilename(rel, padded.length).padEnd(padded.length))
|
|
3743
3787
|
),
|
|
3744
3788
|
cell("Functions", ansi.dim),
|
|
3745
3789
|
cell("", ansi.dim),
|
|
@@ -3753,14 +3797,8 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
3753
3797
|
rows.push([
|
|
3754
3798
|
cell(rel, (padded) => {
|
|
3755
3799
|
const width = padded.length;
|
|
3756
|
-
const display = shortenPathPreservingFilename(rel, width).padEnd(
|
|
3757
|
-
|
|
3758
|
-
);
|
|
3759
|
-
return linkifyPadded(
|
|
3760
|
-
opts.absPath,
|
|
3761
|
-
missedFunction.line,
|
|
3762
|
-
opts.editorCmd
|
|
3763
|
-
)(display);
|
|
3800
|
+
const display = shortenPathPreservingFilename(rel, width).padEnd(width);
|
|
3801
|
+
return linkifyPadded(opts.absPath, missedFunction.line, opts.editorCmd)(display);
|
|
3764
3802
|
}),
|
|
3765
3803
|
cell("Func"),
|
|
3766
3804
|
cell(`L${missedFunction.line}`),
|
|
@@ -3777,11 +3815,7 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
3777
3815
|
rows.push([
|
|
3778
3816
|
cell(
|
|
3779
3817
|
rel,
|
|
3780
|
-
(padded) => ansi.dim(
|
|
3781
|
-
shortenPathPreservingFilename(rel, padded.length).padEnd(
|
|
3782
|
-
padded.length
|
|
3783
|
-
)
|
|
3784
|
-
)
|
|
3818
|
+
(padded) => ansi.dim(shortenPathPreservingFilename(rel, padded.length).padEnd(padded.length))
|
|
3785
3819
|
),
|
|
3786
3820
|
cell("Branches", ansi.dim),
|
|
3787
3821
|
cell("", ansi.dim),
|
|
@@ -3795,14 +3829,8 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
3795
3829
|
rows.push([
|
|
3796
3830
|
cell(rel, (padded) => {
|
|
3797
3831
|
const width = padded.length;
|
|
3798
|
-
const display = shortenPathPreservingFilename(rel, width).padEnd(
|
|
3799
|
-
|
|
3800
|
-
);
|
|
3801
|
-
return linkifyPadded(
|
|
3802
|
-
opts.absPath,
|
|
3803
|
-
missedBranch.line,
|
|
3804
|
-
opts.editorCmd
|
|
3805
|
-
)(display);
|
|
3832
|
+
const display = shortenPathPreservingFilename(rel, width).padEnd(width);
|
|
3833
|
+
return linkifyPadded(opts.absPath, missedBranch.line, opts.editorCmd)(display);
|
|
3806
3834
|
}),
|
|
3807
3835
|
cell("Branch"),
|
|
3808
3836
|
cell(`L${missedBranch.line}`),
|
|
@@ -3810,9 +3838,7 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
3810
3838
|
cell(""),
|
|
3811
3839
|
cell(""),
|
|
3812
3840
|
cell(""),
|
|
3813
|
-
cell(
|
|
3814
|
-
`#${missedBranch.id} missed [${missedBranch.zeroPaths.join(", ")}]`
|
|
3815
|
-
)
|
|
3841
|
+
cell(`#${missedBranch.id} missed [${missedBranch.zeroPaths.join(", ")}]`)
|
|
3816
3842
|
]);
|
|
3817
3843
|
}
|
|
3818
3844
|
}
|
|
@@ -3832,9 +3858,7 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
3832
3858
|
rows.push([
|
|
3833
3859
|
cell(rel, (padded) => {
|
|
3834
3860
|
const width = padded.length;
|
|
3835
|
-
const display = shortenPathPreservingFilename(rel, width).padEnd(
|
|
3836
|
-
width
|
|
3837
|
-
);
|
|
3861
|
+
const display = shortenPathPreservingFilename(rel, width).padEnd(width);
|
|
3838
3862
|
return linkifyPadded(opts.absPath, ln, opts.editorCmd)(display);
|
|
3839
3863
|
}),
|
|
3840
3864
|
cell("Line"),
|
|
@@ -3847,16 +3871,7 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
3847
3871
|
]);
|
|
3848
3872
|
}
|
|
3849
3873
|
while (rows.length < target) {
|
|
3850
|
-
rows.push([
|
|
3851
|
-
cell(""),
|
|
3852
|
-
cell(""),
|
|
3853
|
-
cell(""),
|
|
3854
|
-
cell(""),
|
|
3855
|
-
cell(""),
|
|
3856
|
-
cell(""),
|
|
3857
|
-
cell(""),
|
|
3858
|
-
cell("")
|
|
3859
|
-
]);
|
|
3874
|
+
rows.push([cell(""), cell(""), cell(""), cell(""), cell(""), cell(""), cell(""), cell("")]);
|
|
3860
3875
|
}
|
|
3861
3876
|
}
|
|
3862
3877
|
}
|
|
@@ -3864,20 +3879,17 @@ var renderPerFileCompositeTable = async (opts) => {
|
|
|
3864
3879
|
console.info(table);
|
|
3865
3880
|
const sep = ansi.gray(
|
|
3866
3881
|
"\u2500".repeat(
|
|
3867
|
-
Math.max(
|
|
3868
|
-
20,
|
|
3869
|
-
typeof process.stdout.columns === "number" ? process.stdout.columns : 100
|
|
3870
|
-
)
|
|
3882
|
+
Math.max(20, typeof process.stdout.columns === "number" ? process.stdout.columns : 100)
|
|
3871
3883
|
)
|
|
3872
3884
|
);
|
|
3873
3885
|
console.info(sep);
|
|
3874
3886
|
};
|
|
3875
3887
|
var printPerFileCompositeTables = async (opts) => {
|
|
3876
3888
|
const selectionAbs = (opts.selectionPaths ?? []).map(
|
|
3877
|
-
(selPath) =>
|
|
3889
|
+
(selPath) => path8.resolve(selPath).replace(/\\/g, "/")
|
|
3878
3890
|
);
|
|
3879
3891
|
const changedAbs = (opts.changedFiles ?? []).map(
|
|
3880
|
-
(chgPath) =>
|
|
3892
|
+
(chgPath) => path8.resolve(chgPath).replace(/\\/g, "/")
|
|
3881
3893
|
);
|
|
3882
3894
|
const tokenizeForSimilarity = (filePathForTokens) => new Set(
|
|
3883
3895
|
filePathForTokens.toLowerCase().replace(/[^a-z0-9/_\-.]/g, " ").split(/[/_.-]+/).filter(Boolean)
|
|
@@ -3893,15 +3905,15 @@ var printPerFileCompositeTables = async (opts) => {
|
|
|
3893
3905
|
return intersectionCount / unionSize;
|
|
3894
3906
|
};
|
|
3895
3907
|
const isSameDirOrChild = (firstAbs, secondAbs) => {
|
|
3896
|
-
const dirA =
|
|
3897
|
-
const dirB =
|
|
3908
|
+
const dirA = path8.dirname(firstAbs).replace(/\\/g, "/");
|
|
3909
|
+
const dirB = path8.dirname(secondAbs).replace(/\\/g, "/");
|
|
3898
3910
|
return dirA === dirB || dirB.startsWith(`${dirA}/`) || dirA.startsWith(`${dirB}/`);
|
|
3899
3911
|
};
|
|
3900
3912
|
const selectionTokens = selectionAbs.map(tokenizeForSimilarity);
|
|
3901
3913
|
const changedTokens = changedAbs.map(tokenizeForSimilarity);
|
|
3902
|
-
const executedTestsAbs = (opts.executedTests ?? []).map((testPath) =>
|
|
3914
|
+
const executedTestsAbs = (opts.executedTests ?? []).map((testPath) => path8.resolve(testPath).replace(/\\/g, "/")).filter((absPath) => absPath.length > 0);
|
|
3903
3915
|
const testTokens = executedTestsAbs.map(tokenizeForSimilarity);
|
|
3904
|
-
const allMapFilesAbs = opts.map.files().map((absPath) =>
|
|
3916
|
+
const allMapFilesAbs = opts.map.files().map((absPath) => path8.resolve(absPath).replace(/\\/g, "/"));
|
|
3905
3917
|
const uncoveredCandidates = allMapFilesAbs.filter((absPath) => {
|
|
3906
3918
|
const sum = opts.map.fileCoverageFor(absPath).toSummary();
|
|
3907
3919
|
return !(sum.lines.pct >= 100 && sum.functions.pct >= 100 && sum.branches.pct >= 100);
|
|
@@ -3918,33 +3930,24 @@ var printPerFileCompositeTables = async (opts) => {
|
|
|
3918
3930
|
const selectionSetAbs = new Set(selectionAbs);
|
|
3919
3931
|
const scored = await Promise.all(
|
|
3920
3932
|
candidates.map(async (abs) => {
|
|
3921
|
-
const rel =
|
|
3933
|
+
const rel = path8.relative(opts.root, abs).replace(/\\/g, "/");
|
|
3922
3934
|
const sum = opts.map.fileCoverageFor(abs).toSummary();
|
|
3923
3935
|
const pct = Number.isFinite(sum.lines.pct) ? sum.lines.pct : 0;
|
|
3924
|
-
const absNorm =
|
|
3936
|
+
const absNorm = path8.resolve(abs).replace(/\\/g, "/");
|
|
3925
3937
|
const selfTokens = tokenizeForSimilarity(absNorm);
|
|
3926
3938
|
const selSim = Math.max(
|
|
3927
3939
|
0,
|
|
3928
|
-
...selectionTokens.map(
|
|
3929
|
-
(selectionTokenSet) => jaccard(selfTokens, selectionTokenSet)
|
|
3930
|
-
)
|
|
3940
|
+
...selectionTokens.map((selectionTokenSet) => jaccard(selfTokens, selectionTokenSet))
|
|
3931
3941
|
);
|
|
3932
3942
|
const chgSim = Math.max(
|
|
3933
3943
|
0,
|
|
3934
|
-
...changedTokens.map(
|
|
3935
|
-
(changedTokenSet) => jaccard(selfTokens, changedTokenSet)
|
|
3936
|
-
)
|
|
3937
|
-
);
|
|
3938
|
-
const tstSim = Math.max(
|
|
3939
|
-
0,
|
|
3940
|
-
...testTokens.map((tset) => jaccard(selfTokens, tset))
|
|
3944
|
+
...changedTokens.map((changedTokenSet) => jaccard(selfTokens, changedTokenSet))
|
|
3941
3945
|
);
|
|
3946
|
+
const tstSim = Math.max(0, ...testTokens.map((tset) => jaccard(selfTokens, tset)));
|
|
3942
3947
|
const nearSelection = selectionAbs.some(
|
|
3943
3948
|
(selectionPath) => isSameDirOrChild(absNorm, selectionPath)
|
|
3944
3949
|
);
|
|
3945
|
-
const nearChanged = changedAbs.some(
|
|
3946
|
-
(changedPath) => isSameDirOrChild(absNorm, changedPath)
|
|
3947
|
-
);
|
|
3950
|
+
const nearChanged = changedAbs.some((changedPath) => isSameDirOrChild(absNorm, changedPath));
|
|
3948
3951
|
const related = selSim > 0 || chgSim > 0 || nearSelection || nearChanged;
|
|
3949
3952
|
const distance = selectionSetAbs.has(absNorm) ? 0 : distFromTests.get(absNorm) ?? INF;
|
|
3950
3953
|
let group = 6;
|
|
@@ -3968,9 +3971,12 @@ var printPerFileCompositeTables = async (opts) => {
|
|
|
3968
3971
|
return { abs: absNorm, rel, linesPct: pct, group, score, distance };
|
|
3969
3972
|
})
|
|
3970
3973
|
);
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
+
const prodSeeds = selectionAbs.length > 0 ? selectionAbs : changedAbs;
|
|
3975
|
+
const rank = await computeDirectnessRank({ repoRoot: opts.root, productionSeeds: prodSeeds });
|
|
3976
|
+
let files = sortPathsWithRank(
|
|
3977
|
+
rank,
|
|
3978
|
+
scored.map((s) => s.abs)
|
|
3979
|
+
);
|
|
3974
3980
|
if (selectionAbs.length > 0) {
|
|
3975
3981
|
const selectionSet = new Set(selectionAbs);
|
|
3976
3982
|
const selectedHead = files.filter((filePath) => selectionSet.has(filePath));
|
|
@@ -3993,7 +3999,7 @@ var printPerFileCompositeTables = async (opts) => {
|
|
|
3993
3999
|
};
|
|
3994
4000
|
|
|
3995
4001
|
// src/lib/jest-bridge.ts
|
|
3996
|
-
var
|
|
4002
|
+
var path9 = __toESM(require("node:path"), 1);
|
|
3997
4003
|
var fs4 = __toESM(require("node:fs"), 1);
|
|
3998
4004
|
var util = __toESM(require("node:util"), 1);
|
|
3999
4005
|
var import_json5 = __toESM(require_lib(), 1);
|
|
@@ -4068,7 +4074,7 @@ var extractBridgePath = (raw, cwd) => {
|
|
|
4068
4074
|
return null;
|
|
4069
4075
|
}
|
|
4070
4076
|
const jsonPath = matches[matches.length - 1][1].trim().replace(/^["'`]|["'`]$/g, "");
|
|
4071
|
-
return
|
|
4077
|
+
return path9.isAbsolute(jsonPath) ? jsonPath : path9.resolve(cwd, jsonPath);
|
|
4072
4078
|
};
|
|
4073
4079
|
var drawRule = (label) => {
|
|
4074
4080
|
const width = Math.max(
|
|
@@ -4667,7 +4673,7 @@ var buildStackSection = (mergedForStack, ctx, fallbackLoc) => {
|
|
|
4667
4673
|
const loc = deepestProjectLoc(mergedForStack, ctx.projectHint);
|
|
4668
4674
|
if (loc) {
|
|
4669
4675
|
const href = preferredEditorHref(loc.file, loc.line, ctx.editorCmd);
|
|
4670
|
-
out.push(` ${ansi.dim("at")} ${osc8(`${
|
|
4676
|
+
out.push(` ${ansi.dim("at")} ${osc8(`${path9.basename(loc.file)}:${loc.line}`, href)}`);
|
|
4671
4677
|
}
|
|
4672
4678
|
out.push("");
|
|
4673
4679
|
return out;
|
|
@@ -4707,6 +4713,7 @@ var formatJestOutputVitest = (raw, opts) => {
|
|
|
4707
4713
|
const projectHint = new RegExp(
|
|
4708
4714
|
`(${cwd.replace(/[.*+?^${}()|[\\]\\\\]/g, "\\$&")})|(/gigworx-node/)`
|
|
4709
4715
|
);
|
|
4716
|
+
const onlyFailures = Boolean(opts?.onlyFailures);
|
|
4710
4717
|
const lines = raw.split(/\r?\n/);
|
|
4711
4718
|
const out = [];
|
|
4712
4719
|
const seenFailures = /* @__PURE__ */ new Set();
|
|
@@ -4794,8 +4801,10 @@ var formatJestOutputVitest = (raw, opts) => {
|
|
|
4794
4801
|
continue;
|
|
4795
4802
|
}
|
|
4796
4803
|
seenFiles.add(rel);
|
|
4797
|
-
|
|
4798
|
-
|
|
4804
|
+
if (!(onlyFailures && badge === "PASS")) {
|
|
4805
|
+
const pill = badge === "PASS" ? colorTokens.passPill("PASS") : colorTokens.failPill("FAIL");
|
|
4806
|
+
out.push(`${pill} ${ansi.white(rel)}`);
|
|
4807
|
+
}
|
|
4799
4808
|
lineIndex += 1;
|
|
4800
4809
|
continue;
|
|
4801
4810
|
}
|
|
@@ -4908,14 +4917,21 @@ function renderVitestFromJestJSON(data, opts) {
|
|
|
4908
4917
|
`(${cwd.replace(/[.*+?^${}()|[\\]\\\\]/g, "\\$&")})|(/gigworx-node/)`
|
|
4909
4918
|
);
|
|
4910
4919
|
const ctx = { projectHint, editorCmd: opts?.editorCmd, showStacks: true };
|
|
4920
|
+
const onlyFailures = Boolean(opts?.onlyFailures);
|
|
4911
4921
|
const out = [];
|
|
4912
|
-
|
|
4913
|
-
|
|
4922
|
+
if (!onlyFailures) {
|
|
4923
|
+
out.push(renderRunLine(cwd));
|
|
4924
|
+
out.push("");
|
|
4925
|
+
}
|
|
4914
4926
|
for (const file of data.testResults) {
|
|
4915
4927
|
const rel = file.testFilePath.replace(/\\/g, "/").replace(`${cwd}/`, "");
|
|
4916
4928
|
const failed = file.testResults.filter((assertion) => assertion.status === "failed");
|
|
4917
|
-
|
|
4918
|
-
|
|
4929
|
+
if (!onlyFailures) {
|
|
4930
|
+
out.push(...buildPerFileOverview(rel, file.testResults));
|
|
4931
|
+
}
|
|
4932
|
+
if (!(onlyFailures && failed.length === 0)) {
|
|
4933
|
+
out.push(buildFileBadgeLine(rel, failed.length));
|
|
4934
|
+
}
|
|
4919
4935
|
if (file.failureMessage && failed.length === 0) {
|
|
4920
4936
|
const lines = file.failureMessage.split(/\r?\n/);
|
|
4921
4937
|
const details = linesFromDetails(file.failureDetails);
|
|
@@ -4946,7 +4962,7 @@ function renderVitestFromJestJSON(data, opts) {
|
|
|
4946
4962
|
const deepestLoc = deepestProjectLoc(mergedForStack, projectHint);
|
|
4947
4963
|
const locLink = deepestLoc && (() => {
|
|
4948
4964
|
const href = preferredEditorHref(deepestLoc.file, deepestLoc.line, opts?.editorCmd);
|
|
4949
|
-
const base = `${
|
|
4965
|
+
const base = `${path9.basename(deepestLoc.file)}:${deepestLoc.line}`;
|
|
4950
4966
|
return osc8(base, href);
|
|
4951
4967
|
})();
|
|
4952
4968
|
const headerLine = `${ansi.white(header)}${locLink ? ` ${ansi.dim(`(${locLink})`)}` : ""}`;
|
|
@@ -4991,13 +5007,8 @@ ${footer}`;
|
|
|
4991
5007
|
}
|
|
4992
5008
|
|
|
4993
5009
|
// src/lib/program.ts
|
|
4994
|
-
var import_meta = {};
|
|
4995
5010
|
var jestBin = "./node_modules/.bin/jest";
|
|
4996
5011
|
var babelNodeBin = "./node_modules/.bin/babel-node";
|
|
4997
|
-
var moduleSpecifierForRequire = (
|
|
4998
|
-
// @ts-ignore
|
|
4999
|
-
typeof __filename !== "undefined" ? __filename : import_meta.url
|
|
5000
|
-
);
|
|
5001
5012
|
var registerSignalHandlersOnce = () => {
|
|
5002
5013
|
let handled = false;
|
|
5003
5014
|
const on = (sig) => {
|
|
@@ -5015,7 +5026,6 @@ Received ${sig}, exiting...
|
|
|
5015
5026
|
};
|
|
5016
5027
|
var isDebug = () => Boolean(process.env.TEST_CLI_DEBUG);
|
|
5017
5028
|
var mergeLcov = async () => {
|
|
5018
|
-
const jestLcovPath = "coverage/jest/lcov.info";
|
|
5019
5029
|
const vitestLcovPath = "coverage/vitest/lcov.info";
|
|
5020
5030
|
const mergedOutPath = "coverage/lcov.info";
|
|
5021
5031
|
const readOrEmpty = async (filePath) => {
|
|
@@ -5026,7 +5036,7 @@ var mergeLcov = async () => {
|
|
|
5026
5036
|
}
|
|
5027
5037
|
};
|
|
5028
5038
|
let vitestContent = "";
|
|
5029
|
-
|
|
5039
|
+
const jestParts = [];
|
|
5030
5040
|
try {
|
|
5031
5041
|
vitestContent = await readOrEmpty(vitestLcovPath);
|
|
5032
5042
|
} catch (readVitestError) {
|
|
@@ -5034,20 +5044,46 @@ var mergeLcov = async () => {
|
|
|
5034
5044
|
console.info(`read vitest lcov failed: ${String(readVitestError)}`);
|
|
5035
5045
|
}
|
|
5036
5046
|
}
|
|
5047
|
+
const collectLcovs = (dir) => {
|
|
5048
|
+
const out = [];
|
|
5049
|
+
try {
|
|
5050
|
+
const entries = fsSync3.readdirSync(dir, { withFileTypes: true });
|
|
5051
|
+
for (const entry of entries) {
|
|
5052
|
+
const full = path10.join(dir, entry.name);
|
|
5053
|
+
if (entry.isDirectory()) {
|
|
5054
|
+
out.push(...collectLcovs(full));
|
|
5055
|
+
} else if (entry.isFile() && entry.name === "lcov.info") {
|
|
5056
|
+
out.push(full);
|
|
5057
|
+
}
|
|
5058
|
+
}
|
|
5059
|
+
} catch {
|
|
5060
|
+
}
|
|
5061
|
+
return out;
|
|
5062
|
+
};
|
|
5037
5063
|
try {
|
|
5038
|
-
|
|
5064
|
+
const jestRoot = path10.join("coverage", "jest");
|
|
5065
|
+
const candidates = [path10.join(jestRoot, "lcov.info"), ...collectLcovs(jestRoot)].map((candidatePath) => path10.resolve(candidatePath)).filter((absolutePath, index, arr) => arr.indexOf(absolutePath) === index);
|
|
5066
|
+
for (const filePath of candidates) {
|
|
5067
|
+
try {
|
|
5068
|
+
const content = await readOrEmpty(filePath);
|
|
5069
|
+
if (content.trim()) {
|
|
5070
|
+
jestParts.push(content.trim());
|
|
5071
|
+
}
|
|
5072
|
+
} catch {
|
|
5073
|
+
}
|
|
5074
|
+
}
|
|
5039
5075
|
} catch (readJestError) {
|
|
5040
5076
|
if (isDebug()) {
|
|
5041
|
-
console.info(`
|
|
5077
|
+
console.info(`scan jest lcov failed: ${String(readJestError)}`);
|
|
5042
5078
|
}
|
|
5043
5079
|
}
|
|
5044
|
-
if (!vitestContent &&
|
|
5080
|
+
if (!vitestContent && jestParts.length === 0) {
|
|
5045
5081
|
if (isDebug()) {
|
|
5046
5082
|
console.info("No coverage outputs found to merge.");
|
|
5047
5083
|
}
|
|
5048
5084
|
return;
|
|
5049
5085
|
}
|
|
5050
|
-
const merged = [vitestContent.trim(),
|
|
5086
|
+
const merged = [vitestContent.trim(), ...jestParts].filter(Boolean).join("\n");
|
|
5051
5087
|
if (merged.length > 0) {
|
|
5052
5088
|
await (await import("node:fs/promises")).mkdir("coverage", { recursive: true });
|
|
5053
5089
|
await (await import("node:fs/promises")).writeFile(mergedOutPath, `${merged}
|
|
@@ -5060,23 +5096,40 @@ var mergeLcov = async () => {
|
|
|
5060
5096
|
}
|
|
5061
5097
|
};
|
|
5062
5098
|
var emitMergedCoverage = async (ui, opts) => {
|
|
5063
|
-
const jestJson = path9.join("coverage", "jest", "coverage-final.json");
|
|
5064
|
-
const jSize = fsSync3.existsSync(jestJson) ? fsSync3.statSync(jestJson).size : -1;
|
|
5065
|
-
const jestSizeLabel = jSize >= 0 ? `${jSize} bytes` : "missing";
|
|
5066
|
-
if (isDebug()) {
|
|
5067
|
-
console.info(`Coverage JSON probe \u2192 jest: ${jestSizeLabel}`);
|
|
5068
|
-
}
|
|
5069
|
-
const jestData = await readCoverageJson(jestJson);
|
|
5070
|
-
const jestFilesCount = Object.keys(jestData).length;
|
|
5071
|
-
if (isDebug()) {
|
|
5072
|
-
console.info(`Decoded coverage entries \u2192 jest: ${jestFilesCount}`);
|
|
5073
|
-
}
|
|
5074
5099
|
const map = (0, import_istanbul_lib_coverage2.createCoverageMap)({});
|
|
5075
|
-
|
|
5100
|
+
const listJsons = (dir) => {
|
|
5101
|
+
const out = [];
|
|
5076
5102
|
try {
|
|
5077
|
-
|
|
5103
|
+
const entries = fsSync3.readdirSync(dir, { withFileTypes: true });
|
|
5104
|
+
for (const entry of entries) {
|
|
5105
|
+
const full = path10.join(dir, entry.name);
|
|
5106
|
+
if (entry.isDirectory()) {
|
|
5107
|
+
out.push(...listJsons(full));
|
|
5108
|
+
} else if (entry.isFile() && entry.name === "coverage-final.json") {
|
|
5109
|
+
out.push(full);
|
|
5110
|
+
}
|
|
5111
|
+
}
|
|
5112
|
+
} catch {
|
|
5113
|
+
}
|
|
5114
|
+
return out;
|
|
5115
|
+
};
|
|
5116
|
+
const coverageRoot = path10.join("coverage", "jest");
|
|
5117
|
+
const jsonCandidates = [
|
|
5118
|
+
path10.join(coverageRoot, "coverage-final.json"),
|
|
5119
|
+
...listJsons(coverageRoot)
|
|
5120
|
+
].map((candidatePath) => path10.resolve(candidatePath)).filter((absolutePath, index, arr) => {
|
|
5121
|
+
const isFirst = arr.indexOf(absolutePath) === index;
|
|
5122
|
+
const exists = fsSync3.existsSync(absolutePath);
|
|
5123
|
+
return isFirst && exists;
|
|
5124
|
+
});
|
|
5125
|
+
for (const jsonPath of jsonCandidates) {
|
|
5126
|
+
try {
|
|
5127
|
+
const data = await readCoverageJson(jsonPath);
|
|
5128
|
+
if (Object.keys(data).length) {
|
|
5129
|
+
map.merge(data);
|
|
5130
|
+
}
|
|
5078
5131
|
} catch (mergeJestError) {
|
|
5079
|
-
console.warn(`Failed merging jest coverage JSON: ${String(mergeJestError)}`);
|
|
5132
|
+
console.warn(`Failed merging jest coverage JSON @ ${jsonPath}: ${String(mergeJestError)}`);
|
|
5080
5133
|
}
|
|
5081
5134
|
}
|
|
5082
5135
|
if (map.files().length === 0) {
|
|
@@ -5126,7 +5179,7 @@ var emitMergedCoverage = async (ui, opts) => {
|
|
|
5126
5179
|
executedTests: opts.executedTests ?? []
|
|
5127
5180
|
});
|
|
5128
5181
|
const context = LibReport.createContext({
|
|
5129
|
-
dir:
|
|
5182
|
+
dir: path10.resolve("coverage", "merged"),
|
|
5130
5183
|
coverageMap: filteredMap,
|
|
5131
5184
|
defaultSummarizer: "nested"
|
|
5132
5185
|
});
|
|
@@ -5194,8 +5247,8 @@ var emitMergedCoverage = async (ui, opts) => {
|
|
|
5194
5247
|
for (const reporter of reporters) {
|
|
5195
5248
|
reporter.execute(context);
|
|
5196
5249
|
}
|
|
5197
|
-
const textPath =
|
|
5198
|
-
const summaryPath =
|
|
5250
|
+
const textPath = path10.resolve("coverage", "merged", "coverage.txt");
|
|
5251
|
+
const summaryPath = path10.resolve("coverage", "merged", "coverage-summary.txt");
|
|
5199
5252
|
const filesToPrint = [];
|
|
5200
5253
|
if (fsSync3.existsSync(textPath)) {
|
|
5201
5254
|
filesToPrint.push(textPath);
|
|
@@ -5266,6 +5319,7 @@ var program = async () => {
|
|
|
5266
5319
|
collectCoverage,
|
|
5267
5320
|
coverageUi,
|
|
5268
5321
|
coverageAbortOnFailure,
|
|
5322
|
+
onlyFailures,
|
|
5269
5323
|
selectionSpecified,
|
|
5270
5324
|
selectionPaths,
|
|
5271
5325
|
includeGlobs,
|
|
@@ -5277,17 +5331,43 @@ var program = async () => {
|
|
|
5277
5331
|
coverageMode,
|
|
5278
5332
|
coverageMaxFiles: coverageMaxFilesArg,
|
|
5279
5333
|
coverageMaxHotspots: coverageMaxHotspotsArg,
|
|
5280
|
-
coveragePageFit
|
|
5334
|
+
coveragePageFit,
|
|
5335
|
+
changed
|
|
5281
5336
|
} = deriveArgs(argv);
|
|
5282
|
-
|
|
5337
|
+
const getChangedFiles = async (mode, cwd) => {
|
|
5338
|
+
const collect = async (cmd, args) => {
|
|
5339
|
+
try {
|
|
5340
|
+
const out = await runText(cmd, args, {
|
|
5341
|
+
cwd,
|
|
5342
|
+
env: safeEnv(process.env, {}),
|
|
5343
|
+
timeoutMs: 4e3
|
|
5344
|
+
});
|
|
5345
|
+
return out.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
5346
|
+
} catch {
|
|
5347
|
+
return [];
|
|
5348
|
+
}
|
|
5349
|
+
};
|
|
5350
|
+
const staged = mode === "staged" || mode === "all" ? await collect("git", ["diff", "--name-only", "--diff-filter=ACMRTUXB", "--cached"]) : [];
|
|
5351
|
+
const unstagedTracked = mode === "unstaged" || mode === "all" ? await collect("git", ["diff", "--name-only", "--diff-filter=ACMRTUXB"]) : [];
|
|
5352
|
+
const untracked = mode === "unstaged" || mode === "all" ? await collect("git", ["ls-files", "--others", "--exclude-standard"]) : [];
|
|
5353
|
+
const rels = Array.from(/* @__PURE__ */ new Set([...staged, ...unstagedTracked, ...untracked]));
|
|
5354
|
+
return rels.map((rel) => path10.resolve(cwd, rel).replace(/\\/g, "/")).filter((abs) => !abs.includes("/node_modules/") && !abs.includes("/coverage/"));
|
|
5355
|
+
};
|
|
5356
|
+
const repoRootForChanged = workspaceRoot ?? await findRepoRoot();
|
|
5357
|
+
const changedSelectionAbs = changed ? await getChangedFiles(changed, repoRootForChanged) : [];
|
|
5358
|
+
const selectionPathsAugmented = changedSelectionAbs.length ? Array.from(/* @__PURE__ */ new Set([...selectionPaths, ...changedSelectionAbs])) : selectionPaths;
|
|
5359
|
+
const selectionSpecifiedAugmented = Boolean(selectionSpecified || changedSelectionAbs.length > 0);
|
|
5360
|
+
console.info(
|
|
5361
|
+
`Selection \u2192 specified=${selectionSpecifiedAugmented} paths=${selectionPathsAugmented.length}`
|
|
5362
|
+
);
|
|
5283
5363
|
const { jest } = argsForDiscovery(["run"], jestArgs);
|
|
5284
|
-
const selectionLooksLikeTest =
|
|
5364
|
+
const selectionLooksLikeTest = selectionPathsAugmented.some(
|
|
5285
5365
|
(pathText) => /\.(test|spec)\.[tj]sx?$/i.test(pathText) || /(^|\/)tests?\//i.test(pathText)
|
|
5286
5366
|
);
|
|
5287
|
-
const selectionLooksLikePath =
|
|
5367
|
+
const selectionLooksLikePath = selectionPathsAugmented.some(
|
|
5288
5368
|
(pathText) => /[\\/]/.test(pathText) || /\.(m?[tj]sx?)$/i.test(pathText)
|
|
5289
5369
|
);
|
|
5290
|
-
const selectionHasPaths =
|
|
5370
|
+
const selectionHasPaths = selectionPathsAugmented.length > 0;
|
|
5291
5371
|
const repoRootForDiscovery = workspaceRoot ?? await findRepoRoot();
|
|
5292
5372
|
const expandProductionSelections = async (tokens, repoRoot) => {
|
|
5293
5373
|
const results = /* @__PURE__ */ new Set();
|
|
@@ -5296,18 +5376,18 @@ var program = async () => {
|
|
|
5296
5376
|
if (!token) {
|
|
5297
5377
|
continue;
|
|
5298
5378
|
}
|
|
5299
|
-
const isAbs =
|
|
5379
|
+
const isAbs = path10.isAbsolute(token);
|
|
5300
5380
|
const looksLikeRelPath = /[\\/]/.test(token);
|
|
5301
5381
|
let candidateFromRoot;
|
|
5302
5382
|
if (token.startsWith("/")) {
|
|
5303
|
-
candidateFromRoot =
|
|
5383
|
+
candidateFromRoot = path10.join(repoRoot, token.slice(1));
|
|
5304
5384
|
} else if (looksLikeRelPath) {
|
|
5305
|
-
candidateFromRoot =
|
|
5385
|
+
candidateFromRoot = path10.join(repoRoot, token);
|
|
5306
5386
|
} else {
|
|
5307
5387
|
candidateFromRoot = void 0;
|
|
5308
5388
|
}
|
|
5309
5389
|
const tryPushIfProd = (absPath) => {
|
|
5310
|
-
const norm =
|
|
5390
|
+
const norm = path10.resolve(absPath).replace(/\\/g, "/");
|
|
5311
5391
|
const isTest = /(^|\/)tests?\//i.test(norm) || /\.(test|spec)\.[tj]sx?$/i.test(norm);
|
|
5312
5392
|
if (!isTest && fsSync3.existsSync(norm)) {
|
|
5313
5393
|
results.add(norm);
|
|
@@ -5329,7 +5409,7 @@ var program = async () => {
|
|
|
5329
5409
|
}),
|
|
5330
5410
|
timeoutMs: 4e3
|
|
5331
5411
|
});
|
|
5332
|
-
const matches = out.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map((rel) =>
|
|
5412
|
+
const matches = out.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map((rel) => path10.resolve(repoRoot, rel).replace(/\\/g, "/")).filter(
|
|
5333
5413
|
(abs) => !abs.includes("/node_modules/") && !abs.includes("/coverage/") && !/(^|\/)tests?\//i.test(abs) && !/\.(test|spec)\.[tj]sx?$/i.test(abs)
|
|
5334
5414
|
);
|
|
5335
5415
|
matches.forEach((abs) => results.add(abs));
|
|
@@ -5338,20 +5418,20 @@ var program = async () => {
|
|
|
5338
5418
|
}
|
|
5339
5419
|
return Array.from(results);
|
|
5340
5420
|
};
|
|
5341
|
-
const initialProdSelections =
|
|
5421
|
+
const initialProdSelections = selectionPathsAugmented.filter(
|
|
5342
5422
|
(pathText) => (/[\\/]/.test(pathText) || /\.(m?[tj]sx?)$/i.test(pathText)) && !/(^|\/)tests?\//i.test(pathText) && !/\.(test|spec)\.[tj]sx?$/i.test(pathText)
|
|
5343
5423
|
);
|
|
5344
|
-
const expandedProdSelections = initialProdSelections.length ? initialProdSelections : await expandProductionSelections(
|
|
5424
|
+
const expandedProdSelections = initialProdSelections.length ? initialProdSelections : await expandProductionSelections(selectionPathsAugmented, repoRootForDiscovery);
|
|
5345
5425
|
const selectionIncludesProdPaths = expandedProdSelections.length > 0;
|
|
5346
5426
|
console.info(
|
|
5347
5427
|
`Selection classify \u2192 looksLikePath=${selectionLooksLikePath} looksLikeTest=${selectionLooksLikeTest} prodPaths=${selectionIncludesProdPaths}`
|
|
5348
5428
|
);
|
|
5349
|
-
const stripPathTokens = (args) => args.filter((token) => !
|
|
5429
|
+
const stripPathTokens = (args) => args.filter((token) => !selectionPathsAugmented.includes(token));
|
|
5350
5430
|
const jestDiscoveryArgs = selectionIncludesProdPaths ? stripPathTokens(jest) : jest;
|
|
5351
5431
|
const projectConfigs = [];
|
|
5352
5432
|
try {
|
|
5353
|
-
const baseCfg =
|
|
5354
|
-
const tsCfg =
|
|
5433
|
+
const baseCfg = path10.resolve("jest.config.js");
|
|
5434
|
+
const tsCfg = path10.resolve("jest.ts.config.js");
|
|
5355
5435
|
if (fsSync3.existsSync(baseCfg)) {
|
|
5356
5436
|
projectConfigs.push(baseCfg);
|
|
5357
5437
|
}
|
|
@@ -5368,7 +5448,7 @@ var program = async () => {
|
|
|
5368
5448
|
);
|
|
5369
5449
|
const prodSelections2 = expandedProdSelections;
|
|
5370
5450
|
for (const cfg of projectConfigs) {
|
|
5371
|
-
const cfgCwd =
|
|
5451
|
+
const cfgCwd = path10.dirname(cfg);
|
|
5372
5452
|
const allTests = await discoverJestResilient([...jestDiscoveryArgs, "--config", cfg], {
|
|
5373
5453
|
cwd: cfgCwd
|
|
5374
5454
|
});
|
|
@@ -5381,7 +5461,7 @@ var program = async () => {
|
|
|
5381
5461
|
});
|
|
5382
5462
|
} catch (err) {
|
|
5383
5463
|
if (isDebug()) {
|
|
5384
|
-
console.warn(`direct selection failed for project ${
|
|
5464
|
+
console.warn(`direct selection failed for project ${path10.basename(cfg)}: ${String(err)}`);
|
|
5385
5465
|
}
|
|
5386
5466
|
}
|
|
5387
5467
|
perProjectFiles.set(cfg, directPerProject);
|
|
@@ -5393,7 +5473,7 @@ var program = async () => {
|
|
|
5393
5473
|
)} | related=${selectionIncludesProdPaths} | cwd=${repoRootForDiscovery}`
|
|
5394
5474
|
);
|
|
5395
5475
|
for (const cfg of projectConfigs) {
|
|
5396
|
-
const cfgCwd =
|
|
5476
|
+
const cfgCwd = path10.dirname(cfg);
|
|
5397
5477
|
const files = await discoverJestResilient([...jestDiscoveryArgs, "--config", cfg], {
|
|
5398
5478
|
cwd: cfgCwd
|
|
5399
5479
|
});
|
|
@@ -5403,18 +5483,18 @@ var program = async () => {
|
|
|
5403
5483
|
const perProjectFiltered = /* @__PURE__ */ new Map();
|
|
5404
5484
|
for (const cfg of projectConfigs) {
|
|
5405
5485
|
const files = perProjectFiles.get(cfg) ?? [];
|
|
5406
|
-
const selectionTestPaths =
|
|
5486
|
+
const selectionTestPaths = selectionPathsAugmented.filter(
|
|
5407
5487
|
(pathToken) => /\.(test|spec)\.[tj]sx?$/i.test(pathToken) || /(^|\/)tests?\//i.test(pathToken)
|
|
5408
5488
|
);
|
|
5409
5489
|
const candidates = selectionHasPaths && selectionLooksLikeTest ? selectionTestPaths : files;
|
|
5410
5490
|
const absFiles = candidates.map(
|
|
5411
|
-
(candidatePath) =>
|
|
5491
|
+
(candidatePath) => path10.isAbsolute(candidatePath) ? candidatePath : path10.join(repoRootForDiscovery, candidatePath)
|
|
5412
5492
|
).map((absolutePath) => absolutePath.replace(/\\/g, "/"));
|
|
5413
5493
|
const onlyOwned = await filterCandidatesForProject(
|
|
5414
5494
|
cfg,
|
|
5415
5495
|
jestDiscoveryArgs,
|
|
5416
5496
|
absFiles,
|
|
5417
|
-
|
|
5497
|
+
path10.dirname(cfg)
|
|
5418
5498
|
);
|
|
5419
5499
|
perProjectFiltered.set(cfg, onlyOwned);
|
|
5420
5500
|
}
|
|
@@ -5426,7 +5506,7 @@ var program = async () => {
|
|
|
5426
5506
|
if (selectionHasPaths && prodSelections.length > 0) {
|
|
5427
5507
|
console.info(`rg related \u2192 prodSelections=${prodSelections.length} (starting)`);
|
|
5428
5508
|
const repoRootForRefinement = workspaceRoot ?? await findRepoRoot();
|
|
5429
|
-
const selectionKey = prodSelections.map((absPath) =>
|
|
5509
|
+
const selectionKey = prodSelections.map((absPath) => path10.relative(repoRootForRefinement, absPath).replace(/\\/g, "/")).sort((firstPath, secondPath) => firstPath.localeCompare(secondPath)).join("|");
|
|
5430
5510
|
const { cachedRelated: cachedRelated2, findRelatedTestsFast: findRelatedTestsFast2, DEFAULT_TEST_GLOBS: DEFAULT_TEST_GLOBS2 } = await Promise.resolve().then(() => (init_fast_related(), fast_related_exports));
|
|
5431
5511
|
const { DEFAULT_EXCLUDE: DEFAULT_EXCLUDE2 } = await Promise.resolve().then(() => (init_args(), args_exports));
|
|
5432
5512
|
const rgMatches = await cachedRelated2({
|
|
@@ -5456,7 +5536,7 @@ var program = async () => {
|
|
|
5456
5536
|
cfg,
|
|
5457
5537
|
jestDiscoveryArgs,
|
|
5458
5538
|
rgCandidates,
|
|
5459
|
-
|
|
5539
|
+
path10.dirname(cfg)
|
|
5460
5540
|
);
|
|
5461
5541
|
perProjectFromRg.set(cfg, owned);
|
|
5462
5542
|
}
|
|
@@ -5471,9 +5551,9 @@ var program = async () => {
|
|
|
5471
5551
|
} else {
|
|
5472
5552
|
const repoRootForScan = repoRootForDiscovery;
|
|
5473
5553
|
const toSeeds = (abs) => {
|
|
5474
|
-
const rel =
|
|
5554
|
+
const rel = path10.relative(repoRootForScan, abs).replace(/\\/g, "/");
|
|
5475
5555
|
const withoutExt = rel.replace(/\.(m?[tj]sx?)$/i, "");
|
|
5476
|
-
const base =
|
|
5556
|
+
const base = path10.basename(withoutExt);
|
|
5477
5557
|
const segs = withoutExt.split("/");
|
|
5478
5558
|
const tail2 = segs.slice(-2).join("/");
|
|
5479
5559
|
return Array.from(new Set([withoutExt, base, tail2].filter(Boolean)));
|
|
@@ -5488,8 +5568,8 @@ var program = async () => {
|
|
|
5488
5568
|
}
|
|
5489
5569
|
};
|
|
5490
5570
|
const resolveLocalImport = (fromFile, spec) => {
|
|
5491
|
-
const baseDir =
|
|
5492
|
-
const cand =
|
|
5571
|
+
const baseDir = path10.dirname(fromFile);
|
|
5572
|
+
const cand = path10.resolve(baseDir, spec);
|
|
5493
5573
|
const exts = ["", ".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
5494
5574
|
for (const ext of exts) {
|
|
5495
5575
|
const full = ext ? `${cand}${ext}` : cand;
|
|
@@ -5498,7 +5578,7 @@ var program = async () => {
|
|
|
5498
5578
|
}
|
|
5499
5579
|
}
|
|
5500
5580
|
for (const ext of exts) {
|
|
5501
|
-
const full =
|
|
5581
|
+
const full = path10.join(cand, `index${ext}`);
|
|
5502
5582
|
if (fsSync3.existsSync(full)) {
|
|
5503
5583
|
return full;
|
|
5504
5584
|
}
|
|
@@ -5552,7 +5632,7 @@ var program = async () => {
|
|
|
5552
5632
|
cfg,
|
|
5553
5633
|
jestDiscoveryArgs,
|
|
5554
5634
|
keptCandidates,
|
|
5555
|
-
|
|
5635
|
+
path10.dirname(cfg)
|
|
5556
5636
|
);
|
|
5557
5637
|
perProjectFromScan.set(cfg, owned);
|
|
5558
5638
|
}
|
|
@@ -5579,9 +5659,9 @@ var program = async () => {
|
|
|
5579
5659
|
if (effectiveJestFiles.length === 0) {
|
|
5580
5660
|
const repoRoot = repoRootForRefinement;
|
|
5581
5661
|
const seeds = prodSelections.map(
|
|
5582
|
-
(abs) =>
|
|
5662
|
+
(abs) => path10.relative(repoRoot, abs).replace(/\\/g, "/").replace(/\.(m?[tj]sx?)$/i, "")
|
|
5583
5663
|
).flatMap((rel) => {
|
|
5584
|
-
const base =
|
|
5664
|
+
const base = path10.basename(rel);
|
|
5585
5665
|
const segments = rel.split("/");
|
|
5586
5666
|
return Array.from(new Set([rel, base, segments.slice(-2).join("/")].filter(Boolean)));
|
|
5587
5667
|
});
|
|
@@ -5594,8 +5674,8 @@ var program = async () => {
|
|
|
5594
5674
|
}
|
|
5595
5675
|
};
|
|
5596
5676
|
const resolveLocalImport = (fromFile, spec) => {
|
|
5597
|
-
const baseDir =
|
|
5598
|
-
const candidate =
|
|
5677
|
+
const baseDir = path10.dirname(fromFile);
|
|
5678
|
+
const candidate = path10.resolve(baseDir, spec);
|
|
5599
5679
|
const extensions = ["", ".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts"];
|
|
5600
5680
|
for (const ext of extensions) {
|
|
5601
5681
|
const fullPath = ext ? `${candidate}${ext}` : candidate;
|
|
@@ -5604,7 +5684,7 @@ var program = async () => {
|
|
|
5604
5684
|
}
|
|
5605
5685
|
}
|
|
5606
5686
|
for (const ext of extensions) {
|
|
5607
|
-
const fullPath =
|
|
5687
|
+
const fullPath = path10.join(candidate, `index${ext}`);
|
|
5608
5688
|
if (fsSync3.existsSync(fullPath)) {
|
|
5609
5689
|
return fullPath;
|
|
5610
5690
|
}
|
|
@@ -5723,8 +5803,8 @@ var program = async () => {
|
|
|
5723
5803
|
}
|
|
5724
5804
|
}
|
|
5725
5805
|
const jestDecision = decideShouldRunJest([], effectiveJestFiles, {
|
|
5726
|
-
selectionSpecified,
|
|
5727
|
-
selectionPaths
|
|
5806
|
+
selectionSpecified: selectionSpecifiedAugmented,
|
|
5807
|
+
selectionPaths: selectionPathsAugmented
|
|
5728
5808
|
});
|
|
5729
5809
|
const { shouldRunJest } = jestDecision;
|
|
5730
5810
|
const jestCount = effectiveJestFiles.length;
|
|
@@ -5742,45 +5822,63 @@ var program = async () => {
|
|
|
5742
5822
|
}
|
|
5743
5823
|
console.info(`Run plan \u2192 Jest maybe=${shouldRunJest} (projects=${projectConfigs.length})`);
|
|
5744
5824
|
let jestExitCode = 0;
|
|
5825
|
+
const allBridgeJson = [];
|
|
5745
5826
|
const executedTestFilesSet = /* @__PURE__ */ new Set();
|
|
5746
5827
|
if (shouldRunJest) {
|
|
5747
5828
|
console.info("Starting Jest (no Vitest targets)\u2026");
|
|
5748
5829
|
await runJestBootstrap();
|
|
5749
5830
|
const jestRunArgs = selectionIncludesProdPaths ? stripPathTokens(jestArgs) : jestArgs;
|
|
5831
|
+
const sanitizedJestRunArgs = jestRunArgs.filter(
|
|
5832
|
+
(arg) => !/^--coverageDirectory(?:=|$)/.test(String(arg))
|
|
5833
|
+
);
|
|
5750
5834
|
const projectsToRun = projectConfigs.filter(
|
|
5751
5835
|
(cfg) => (perProjectFiltered.get(cfg) ?? []).length > 0
|
|
5752
5836
|
);
|
|
5753
|
-
const totalProjectsToRun = projectsToRun.length;
|
|
5754
5837
|
const stripFooter = (text) => {
|
|
5755
5838
|
const lines = text.split("\n");
|
|
5756
5839
|
const idx = lines.findIndex((ln) => /^Test Files\s/.test(stripAnsiSimple(ln)));
|
|
5757
5840
|
return idx >= 0 ? lines.slice(0, idx).join("\n").trimEnd() : text;
|
|
5758
5841
|
};
|
|
5842
|
+
const prodSeedsForRun = (() => {
|
|
5843
|
+
const changedAbs = (changedSelectionAbs ?? []).map(
|
|
5844
|
+
(absPath) => path10.resolve(absPath).replace(/\\/g, "/")
|
|
5845
|
+
);
|
|
5846
|
+
const selAbs = selectionPathsAugmented.map(
|
|
5847
|
+
(pathToken) => path10.resolve(pathToken).replace(/\\/g, "/")
|
|
5848
|
+
);
|
|
5849
|
+
return (changedAbs.length ? changedAbs : selAbs).filter(
|
|
5850
|
+
(abs) => /[\\/]/.test(abs) && !/(^|\/)tests?\//i.test(abs) && !/\.(test|spec)\.[tj]sx?$/i.test(abs)
|
|
5851
|
+
);
|
|
5852
|
+
})();
|
|
5853
|
+
const repoRootForRank = repoRootForDiscovery;
|
|
5854
|
+
const fileRank = await computeDirectnessRank({
|
|
5855
|
+
repoRoot: repoRootForRank,
|
|
5856
|
+
productionSeeds: prodSeedsForRun
|
|
5857
|
+
});
|
|
5759
5858
|
for (let projIndex = 0; projIndex < projectsToRun.length; projIndex += 1) {
|
|
5760
5859
|
const cfg = projectsToRun[projIndex];
|
|
5761
|
-
const isLastProject = projIndex === totalProjectsToRun - 1;
|
|
5762
5860
|
const files = perProjectFiltered.get(cfg) ?? [];
|
|
5763
5861
|
if (files.length === 0) {
|
|
5764
|
-
console.info(`Project ${
|
|
5862
|
+
console.info(`Project ${path10.basename(cfg)}: 0 matching tests after filter; skipping.`);
|
|
5765
5863
|
continue;
|
|
5766
5864
|
}
|
|
5767
5865
|
files.forEach(
|
|
5768
|
-
(absTestPath) => executedTestFilesSet.add(
|
|
5866
|
+
(absTestPath) => executedTestFilesSet.add(path10.resolve(absTestPath).replace(/\\/g, "/"))
|
|
5769
5867
|
);
|
|
5770
|
-
const outJson =
|
|
5868
|
+
const outJson = path10.join(
|
|
5771
5869
|
os2.tmpdir(),
|
|
5772
5870
|
`jest-bridge-${Date.now()}-${Math.random().toString(36).slice(2)}.json`
|
|
5773
5871
|
);
|
|
5774
|
-
const reporterPath =
|
|
5872
|
+
const reporterPath = path10.resolve("scripts/jest-vitest-bridge.cjs");
|
|
5775
5873
|
try {
|
|
5776
5874
|
if (!fsSync3.existsSync(reporterPath)) {
|
|
5777
|
-
fsSync3.mkdirSync(
|
|
5875
|
+
fsSync3.mkdirSync(path10.dirname(reporterPath), { recursive: true });
|
|
5778
5876
|
fsSync3.writeFileSync(reporterPath, JEST_BRIDGE_REPORTER_SOURCE, "utf8");
|
|
5779
5877
|
}
|
|
5780
5878
|
} catch (ensureReporterError) {
|
|
5781
5879
|
console.warn(`Unable to ensure jest bridge reporter: ${String(ensureReporterError)}`);
|
|
5782
5880
|
}
|
|
5783
|
-
const selectedFilesForCoverage =
|
|
5881
|
+
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}`);
|
|
5784
5882
|
const coverageFromArgs = [];
|
|
5785
5883
|
for (const relPath of selectedFilesForCoverage) {
|
|
5786
5884
|
coverageFromArgs.push("--collectCoverageFrom", relPath);
|
|
@@ -5794,14 +5892,17 @@ var program = async () => {
|
|
|
5794
5892
|
"--config",
|
|
5795
5893
|
cfg,
|
|
5796
5894
|
"--runTestsByPath",
|
|
5797
|
-
|
|
5798
|
-
reporterPath,
|
|
5895
|
+
`--reporters=${reporterPath}`,
|
|
5799
5896
|
"--silent",
|
|
5800
5897
|
"--colors",
|
|
5801
5898
|
"--json",
|
|
5802
5899
|
"--outputFile",
|
|
5803
5900
|
outJson,
|
|
5804
|
-
...
|
|
5901
|
+
...sanitizedJestRunArgs,
|
|
5902
|
+
...collectCoverage ? [
|
|
5903
|
+
"--coverageDirectory",
|
|
5904
|
+
path10.join("coverage", "jest", path10.basename(cfg).replace(/[^a-zA-Z0-9_.-]+/g, "_"))
|
|
5905
|
+
] : [],
|
|
5805
5906
|
...coverageFromArgs,
|
|
5806
5907
|
"--passWithNoTests",
|
|
5807
5908
|
...files
|
|
@@ -5827,10 +5928,24 @@ var program = async () => {
|
|
|
5827
5928
|
const jsonText = fsSync3.readFileSync(outJson, "utf8");
|
|
5828
5929
|
const parsed = JSON.parse(jsonText);
|
|
5829
5930
|
const bridge = coerceJestJsonToBridge(parsed);
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5931
|
+
allBridgeJson.push(bridge);
|
|
5932
|
+
try {
|
|
5933
|
+
const reordered = {
|
|
5934
|
+
...bridge,
|
|
5935
|
+
testResults: sortTestResultsWithRank(fileRank, bridge.testResults).reverse()
|
|
5936
|
+
};
|
|
5937
|
+
pretty = renderVitestFromJestJSON(reordered, {
|
|
5938
|
+
cwd: repoRootForDiscovery,
|
|
5939
|
+
...editorCmd !== void 0 ? { editorCmd } : {},
|
|
5940
|
+
onlyFailures
|
|
5941
|
+
});
|
|
5942
|
+
} catch {
|
|
5943
|
+
pretty = renderVitestFromJestJSON(bridge, {
|
|
5944
|
+
cwd: repoRootForDiscovery,
|
|
5945
|
+
...editorCmd !== void 0 ? { editorCmd } : {},
|
|
5946
|
+
onlyFailures
|
|
5947
|
+
});
|
|
5948
|
+
}
|
|
5834
5949
|
if (debug) {
|
|
5835
5950
|
const preview = pretty.split("\n").slice(0, 3).join("\n");
|
|
5836
5951
|
console.info(`pretty preview (json):
|
|
@@ -5845,7 +5960,8 @@ ${preview}${pretty.includes("\n") ? "\n\u2026" : ""}`);
|
|
|
5845
5960
|
}
|
|
5846
5961
|
const renderOpts = {
|
|
5847
5962
|
cwd: repoRootForDiscovery,
|
|
5848
|
-
...editorCmd !== void 0 ? { editorCmd } : {}
|
|
5963
|
+
...editorCmd !== void 0 ? { editorCmd } : {},
|
|
5964
|
+
onlyFailures
|
|
5849
5965
|
};
|
|
5850
5966
|
pretty = formatJestOutputVitest(output, renderOpts);
|
|
5851
5967
|
if (debug) {
|
|
@@ -5854,9 +5970,7 @@ ${preview}${pretty.includes("\n") ? "\n\u2026" : ""}`);
|
|
|
5854
5970
|
${preview}${pretty.includes("\n") ? "\n\u2026" : ""}`);
|
|
5855
5971
|
}
|
|
5856
5972
|
}
|
|
5857
|
-
|
|
5858
|
-
pretty = stripFooter(pretty);
|
|
5859
|
-
}
|
|
5973
|
+
pretty = stripFooter(pretty);
|
|
5860
5974
|
if (pretty.trim().length > 0) {
|
|
5861
5975
|
process.stdout.write(pretty.endsWith("\n") ? pretty : `${pretty}
|
|
5862
5976
|
`);
|
|
@@ -5868,15 +5982,70 @@ ${preview}${pretty.includes("\n") ? "\n\u2026" : ""}`);
|
|
|
5868
5982
|
} else {
|
|
5869
5983
|
console.info("Jest run skipped based on selection and thresholds.");
|
|
5870
5984
|
}
|
|
5871
|
-
if (
|
|
5872
|
-
|
|
5985
|
+
if (allBridgeJson.length > 0) {
|
|
5986
|
+
const agg = allBridgeJson.map((bridge) => bridge.aggregated);
|
|
5987
|
+
const sum = (select) => agg.reduce((total, item) => total + (select(item) || 0), 0);
|
|
5988
|
+
const startTime = Math.min(
|
|
5989
|
+
...allBridgeJson.map((bridge) => Number(bridge.startTime || Date.now()))
|
|
5990
|
+
);
|
|
5991
|
+
const unified = {
|
|
5992
|
+
startTime,
|
|
5993
|
+
testResults: allBridgeJson.flatMap((bridge) => bridge.testResults),
|
|
5994
|
+
aggregated: {
|
|
5995
|
+
numTotalTestSuites: sum((item) => item.numTotalTestSuites),
|
|
5996
|
+
numPassedTestSuites: sum((item) => item.numPassedTestSuites),
|
|
5997
|
+
numFailedTestSuites: sum((item) => item.numFailedTestSuites),
|
|
5998
|
+
numTotalTests: sum((item) => item.numTotalTests),
|
|
5999
|
+
numPassedTests: sum((item) => item.numPassedTests),
|
|
6000
|
+
numFailedTests: sum((item) => item.numFailedTests),
|
|
6001
|
+
numPendingTests: sum((item) => item.numPendingTests),
|
|
6002
|
+
numTodoTests: sum((item) => item.numTodoTests),
|
|
6003
|
+
startTime,
|
|
6004
|
+
success: agg.every((item) => Boolean(item.success)),
|
|
6005
|
+
runTimeMs: sum((item) => Number(item.runTimeMs ?? 0))
|
|
6006
|
+
}
|
|
6007
|
+
};
|
|
6008
|
+
try {
|
|
6009
|
+
const prodSeeds = (() => {
|
|
6010
|
+
const changedAbs = (changedSelectionAbs ?? []).map(
|
|
6011
|
+
(absPath) => path10.resolve(absPath).replace(/\\/g, "/")
|
|
6012
|
+
);
|
|
6013
|
+
const selAbs = selectionPathsAugmented.map(
|
|
6014
|
+
(pathToken) => path10.resolve(pathToken).replace(/\\/g, "/")
|
|
6015
|
+
);
|
|
6016
|
+
return (changedAbs.length ? changedAbs : selAbs).filter(
|
|
6017
|
+
(abs) => /[\\/]/.test(abs) && !/(^|\/)tests?\//i.test(abs) && !/\.(test|spec)\.[tj]sx?$/i.test(abs)
|
|
6018
|
+
);
|
|
6019
|
+
})();
|
|
6020
|
+
const unifiedRank = await computeDirectnessRank({
|
|
6021
|
+
repoRoot: repoRootForDiscovery,
|
|
6022
|
+
productionSeeds: prodSeeds
|
|
6023
|
+
});
|
|
6024
|
+
const ordered = sortTestResultsWithRank(unifiedRank, unified.testResults).reverse();
|
|
6025
|
+
unified.testResults = ordered;
|
|
6026
|
+
} catch {
|
|
6027
|
+
}
|
|
6028
|
+
const text = renderVitestFromJestJSON(unified, {
|
|
6029
|
+
cwd: repoRootForDiscovery,
|
|
6030
|
+
...editorCmd !== void 0 ? { editorCmd } : {},
|
|
6031
|
+
onlyFailures
|
|
6032
|
+
});
|
|
6033
|
+
if (text.trim().length > 0) {
|
|
6034
|
+
process.stdout.write(text.endsWith("\n") ? text : `${text}
|
|
6035
|
+
`);
|
|
6036
|
+
}
|
|
6037
|
+
}
|
|
6038
|
+
const finalExitCode = jestExitCode;
|
|
6039
|
+
if (collectCoverage && shouldRunJest && coverageAbortOnFailure && finalExitCode !== 0) {
|
|
6040
|
+
process.exit(finalExitCode);
|
|
6041
|
+
return;
|
|
5873
6042
|
}
|
|
5874
6043
|
if (collectCoverage && shouldRunJest) {
|
|
5875
6044
|
await mergeLcov();
|
|
5876
6045
|
const repoRoot = workspaceRoot ?? await findRepoRoot();
|
|
5877
6046
|
const mergedOptsBase = {
|
|
5878
|
-
selectionSpecified,
|
|
5879
|
-
selectionPaths,
|
|
6047
|
+
selectionSpecified: selectionSpecifiedAugmented,
|
|
6048
|
+
selectionPaths: selectionPathsAugmented,
|
|
5880
6049
|
includeGlobs,
|
|
5881
6050
|
excludeGlobs,
|
|
5882
6051
|
workspaceRoot: repoRoot,
|
|
@@ -5891,7 +6060,6 @@ ${preview}${pretty.includes("\n") ? "\n\u2026" : ""}`);
|
|
|
5891
6060
|
};
|
|
5892
6061
|
await emitMergedCoverage(coverageUi, mergedOptsBase);
|
|
5893
6062
|
}
|
|
5894
|
-
const finalExitCode = jestExitCode;
|
|
5895
6063
|
process.exit(finalExitCode);
|
|
5896
6064
|
};
|
|
5897
6065
|
|