headlamp 0.1.15 → 0.1.17
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 +16 -0
- package/dist/cli.cjs +78 -22
- package/dist/cli.cjs.map +2 -2
- package/dist/index.js +78 -22
- package/dist/index.js.map +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -69,6 +69,22 @@ npx headlamp --onlyFailures
|
|
|
69
69
|
npx headlamp --changed --onlyFailures
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
+
- `--showLogs[=true|false]`:
|
|
73
|
+
- When enabled, Headlamp prints a dedicated "Logs" section under each failing test and failing file with the full console output captured by the runner.
|
|
74
|
+
- By default (without this flag), Headlamp shows a condensed "Console errors" snippet with only the most relevant error messages. `--showLogs` includes all console entries (log/info/warn/error).
|
|
75
|
+
- Supported forms: `--showLogs`, `--showLogs=true`, `--showLogs=false`.
|
|
76
|
+
- Works alongside `--onlyFailures`, coverage flags, and selection flags.
|
|
77
|
+
|
|
78
|
+
Examples:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Always include the full console output for each failure
|
|
82
|
+
npx headlamp --showLogs
|
|
83
|
+
|
|
84
|
+
# Combine with only failures visible during the run
|
|
85
|
+
npx headlamp --onlyFailures --showLogs
|
|
86
|
+
```
|
|
87
|
+
|
|
72
88
|
## Changed-file selection
|
|
73
89
|
|
|
74
90
|
- `--changed[=mode]` selects tests by files changed in your working tree or branch.
|
package/dist/cli.cjs
CHANGED
|
@@ -249,6 +249,7 @@ var init_args = __esm({
|
|
|
249
249
|
coverageUi: (value) => ({ type: "coverageUi", value }),
|
|
250
250
|
coverageAbortOnFailure: (value) => ({ type: "coverageAbortOnFailure", value }),
|
|
251
251
|
onlyFailures: (value) => ({ type: "onlyFailures", value }),
|
|
252
|
+
showLogs: (value) => ({ type: "showLogs", value }),
|
|
252
253
|
jestArg: (value) => ({ type: "jestArg", value }),
|
|
253
254
|
jestArgs: (values) => ({ type: "jestArgs", values }),
|
|
254
255
|
vitestArg: (value) => ({ type: "vitestArg", value }),
|
|
@@ -415,6 +416,16 @@ var init_args = __esm({
|
|
|
415
416
|
"--onlyFailures",
|
|
416
417
|
(_flag, lookahead) => step([ActionBuilders.onlyFailures(isTruthy(String(lookahead)))], true)
|
|
417
418
|
),
|
|
419
|
+
// --showLogs flag (boolean)
|
|
420
|
+
rule.eq("--showLogs", () => step([ActionBuilders.showLogs(true)])),
|
|
421
|
+
rule.startsWith(
|
|
422
|
+
"--showLogs=",
|
|
423
|
+
(value) => step([ActionBuilders.showLogs(isTruthy((value.split("=")[1] ?? "").trim().toLowerCase()))])
|
|
424
|
+
),
|
|
425
|
+
rule.withLookahead(
|
|
426
|
+
"--showLogs",
|
|
427
|
+
(_flag, lookahead) => step([ActionBuilders.showLogs(isTruthy(String(lookahead)))], true)
|
|
428
|
+
),
|
|
418
429
|
rule.withLookahead(
|
|
419
430
|
"--testPathPattern",
|
|
420
431
|
(flag, lookahead) => step([ActionBuilders.jestArgs([flag, lookahead])], true)
|
|
@@ -573,6 +584,8 @@ var init_args = __esm({
|
|
|
573
584
|
return { vitest: [], jest: [], coverage: false, coverageAbortOnFailure: action.value };
|
|
574
585
|
case "onlyFailures":
|
|
575
586
|
return { vitest: [], jest: [], coverage: false, onlyFailures: action.value };
|
|
587
|
+
case "showLogs":
|
|
588
|
+
return { vitest: [], jest: [], coverage: false, showLogs: action.value };
|
|
576
589
|
case "jestArgs":
|
|
577
590
|
return { vitest: [], jest: action.values, coverage: false };
|
|
578
591
|
case "selectionHint":
|
|
@@ -648,6 +661,7 @@ var init_args = __esm({
|
|
|
648
661
|
...right.changedDepth !== void 0 || left.changedDepth !== void 0 ? { changedDepth: right.changedDepth ?? left.changedDepth } : {},
|
|
649
662
|
...right.coverageAbortOnFailure !== void 0 || left.coverageAbortOnFailure !== void 0 ? { coverageAbortOnFailure: right.coverageAbortOnFailure ?? left.coverageAbortOnFailure } : {},
|
|
650
663
|
...right.onlyFailures !== void 0 || left.onlyFailures !== void 0 ? { onlyFailures: right.onlyFailures ?? left.onlyFailures } : {},
|
|
664
|
+
...right.showLogs !== void 0 || left.showLogs !== void 0 ? { showLogs: right.showLogs ?? left.showLogs } : {},
|
|
651
665
|
...right.coverageDetail !== void 0 || left.coverageDetail !== void 0 ? { coverageDetail: right.coverageDetail ?? left.coverageDetail } : {},
|
|
652
666
|
...right.coverageShowCode !== void 0 || left.coverageShowCode !== void 0 ? { coverageShowCode: right.coverageShowCode ?? left.coverageShowCode } : {},
|
|
653
667
|
...right.coverageMode !== void 0 || left.coverageMode !== void 0 ? { coverageMode: right.coverageMode ?? left.coverageMode } : {},
|
|
@@ -672,6 +686,7 @@ var init_args = __esm({
|
|
|
672
686
|
let coverageUi = "both";
|
|
673
687
|
let coverageAbortOnFailure = false;
|
|
674
688
|
let onlyFailures = false;
|
|
689
|
+
let showLogs = false;
|
|
675
690
|
let coverageShowCode = Boolean(process.stdout.isTTY);
|
|
676
691
|
let coverageMode = "auto";
|
|
677
692
|
const coverageMaxFilesLocalInit = void 0;
|
|
@@ -690,6 +705,7 @@ var init_args = __esm({
|
|
|
690
705
|
coverageUi = contrib.coverageUi ?? coverageUi;
|
|
691
706
|
coverageAbortOnFailure = contrib.coverageAbortOnFailure ?? coverageAbortOnFailure;
|
|
692
707
|
onlyFailures = contrib.onlyFailures ?? onlyFailures;
|
|
708
|
+
showLogs = contrib.showLogs ?? showLogs;
|
|
693
709
|
coverageShowCode = contrib.coverageShowCode ?? coverageShowCode;
|
|
694
710
|
const coverageDetailComputed = contrib.coverageDetail ?? (contrib.selection ? "auto" : void 0);
|
|
695
711
|
coverageMode = contrib.coverageMode ?? (contrib.selection ? "compact" : "auto");
|
|
@@ -724,6 +740,7 @@ var init_args = __esm({
|
|
|
724
740
|
coverageUi,
|
|
725
741
|
coverageAbortOnFailure,
|
|
726
742
|
onlyFailures,
|
|
743
|
+
showLogs,
|
|
727
744
|
selectionSpecified: Boolean(contrib.selection),
|
|
728
745
|
selectionPaths: [...contrib.selectionPaths ?? []],
|
|
729
746
|
includeGlobs,
|
|
@@ -5089,24 +5106,43 @@ var buildStackSection = (mergedForStack, ctx, fallbackLoc) => {
|
|
|
5089
5106
|
};
|
|
5090
5107
|
var MAX_CONSOLE_ERRORS_TO_SHOW = 3;
|
|
5091
5108
|
var isConsoleEntry = (candidate) => typeof candidate === "object" && candidate !== null;
|
|
5092
|
-
var buildConsoleSection = (maybeConsole) => {
|
|
5109
|
+
var buildConsoleSection = (maybeConsole, opts) => {
|
|
5093
5110
|
const out = [];
|
|
5094
5111
|
if (!Array.isArray(maybeConsole)) {
|
|
5095
5112
|
return out;
|
|
5096
5113
|
}
|
|
5097
5114
|
const entries = maybeConsole.filter(isConsoleEntry);
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5115
|
+
if (opts?.full) {
|
|
5116
|
+
const toMsg = (entry) => {
|
|
5117
|
+
const type = String(entry?.type ?? "").toLowerCase();
|
|
5118
|
+
const raw = entry?.message;
|
|
5119
|
+
const msg = Array.isArray(raw) ? raw.map(String).join(" ") : typeof raw === "string" ? raw : String(raw ?? "");
|
|
5120
|
+
const origin = String(entry?.origin ?? "");
|
|
5121
|
+
const typeFmt = type ? `${ansi.white(type)}: ` : "";
|
|
5122
|
+
const originFmt = origin ? ` ${ansi.dim(`(${origin})`)}` : "";
|
|
5123
|
+
return ` ${ansi.dim("\u2022")} ${typeFmt}${msg}${originFmt}`;
|
|
5124
|
+
};
|
|
5125
|
+
const lines = entries.map(toMsg).filter((ln) => stripAnsiSimple(ln).trim().length > 0);
|
|
5126
|
+
if (lines.length) {
|
|
5127
|
+
out.push(ansi.dim(" Logs:"));
|
|
5128
|
+
out.push(...lines, "");
|
|
5129
|
+
}
|
|
5130
|
+
} else {
|
|
5131
|
+
const errorsOnly = entries.filter(
|
|
5132
|
+
(entry) => String(entry?.type ?? "").toLowerCase() === "error"
|
|
5133
|
+
);
|
|
5134
|
+
const scored = errorsOnly.map((entry) => {
|
|
5135
|
+
const raw = entry?.message;
|
|
5136
|
+
const msg = Array.isArray(raw) ? raw.map(String).join(" ") : typeof raw === "string" ? raw : String(raw ?? "");
|
|
5137
|
+
return { msg, score: msg.length };
|
|
5138
|
+
}).filter((item) => item.msg.trim().length > 0).sort((left, right) => right.score - left.score).slice(0, MAX_CONSOLE_ERRORS_TO_SHOW);
|
|
5139
|
+
if (scored.length) {
|
|
5140
|
+
out.push(ansi.dim(" Console errors:"));
|
|
5141
|
+
for (const item of scored) {
|
|
5142
|
+
out.push(` ${ansi.dim("\u2022")} ${item.msg}`);
|
|
5143
|
+
}
|
|
5144
|
+
out.push("");
|
|
5108
5145
|
}
|
|
5109
|
-
out.push("");
|
|
5110
5146
|
}
|
|
5111
5147
|
return out;
|
|
5112
5148
|
};
|
|
@@ -5168,8 +5204,8 @@ var buildThrownSection = (details) => {
|
|
|
5168
5204
|
}
|
|
5169
5205
|
};
|
|
5170
5206
|
const candidates = [];
|
|
5171
|
-
for (const
|
|
5172
|
-
const obj =
|
|
5207
|
+
for (const detailEntry of details) {
|
|
5208
|
+
const obj = detailEntry && typeof detailEntry === "object" ? detailEntry : null;
|
|
5173
5209
|
if (obj && obj.error && typeof obj.error === "object") {
|
|
5174
5210
|
const err = obj.error;
|
|
5175
5211
|
if (typeof err.name === "string") {
|
|
@@ -5366,7 +5402,7 @@ var renderChunks = (chunks, ctx, fns, opts) => {
|
|
|
5366
5402
|
|
|
5367
5403
|
// src/lib/formatter/context.ts
|
|
5368
5404
|
var fs5 = __toESM(require("node:fs"), 1);
|
|
5369
|
-
var makeCtx = (opts, showStacks = false) => {
|
|
5405
|
+
var makeCtx = (opts, showStacks = false, showLogs = false) => {
|
|
5370
5406
|
const cwd = (opts?.cwd ?? process.cwd()).replace(/\\/g, "/");
|
|
5371
5407
|
const width = Math.max(
|
|
5372
5408
|
40,
|
|
@@ -5382,7 +5418,15 @@ var makeCtx = (opts, showStacks = false) => {
|
|
|
5382
5418
|
return [];
|
|
5383
5419
|
}
|
|
5384
5420
|
};
|
|
5385
|
-
return {
|
|
5421
|
+
return {
|
|
5422
|
+
cwd,
|
|
5423
|
+
width,
|
|
5424
|
+
showStacks,
|
|
5425
|
+
showLogs,
|
|
5426
|
+
projectHint,
|
|
5427
|
+
editorCmd: opts?.editorCmd,
|
|
5428
|
+
readSource: readSource2
|
|
5429
|
+
};
|
|
5386
5430
|
};
|
|
5387
5431
|
|
|
5388
5432
|
// src/lib/formatter/bridge/tryBridgeFallback.ts
|
|
@@ -5704,7 +5748,9 @@ var renderFileLevelFailure = (file, ctx) => {
|
|
|
5704
5748
|
suppressDiff: pretty.length > 0,
|
|
5705
5749
|
stackPreview
|
|
5706
5750
|
});
|
|
5707
|
-
const consoleBlock = buildConsoleSection(stripBridgeEventsFromConsole(file.console ?? null)
|
|
5751
|
+
const consoleBlock = buildConsoleSection(stripBridgeEventsFromConsole(file.console ?? null), {
|
|
5752
|
+
full: Boolean(ctx.showLogs)
|
|
5753
|
+
});
|
|
5708
5754
|
const stackTail = ctx.showStacks && stackPreview.length === 0 ? (() => {
|
|
5709
5755
|
const tail = mergedForStack.filter((ln) => isStackLine(stripAnsiSimple(ln))).slice(-4).map((ln) => ` ${colorStackLine(String(ln), ctx.projectHint)}`);
|
|
5710
5756
|
return tail.length ? [ansi.dim(" Stack:"), ...tail, ""] : empty;
|
|
@@ -6019,7 +6065,9 @@ var renderFailedAssertion = (args) => {
|
|
|
6019
6065
|
return empty;
|
|
6020
6066
|
}
|
|
6021
6067
|
})() : empty;
|
|
6022
|
-
const consoleBlock = buildConsoleSection(stripBridgeEventsFromConsole(file.console ?? null)
|
|
6068
|
+
const consoleBlock = buildConsoleSection(stripBridgeEventsFromConsole(file.console ?? null), {
|
|
6069
|
+
full: Boolean(ctx.showLogs)
|
|
6070
|
+
});
|
|
6023
6071
|
const stackTail = ctx.showStacks && stackPreview.length === 0 ? (() => {
|
|
6024
6072
|
const merged = collapseStacks([...msgLines, ...details.stacks]);
|
|
6025
6073
|
const tail = collapseStacks(merged).filter((ln) => isStackLine(stripAnsiSimple(ln))).slice(-4).map((ln) => ` ${colorStackLine(String(ln), ctx.projectHint)}`);
|
|
@@ -6116,7 +6164,11 @@ var formatJestOutputVitest = (raw, opts) => pipe(
|
|
|
6116
6164
|
{ raw, opts },
|
|
6117
6165
|
(state) => ({
|
|
6118
6166
|
...state,
|
|
6119
|
-
ctx: makeCtx(
|
|
6167
|
+
ctx: makeCtx(
|
|
6168
|
+
state.opts,
|
|
6169
|
+
/\bFAIL\b/.test(stripAnsiSimple(state.raw)),
|
|
6170
|
+
Boolean(state.opts?.showLogs)
|
|
6171
|
+
)
|
|
6120
6172
|
}),
|
|
6121
6173
|
(state) => ({ ...state, chunks: parseChunks(state.raw) }),
|
|
6122
6174
|
(state) => ({
|
|
@@ -6471,6 +6523,7 @@ var program = async () => {
|
|
|
6471
6523
|
coverageUi,
|
|
6472
6524
|
coverageAbortOnFailure,
|
|
6473
6525
|
onlyFailures,
|
|
6526
|
+
showLogs,
|
|
6474
6527
|
selectionSpecified,
|
|
6475
6528
|
selectionPaths,
|
|
6476
6529
|
includeGlobs,
|
|
@@ -7173,7 +7226,8 @@ var program = async () => {
|
|
|
7173
7226
|
reordered,
|
|
7174
7227
|
makeCtx(
|
|
7175
7228
|
{ cwd: repoRootForDiscovery, ...editorCmd !== void 0 ? { editorCmd } : {} },
|
|
7176
|
-
/\bFAIL\b/.test(stripAnsiSimple(output))
|
|
7229
|
+
/\bFAIL\b/.test(stripAnsiSimple(output)),
|
|
7230
|
+
Boolean(showLogs)
|
|
7177
7231
|
),
|
|
7178
7232
|
{ onlyFailures }
|
|
7179
7233
|
);
|
|
@@ -7182,7 +7236,8 @@ var program = async () => {
|
|
|
7182
7236
|
bridge,
|
|
7183
7237
|
makeCtx(
|
|
7184
7238
|
{ cwd: repoRootForDiscovery, ...editorCmd !== void 0 ? { editorCmd } : {} },
|
|
7185
|
-
/\bFAIL\b/.test(stripAnsiSimple(output))
|
|
7239
|
+
/\bFAIL\b/.test(stripAnsiSimple(output)),
|
|
7240
|
+
Boolean(showLogs)
|
|
7186
7241
|
),
|
|
7187
7242
|
{ onlyFailures }
|
|
7188
7243
|
);
|
|
@@ -7284,7 +7339,8 @@ ${stripFooter(rawAlso)}`.trimEnd();
|
|
|
7284
7339
|
unified,
|
|
7285
7340
|
makeCtx(
|
|
7286
7341
|
{ cwd: repoRootForDiscovery, ...editorCmd !== void 0 ? { editorCmd } : {} },
|
|
7287
|
-
showStacks
|
|
7342
|
+
showStacks,
|
|
7343
|
+
Boolean(showLogs)
|
|
7288
7344
|
),
|
|
7289
7345
|
{ onlyFailures }
|
|
7290
7346
|
);
|