@andy2639/jest-context 1.0.0 → 1.0.2
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/CHANGELOG.md +12 -0
- package/README.md +23 -1
- package/dist/bin/console-context.cjs +31 -8
- package/dist/bin/console-context.cjs.map +1 -1
- package/dist/bin/console-context.mjs +2 -2
- package/dist/bin/coverage-context.cjs +47 -30
- package/dist/bin/coverage-context.cjs.map +1 -1
- package/dist/bin/coverage-context.mjs +2 -2
- package/dist/bin/jest-context-init.cjs +142 -0
- package/dist/bin/jest-context-init.cjs.map +1 -0
- package/dist/bin/jest-context-init.d.mts +1 -0
- package/dist/bin/jest-context-init.d.ts +1 -0
- package/dist/bin/jest-context-init.mjs +14 -0
- package/dist/bin/jest-context-init.mjs.map +1 -0
- package/dist/bin/test-context.cjs +30 -7
- package/dist/bin/test-context.cjs.map +1 -1
- package/dist/bin/test-context.mjs +2 -2
- package/dist/{chunk-WPFTKCAT.mjs → chunk-5QGDUTB3.mjs} +4 -4
- package/dist/chunk-5QGDUTB3.mjs.map +1 -0
- package/dist/{chunk-YTFA3KPD.mjs → chunk-GV4AYRBZ.mjs} +43 -25
- package/dist/chunk-GV4AYRBZ.mjs.map +1 -0
- package/dist/{chunk-DUQBPBV4.mjs → chunk-RCPJ7B43.mjs} +4 -4
- package/dist/{chunk-DUQBPBV4.mjs.map → chunk-RCPJ7B43.mjs.map} +1 -1
- package/dist/chunk-UPBDVC5T.mjs +71 -0
- package/dist/chunk-UPBDVC5T.mjs.map +1 -0
- package/dist/{chunk-DEJBEL4M.mjs → chunk-WEP26C5H.mjs} +10 -11
- package/dist/chunk-WEP26C5H.mjs.map +1 -0
- package/dist/index.cjs +115 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.mjs +8 -4
- package/package.json +3 -3
- package/dist/chunk-DEJBEL4M.mjs.map +0 -1
- package/dist/chunk-WPFTKCAT.mjs.map +0 -1
- package/dist/chunk-YTFA3KPD.mjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.2
|
|
4
|
+
|
|
5
|
+
- Remove `cli-progress` usage and standardize all commands on spinner loaders
|
|
6
|
+
- Update banners to `JEST TEST`, `JEST COVERAGE`, and `JEST CONSOLE`
|
|
7
|
+
- Add `jest-context-init` CLI to inject context scripts into project `package.json`
|
|
8
|
+
- Remove `cli-progress` dependency from the package
|
|
9
|
+
|
|
10
|
+
## 1.0.1
|
|
11
|
+
|
|
12
|
+
- Add safe UI fallbacks when spinner/progress dependencies are incompatible at runtime
|
|
13
|
+
- Prevent `coverage-context` from crashing if `cli-progress` fails to initialize
|
|
14
|
+
|
|
3
15
|
## 1.0.0
|
|
4
16
|
|
|
5
17
|
- Promote package to stable release
|
package/README.md
CHANGED
|
@@ -7,7 +7,8 @@ CLI and core utilities to extract Jest context in LLM-friendly format.
|
|
|
7
7
|
- `test-context`: summarize failed tests
|
|
8
8
|
- `coverage-context`: show files below coverage threshold
|
|
9
9
|
- `console-context`: collect console warnings/errors from tests
|
|
10
|
-
-
|
|
10
|
+
- `jest-context-init`: inject context scripts into project `package.json`
|
|
11
|
+
- terminal UX with `ora` and `cfonts`
|
|
11
12
|
|
|
12
13
|
## Installation
|
|
13
14
|
|
|
@@ -21,6 +22,27 @@ pnpm add -D @andy2639/jest-context
|
|
|
21
22
|
test-context --all
|
|
22
23
|
coverage-context --threshold=90
|
|
23
24
|
console-context --all --only-errors
|
|
25
|
+
jest-context-init
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Bootstrap Scripts
|
|
29
|
+
|
|
30
|
+
Run this in any project where you want the context scripts:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npx @andy2639/jest-context jest-context-init
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
It creates/updates:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"scripts": {
|
|
41
|
+
"console:context": "console-context",
|
|
42
|
+
"coverage:context": "coverage-context",
|
|
43
|
+
"test:context": "test-context"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
24
46
|
```
|
|
25
47
|
|
|
26
48
|
## Flags
|
|
@@ -87,7 +87,7 @@ async function execCommand(cmd, args = [], options = {}) {
|
|
|
87
87
|
return new Promise((resolve, reject) => {
|
|
88
88
|
const resolvedCmd = resolveCommand(cmd);
|
|
89
89
|
const child = (0, import_node_child_process.spawn)(resolvedCmd, args, {
|
|
90
|
-
shell: options.shell ??
|
|
90
|
+
shell: options.shell ?? false
|
|
91
91
|
});
|
|
92
92
|
let stdout = "";
|
|
93
93
|
let stderr = "";
|
|
@@ -167,6 +167,7 @@ async function runJest(args = [], options = {}) {
|
|
|
167
167
|
disableVerbose = false
|
|
168
168
|
} = options;
|
|
169
169
|
const jestCmd = getJestCommand(packageManager);
|
|
170
|
+
const command = resolveCommand(jestCmd[0]);
|
|
170
171
|
const jestArgs = [...jestCmd.slice(1)];
|
|
171
172
|
if (verbose && !disableVerbose) {
|
|
172
173
|
jestArgs.push("--verbose");
|
|
@@ -184,8 +185,8 @@ async function runJest(args = [], options = {}) {
|
|
|
184
185
|
}
|
|
185
186
|
jestArgs.push(...args);
|
|
186
187
|
return new Promise((resolve, reject) => {
|
|
187
|
-
const child = (0, import_node_child_process2.spawn)(
|
|
188
|
-
shell:
|
|
188
|
+
const child = (0, import_node_child_process2.spawn)(command, jestArgs, {
|
|
189
|
+
shell: false
|
|
189
190
|
});
|
|
190
191
|
let stdout = "";
|
|
191
192
|
let stderr = "";
|
|
@@ -404,6 +405,7 @@ function logWarning(message) {
|
|
|
404
405
|
}
|
|
405
406
|
|
|
406
407
|
// src/core/ui.ts
|
|
408
|
+
var hasWarnedSpinnerFallback = false;
|
|
407
409
|
function shouldShowUI(exportMode, noBanner = false) {
|
|
408
410
|
return !exportMode && !noBanner && Boolean(process.stdout.isTTY);
|
|
409
411
|
}
|
|
@@ -449,9 +451,30 @@ function displayBanner(config) {
|
|
|
449
451
|
console.log(boxed);
|
|
450
452
|
}
|
|
451
453
|
function createSpinner(text, color = "cyan") {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
}
|
|
454
|
+
try {
|
|
455
|
+
const ora = require("ora");
|
|
456
|
+
return ora({ text, color, spinner: "dots" });
|
|
457
|
+
} catch {
|
|
458
|
+
if (!hasWarnedSpinnerFallback) {
|
|
459
|
+
hasWarnedSpinnerFallback = true;
|
|
460
|
+
console.warn("Warning: spinner UI unavailable, continuing without spinner.");
|
|
461
|
+
}
|
|
462
|
+
return {
|
|
463
|
+
start: () => NOOP_SPINNER,
|
|
464
|
+
stop: () => NOOP_SPINNER,
|
|
465
|
+
succeed: () => NOOP_SPINNER,
|
|
466
|
+
warn: () => NOOP_SPINNER,
|
|
467
|
+
fail: () => NOOP_SPINNER
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
var NOOP_SPINNER = {
|
|
472
|
+
start: () => NOOP_SPINNER,
|
|
473
|
+
stop: () => NOOP_SPINNER,
|
|
474
|
+
succeed: () => NOOP_SPINNER,
|
|
475
|
+
warn: () => NOOP_SPINNER,
|
|
476
|
+
fail: () => NOOP_SPINNER
|
|
477
|
+
};
|
|
455
478
|
|
|
456
479
|
// src/commands/console-context.ts
|
|
457
480
|
function parseConsoleWarnings(rawOutput) {
|
|
@@ -635,8 +658,8 @@ async function runConsoleContext(argv = process.argv.slice(2)) {
|
|
|
635
658
|
const showUI = shouldShowUI(exportFormat, noBanner);
|
|
636
659
|
if (showUI) {
|
|
637
660
|
displayBanner({
|
|
638
|
-
text: "
|
|
639
|
-
subtitle: "
|
|
661
|
+
text: "JEST",
|
|
662
|
+
subtitle: "CONSOLE",
|
|
640
663
|
info: {
|
|
641
664
|
Mode: mode,
|
|
642
665
|
Filter: filter ?? "none"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/commands/console-context.ts","../../src/core/constants.ts","../../src/core/platform.ts","../../src/core/package-manager.ts","../../src/core/exec.ts","../../src/core/git.ts","../../src/core/jest.ts","../../src/core/parsing.ts","../../src/core/export.ts","../../src/core/cli.ts","../../src/core/ui.ts","../../src/bin/console-context.ts"],"sourcesContent":["import path from \"node:path\";\n\nimport {\n buildJestArgsForMode,\n CONSOLE_LOG_TYPES,\n createSpinner,\n displayBanner,\n displayHelp,\n exitWithError,\n extractConsoleType,\n getDisplayTimestamp,\n handleExportOrDisplay,\n isCodeSnippetLine,\n isConsoleTypeLine,\n isStackTraceLine,\n JEST_PATTERNS,\n logWarning,\n parseExportCliArgs,\n runJest,\n shouldShowUI,\n stripAnsi,\n validateCliArgs,\n VALID_MODES,\n} from \"../core\";\n\ntype ParsedWarning = {\n type: string;\n testFile: string;\n messages: string[];\n};\n\nfunction parseConsoleWarnings(rawOutput: string): ParsedWarning[] {\n const lines = rawOutput.split(\"\\n\");\n const warnings: ParsedWarning[] = [];\n\n const state: {\n currentTestFile: string | null;\n currentWarning: ParsedWarning | null;\n pendingWarnings: ParsedWarning[];\n } = {\n currentTestFile: null,\n currentWarning: null,\n pendingWarnings: [],\n };\n\n const flushCurrentWarning = () => {\n if (!state.currentWarning) return;\n\n if (state.currentWarning.testFile === \"unknown\" && state.currentTestFile) {\n state.currentWarning.testFile = state.currentTestFile;\n }\n\n warnings.push(state.currentWarning);\n state.pendingWarnings.push(state.currentWarning);\n state.currentWarning = null;\n };\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n if (JEST_PATTERNS.TEST_FILE.test(trimmed)) {\n const match = trimmed.match(JEST_PATTERNS.TEST_FILE);\n if (match) {\n state.currentTestFile = path.basename(match[2]);\n for (const warning of state.pendingWarnings) {\n if (warning.testFile === \"unknown\") warning.testFile = state.currentTestFile;\n }\n }\n flushCurrentWarning();\n continue;\n }\n\n if (trimmed === \"● Console\") {\n continue;\n }\n\n if (isConsoleTypeLine(line)) {\n flushCurrentWarning();\n state.currentWarning = {\n type: extractConsoleType(line) ?? \"console.warn\",\n testFile: state.currentTestFile ?? \"unknown\",\n messages: [],\n };\n continue;\n }\n\n if (!state.currentWarning) continue;\n if (isCodeSnippetLine(line)) continue;\n if (isStackTraceLine(line)) continue;\n\n const cleanMessage = stripAnsi(line).trim();\n if (cleanMessage.length > 0) {\n state.currentWarning.messages.push(cleanMessage);\n }\n }\n\n flushCurrentWarning();\n\n return warnings;\n}\n\nfunction filterWarningsByType(warnings: ParsedWarning[], filter: \"errors\" | \"warns\" | null): ParsedWarning[] {\n if (filter === \"errors\") {\n return warnings.filter((w) => w.type === CONSOLE_LOG_TYPES.ERROR);\n }\n if (filter === \"warns\") {\n return warnings.filter((w) => w.type === CONSOLE_LOG_TYPES.WARN);\n }\n\n return warnings;\n}\n\nfunction groupByTestFile(warnings: ParsedWarning[]): Record<string, ParsedWarning[]> {\n const grouped: Record<string, ParsedWarning[]> = {};\n\n for (const warning of warnings) {\n const file = warning.testFile;\n if (!grouped[file]) grouped[file] = [];\n grouped[file].push(warning);\n }\n\n return grouped;\n}\n\nfunction sortFilesByWarningCount(grouped: Record<string, ParsedWarning[]>): Array<[string, ParsedWarning[]]> {\n const entries = Object.entries(grouped);\n entries.sort((a, b) => b[1].length - a[1].length);\n\n return entries;\n}\n\nfunction formatWarningsOutput(\n grouped: Record<string, ParsedWarning[]>,\n timestamp: string,\n stats: { total: number; byType: Record<string, number> }\n): string {\n const lines: string[] = [];\n lines.push(\"=== CONSOLE WARNINGS CONTEXT BEGIN ===\", \"\", `📅 Run Date: ${timestamp}`, \"\");\n\n const sortedEntries = sortFilesByWarningCount(grouped);\n const totalFiles = sortedEntries.length;\n\n if (totalFiles === 0) {\n lines.push(\"✅ No console warnings found!\");\n } else {\n lines.push(\n `⚠️ Found ${stats.total} warning(s) in ${totalFiles} test file(s)`,\n \"\",\n \"📊 Summary by Type:\",\n ` - console.error: ${stats.byType[CONSOLE_LOG_TYPES.ERROR] ?? 0} occurrence(s)`,\n ` - console.warn: ${stats.byType[CONSOLE_LOG_TYPES.WARN] ?? 0} occurrence(s)`,\n \"\",\n \"=\".repeat(60),\n \"\"\n );\n\n for (const [file, warnings] of sortedEntries) {\n lines.push(`📄 File: ${file}`, ` Total Warnings: ${warnings.length}`, \"\");\n\n warnings.forEach((warning, idx) => {\n lines.push(` ${idx + 1}. ${warning.type}`, \"\");\n\n if (warning.messages.length > 0) {\n lines.push(\" 📝 Message:\");\n warning.messages.forEach((msg) => lines.push(` ${msg}`));\n lines.push(\"\");\n }\n\n if (idx < warnings.length - 1) {\n lines.push(\" \" + \"-\".repeat(50), \"\");\n }\n });\n\n lines.push(\"=\".repeat(60), \"\");\n }\n }\n\n lines.push(\"=== CONSOLE WARNINGS CONTEXT END ===\");\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction calculateStatistics(warnings: ParsedWarning[]) {\n const stats = {\n total: warnings.length,\n byType: {\n [CONSOLE_LOG_TYPES.ERROR]: 0,\n [CONSOLE_LOG_TYPES.WARN]: 0,\n },\n };\n\n for (const warning of warnings) {\n if (warning.type === CONSOLE_LOG_TYPES.ERROR) {\n stats.byType[CONSOLE_LOG_TYPES.ERROR]++;\n } else if (warning.type === CONSOLE_LOG_TYPES.WARN) {\n stats.byType[CONSOLE_LOG_TYPES.WARN]++;\n }\n }\n\n return stats;\n}\n\nexport async function runConsoleContext(argv = process.argv.slice(2)): Promise<void> {\n if (argv.includes(\"-h\") || argv.includes(\"--help\")) {\n displayHelp(\"Console Context Script\", {\n description: \"Capture and format console warnings/errors from Jest output.\",\n usage: [\n \"console-context -- --all\",\n \"console-context -- --related\",\n \"console-context -- --tests\",\n ],\n options: [\n \"--all Run all tests (default)\",\n \"--related Run tests related to staged files\",\n \"--tests Run only staged test files\",\n \"--only-errors Show only console.error warnings\",\n \"--only-warns Show only console.warn warnings\",\n \"--export Export output as txt\",\n \"--export=txt|md Export output in selected format\",\n \"--no-banner Disable fancy terminal UI\",\n \"-h, --help Show this help\",\n ],\n examples: [\n \"console-context -- --related --only-errors\",\n \"console-context -- --all --export=md\",\n ],\n });\n }\n\n const noBanner = argv.includes(\"--no-banner\");\n const args = argv.filter((arg) => arg !== \"--no-banner\");\n\n const { exportFormat, exportArgs } = parseExportCliArgs(args);\n const { parsed, unknownArgs } = validateCliArgs(args, {\n mode: {\n values: [...VALID_MODES],\n default: \"--all\",\n exclusive: true,\n },\n filter: {\n values: [\"--only-errors\", \"--only-warns\"],\n exclusive: true,\n },\n });\n\n const exportArgSet = new Set(exportArgs);\n const filteredUnknownArgs = unknownArgs.filter((arg) => !exportArgSet.has(arg));\n if (filteredUnknownArgs.length > 0) {\n logWarning(`Unknown arguments ignored: ${filteredUnknownArgs.join(\", \")}`);\n }\n\n const mode = parsed.mode ?? \"--all\";\n const filter = parsed.filter === \"--only-errors\" ? \"errors\" : parsed.filter === \"--only-warns\" ? \"warns\" : null;\n\n const showUI = shouldShowUI(exportFormat, noBanner);\n if (showUI) {\n displayBanner({\n text: \"CONSOLE\",\n subtitle: \"WARNINGS\",\n info: {\n Mode: mode,\n Filter: filter ?? \"none\",\n },\n colors: [\"yellow\", \"red\"],\n });\n }\n\n const modeKey = mode.replace(\"--\", \"\") as \"all\" | \"related\" | \"tests\";\n\n let jestArgs: string[] = [];\n try {\n jestArgs = await buildJestArgsForMode(modeKey);\n } catch (error) {\n exitWithError((error as Error).message);\n }\n\n const spinner = showUI ? createSpinner(\"Capturing console warnings...\", \"yellow\") : null;\n spinner?.start();\n\n const result = await runJest(jestArgs, {\n disableVerbose: true,\n ignoreErrors: true,\n });\n\n let warnings = parseConsoleWarnings(result.output);\n warnings = filterWarningsByType(warnings, filter);\n\n if (spinner) {\n if (warnings.length > 0) {\n spinner.warn(`Found ${warnings.length} warning(s)`);\n } else {\n spinner.succeed(\"No console warnings found\");\n }\n }\n\n const grouped = groupByTestFile(warnings);\n const stats = calculateStatistics(warnings);\n const timestamp = getDisplayTimestamp();\n const formatted = formatWarningsOutput(grouped, timestamp, stats);\n\n handleExportOrDisplay(formatted, {\n exportFormat,\n prefix: \"export-console-context\",\n title: \"Console Warnings Context\",\n });\n}\n","export const VALID_MODES = [\"--all\", \"--related\", \"--tests\"] as const;\n\nexport const VALID_EXPORT_FORMATS = [\"txt\", \"md\"] as const;\n\nexport const VALID_TEST_EXTENSIONS = /\\.(test|spec)\\.(ts|tsx|js|jsx)$/;\n\nexport const CONSOLE_LOG_TYPES = {\n ERROR: \"console.error\",\n WARN: \"console.warn\",\n LOG: \"console.log\",\n DEBUG: \"console.debug\",\n} as const;\n\nexport const JEST_PATTERNS = {\n FAIL_LINE: /^FAIL\\s+/,\n PASS_LINE: /^PASS\\s+/,\n TEST_FILE: /^(PASS|FAIL)\\s+(.+\\.(test|spec)\\.tsx?)/,\n COVERAGE_LINE:\n /^(.+?)\\s+\\|\\s+([\\d.]+)\\s+\\|\\s+([\\d.]+)\\s+\\|\\s+([\\d.]+)\\s+\\|\\s+([\\d.]+)(?:\\s+\\|\\s+(.+))?$/,\n BULLET_POINT: /^●\\s+/,\n CODE_LINE: /^>?\\s*\\d*\\s*\\|/,\n STACK_TRACE: /^\\s+at\\s+/,\n};\n","export function getPlatform(): NodeJS.Platform {\n return process.platform;\n}\n\nexport function isWindows(): boolean {\n return process.platform === \"win32\";\n}\n\nexport function isMac(): boolean {\n return process.platform === \"darwin\";\n}\n\nexport function isLinux(): boolean {\n return process.platform === \"linux\";\n}\n\nexport function resolveCommand(cmd: string): string {\n if (!isWindows()) return cmd;\n\n const windowsCommands: Record<string, string> = {\n git: \"git.exe\",\n node: \"node.exe\",\n npm: \"npm.cmd\",\n npx: \"npx.cmd\",\n yarn: \"yarn.cmd\",\n pnpm: \"pnpm.cmd\",\n };\n\n return windowsCommands[cmd] ?? cmd;\n}\n","export type PackageManager = \"npm\" | \"yarn\" | \"pnpm\";\n\nexport function detectPackageManager(): PackageManager {\n if (process.env.npm_execpath?.includes(\"yarn\")) return \"yarn\";\n if (process.env.npm_execpath?.includes(\"pnpm\")) return \"pnpm\";\n\n return \"npm\";\n}\n\nexport function getJestCommand(packageManager: PackageManager | null = null): [string, string] {\n const pm = packageManager ?? detectPackageManager();\n\n switch (pm) {\n case \"yarn\":\n return [\"yarn\", \"jest\"];\n case \"pnpm\":\n return [\"pnpm\", \"jest\"];\n default:\n return [\"npx\", \"jest\"];\n }\n}\n","import { spawn } from \"node:child_process\";\n\nimport { resolveCommand } from \"./platform\";\nimport type { ExecResult } from \"../types\";\n\nexport async function execCommand(\n cmd: string,\n args: string[] = [],\n options: { shell?: boolean; ignoreErrors?: boolean } = {}\n): Promise<ExecResult> {\n return new Promise((resolve, reject) => {\n const resolvedCmd = resolveCommand(cmd);\n const child = spawn(resolvedCmd, args, {\n shell: options.shell ?? process.platform === \"win32\",\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout?.on(\"data\", (d) => {\n stdout += d.toString();\n });\n\n child.stderr?.on(\"data\", (d) => {\n stderr += d.toString();\n });\n\n child.on(\"close\", (code) => {\n const result: ExecResult = {\n stdout,\n stderr,\n output: `${stdout}\\n${stderr}`,\n code,\n };\n\n if (code !== 0 && !options.ignoreErrors) {\n reject(new Error(`Command failed with code ${code}: ${cmd} ${args.join(\" \")}`));\n return;\n }\n\n resolve(result);\n });\n\n child.on(\"error\", (error) => {\n reject(new Error(`Failed to execute command: ${error.message}`));\n });\n });\n}\n","import { execCommand } from \"./exec\";\nimport { VALID_TEST_EXTENSIONS } from \"./constants\";\n\nlet cachedGitAvailability: boolean | null = null;\nlet cachedStagedFiles: string[] | null = null;\nlet cachedStagedFilesAt = 0;\nconst STAGED_FILES_CACHE_TTL_MS = 1000;\n\nexport async function hasGit(): Promise<boolean> {\n if (cachedGitAvailability !== null) {\n return cachedGitAvailability;\n }\n\n try {\n const result = await execCommand(\"git\", [\"--version\"], { ignoreErrors: true });\n cachedGitAvailability = result.code === 0;\n\n return cachedGitAvailability;\n } catch {\n cachedGitAvailability = false;\n\n return false;\n }\n}\n\nexport async function getStagedFiles(): Promise<string[]> {\n const now = Date.now();\n if (cachedStagedFiles && now - cachedStagedFilesAt <= STAGED_FILES_CACHE_TTL_MS) {\n return cachedStagedFiles;\n }\n\n const gitAvailable = await hasGit();\n if (!gitAvailable) {\n throw new Error(\"Git is not installed or not available in PATH\");\n }\n\n const result = await execCommand(\"git\", [\"diff\", \"--name-only\", \"--cached\"], {\n ignoreErrors: true,\n });\n\n const files = result.stdout\n .split(\"\\n\")\n .map((f) => f.trim())\n .filter(Boolean);\n\n cachedStagedFiles = files;\n cachedStagedFilesAt = now;\n\n return files;\n}\n\nexport function filterTestFiles(files: string[]): string[] {\n return files.filter((file) => VALID_TEST_EXTENSIONS.test(file));\n}\n","import { spawn } from \"node:child_process\";\n\nimport { getJestCommand, type PackageManager } from \"./package-manager\";\nimport { isWindows } from \"./platform\";\nimport { filterTestFiles, getStagedFiles } from \"./git\";\nimport type { ExecutionMode, ExecResult, RunJestOptions } from \"../types\";\n\nexport async function runJest(args: string[] = [], options: RunJestOptions = {}): Promise<ExecResult> {\n const {\n verbose = false,\n coverage = false,\n packageManager = null,\n ignoreErrors = true,\n disableVerbose = false,\n } = options;\n\n const jestCmd = getJestCommand(packageManager as PackageManager | null);\n const jestArgs = [...jestCmd.slice(1)];\n\n if (verbose && !disableVerbose) {\n jestArgs.push(\"--verbose\");\n }\n\n if (coverage) {\n jestArgs.push(\"--coverage\");\n\n if (options.coverageReporters) {\n for (const reporter of options.coverageReporters) {\n jestArgs.push(`--coverageReporters=${reporter}`);\n }\n }\n }\n\n if (isWindows()) {\n jestArgs.push(\"--no-watchman\");\n }\n\n jestArgs.push(...args);\n\n return new Promise((resolve, reject) => {\n const child = spawn(jestCmd[0], jestArgs, {\n shell: isWindows(),\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout.on(\"data\", (d) => {\n stdout += d.toString();\n });\n\n child.stderr.on(\"data\", (d) => {\n stderr += d.toString();\n });\n\n child.on(\"close\", (code) => {\n const result: ExecResult = {\n stdout,\n stderr,\n output: `${stdout}\\n${stderr}`,\n code,\n };\n\n if (code !== 0 && !ignoreErrors) {\n reject(new Error(`Jest failed with code ${code}`));\n return;\n }\n\n resolve(result);\n });\n\n child.on(\"error\", reject);\n });\n}\n\nexport async function buildJestArgsForMode(mode: ExecutionMode): Promise<string[]> {\n if (mode === \"all\") {\n return [];\n }\n\n const staged = await getStagedFiles();\n if (staged.length === 0) {\n throw new Error(`No staged files found for mode: ${mode}`);\n }\n\n if (mode === \"tests\") {\n const testFiles = filterTestFiles(staged);\n if (testFiles.length === 0) {\n throw new Error(\"No test files found in staged files\");\n }\n\n return testFiles;\n }\n\n return [\"--findRelatedTests\", ...staged];\n}\n","import { CONSOLE_LOG_TYPES, JEST_PATTERNS } from \"./constants\";\n\nexport function stripAnsi(text: string): string {\n return text.replace(/\\x1b\\[[0-9;]*m/g, \"\");\n}\n\nexport function isCodeSnippetLine(line: string): boolean {\n return JEST_PATTERNS.CODE_LINE.test(stripAnsi(line).trim());\n}\n\nexport function isStackTraceLine(line: string): boolean {\n return JEST_PATTERNS.STACK_TRACE.test(stripAnsi(line));\n}\n\nexport function isConsoleTypeLine(line: string): boolean {\n const clean = stripAnsi(line).trim();\n return Object.values(CONSOLE_LOG_TYPES).includes(clean as (typeof CONSOLE_LOG_TYPES)[keyof typeof CONSOLE_LOG_TYPES]);\n}\n\nexport function extractConsoleType(line: string): string | null {\n const clean = stripAnsi(line).trim();\n return Object.values(CONSOLE_LOG_TYPES).find((type) => type === clean) ?? null;\n}\n","import { writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport { VALID_EXPORT_FORMATS } from \"./constants\";\nimport type { ExportFormat, OutputOptions } from \"../types\";\n\nexport function getDisplayTimestamp(locale = \"en-US\"): string {\n return new Date().toLocaleString(locale, {\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: false,\n });\n}\n\nexport function getFilenameTimestamp(): string {\n const now = new Date();\n const pad = (value: number) => String(value).padStart(2, \"0\");\n\n return (\n [now.getFullYear(), pad(now.getMonth() + 1), pad(now.getDate())].join(\"-\") +\n \"_\" +\n [pad(now.getHours()), pad(now.getMinutes()), pad(now.getSeconds())].join(\"-\")\n );\n}\n\nexport function buildTimestampedPath(prefix: string, extension: string, dir = process.cwd()): string {\n const timestamp = getFilenameTimestamp();\n const filename = `${prefix}-${timestamp}.${extension}`;\n\n return path.resolve(dir, filename);\n}\n\nexport function formatAsMarkdown(content: string, title: string, timestamp: string | null = null): string {\n const lines = [`# ${title}`, \"\"];\n\n if (timestamp) {\n lines.push(`Generated: ${timestamp}`, \"\");\n }\n\n lines.push(\"```text\", content.trimEnd(), \"```\", \"\");\n\n return lines.join(\"\\n\");\n}\n\nexport function exportToFile(\n content: string,\n options: { prefix: string; format: ExportFormat; title?: string; dir?: string }\n): string {\n const { prefix, format, title, dir = process.cwd() } = options;\n const filePath = buildTimestampedPath(prefix, format, dir);\n\n let finalContent = content;\n if (format === \"md\" && title) {\n finalContent = formatAsMarkdown(content, title, getDisplayTimestamp());\n }\n\n writeFileSync(filePath, finalContent, \"utf-8\");\n\n return filePath;\n}\n\nexport function parseExportCliArgs(args: string[]): { exportFormat: ExportFormat | null; exportArgs: string[] } {\n let exportFormat: ExportFormat | null = null;\n const exportArgs: string[] = [];\n\n for (const arg of args) {\n if (arg === \"--export\") {\n exportFormat = \"txt\";\n exportArgs.push(arg);\n continue;\n }\n\n if (!arg.startsWith(\"--export=\")) {\n continue;\n }\n\n const value = arg.slice(\"--export=\".length).trim().toLowerCase();\n if (!value || !VALID_EXPORT_FORMATS.includes(value as ExportFormat)) {\n throw new Error(`Invalid value for --export: ${value || \"(empty)\"}. Valid values: txt, md`);\n }\n\n exportFormat = value as ExportFormat;\n exportArgs.push(arg);\n }\n\n return { exportFormat, exportArgs };\n}\n\nexport function handleExportOrDisplay(content: string, config: OutputOptions): string | null {\n const { exportFormat, prefix, title } = config;\n\n if (!exportFormat) {\n console.log(content);\n\n return null;\n }\n\n const outputPath = exportToFile(content, {\n prefix,\n format: exportFormat,\n title,\n });\n\n console.log(`Output exported to: ${outputPath}`);\n\n return outputPath;\n}\n","type SchemaEntry = {\n values?: string[];\n default?: string;\n exclusive?: boolean;\n prefix?: string;\n allowedValues?: string[];\n};\n\nexport function validateCliArgs(\n args: string[],\n schema: Record<string, SchemaEntry>\n): { parsed: Record<string, string | undefined>; unknownArgs: string[] } {\n const parsed: Record<string, string | undefined> = {};\n const unknownArgs: string[] = [];\n\n for (const [key, config] of Object.entries(schema)) {\n if (config.default !== undefined) {\n parsed[key] = config.default;\n }\n }\n\n for (const arg of args) {\n let matched = false;\n\n for (const [key, config] of Object.entries(schema)) {\n if (config.values?.includes(arg)) {\n if (config.exclusive && parsed[key] !== undefined && parsed[key] !== config.default) {\n throw new Error(`Multiple values provided for ${key}: ${parsed[key]} and ${arg}`);\n }\n\n parsed[key] = arg;\n matched = true;\n break;\n }\n\n if (config.prefix && arg.startsWith(config.prefix)) {\n const value = arg.slice(config.prefix.length).trim().toLowerCase();\n\n if (!value) {\n parsed[key] = \"true\";\n matched = true;\n break;\n }\n\n if (config.allowedValues && !config.allowedValues.includes(value)) {\n throw new Error(\n `Invalid value for ${config.prefix}: ${value}. Valid values: ${config.allowedValues.join(\", \")}`\n );\n }\n\n parsed[key] = value;\n matched = true;\n break;\n }\n }\n\n if (!matched && arg.startsWith(\"--\")) {\n unknownArgs.push(arg);\n }\n }\n\n return { parsed, unknownArgs };\n}\n\nexport function displayHelp(\n title: string,\n content: { description?: string; usage?: string[]; options?: string[]; examples?: string[] }\n): never {\n console.log(`\\n${title}\\n`);\n\n if (content.description) {\n console.log(`${content.description}\\n`);\n }\n\n if (content.usage?.length) {\n console.log(\"Usage:\");\n content.usage.forEach((line) => console.log(` ${line}`));\n console.log(\"\");\n }\n\n if (content.options?.length) {\n console.log(\"Options:\");\n content.options.forEach((line) => console.log(` ${line}`));\n console.log(\"\");\n }\n\n if (content.examples?.length) {\n console.log(\"Examples:\");\n content.examples.forEach((line) => console.log(` ${line}`));\n console.log(\"\");\n }\n\n process.exit(0);\n}\n\nexport function exitWithError(message: string, code = 1): never {\n console.error(`❌ ${message}`);\n process.exit(code);\n}\n\nexport function logWarning(message: string): void {\n console.warn(`⚠️ ${message}`);\n}\n\nexport function logInfo(message: string): void {\n console.log(`ℹ️ ${message}`);\n}\n\nexport function logSuccess(message: string): void {\n console.log(`✅ ${message}`);\n}\n","import { getDisplayTimestamp } from \"./export\";\n\ntype Spinner = {\n start: () => Spinner;\n stop: () => Spinner;\n succeed: (message?: string) => Spinner;\n warn: (message?: string) => Spinner;\n fail: (message?: string) => Spinner;\n};\n\ntype ProgressBar = {\n update: (value: number, payload?: Record<string, string>) => void;\n stop: () => void;\n};\n\nexport function shouldShowUI(exportMode: string | null, noBanner = false): boolean {\n return !exportMode && !noBanner && Boolean(process.stdout.isTTY);\n}\n\nexport function displayBanner(config: {\n text: string;\n subtitle?: string;\n info?: Record<string, string>;\n colors?: string[];\n font?: string;\n}): void {\n const { text, subtitle, info = {}, colors = [\"cyan\"], font = \"block\" } = config;\n const bannerText = [text, subtitle].filter(Boolean).join(\" \").trim();\n\n // Lazy load to avoid breaking non-interactive execution.\n const cfonts = require(\"cfonts\") as {\n render: (message: string, options: Record<string, unknown>) => { string: string };\n };\n const boxenModule = require(\"boxen\") as\n | ((text: string, options: Record<string, unknown>) => string)\n | { default: (text: string, options: Record<string, unknown>) => string };\n const boxen = typeof boxenModule === \"function\" ? boxenModule : boxenModule.default;\n\n const renderedBanner = cfonts.render(bannerText, {\n font,\n colors,\n align: \"left\",\n background: \"transparent\",\n letterSpacing: 1,\n lineHeight: 1,\n space: false,\n maxLength: \"0\",\n env: \"node\",\n });\n\n const infoLine = Object.entries(info)\n .map(([key, value]) => `${key}: ${value}`)\n .join(\" | \");\n\n const contentLines = [renderedBanner.string.trimEnd()];\n if (infoLine) {\n contentLines.push(\"\", ` ${infoLine}`);\n }\n contentLines.push(` Date: ${getDisplayTimestamp()}`);\n\n const boxed = boxen(contentLines.join(\"\\n\"), {\n padding: {\n top: 0,\n right: 1,\n bottom: 0,\n left: 1,\n },\n margin: {\n top: 0,\n right: 0,\n bottom: 1,\n left: 0,\n },\n borderStyle: \"round\",\n borderColor: colors[0] ?? \"cyan\",\n });\n\n console.log(boxed);\n}\n\nexport function createSpinner(text: string, color: string = \"cyan\"): Spinner {\n const ora = require(\"ora\") as (config: Record<string, unknown>) => Spinner;\n\n return ora({ text, color, spinner: \"dots\" });\n}\n\nexport function createProgressBar(total = 100, task = \"Progress\"): ProgressBar {\n const cliProgress = require(\"cli-progress\") as {\n SingleBar: new (options: Record<string, unknown>, preset: unknown) => {\n start: (maxValue: number, startValue: number, payload?: Record<string, string>) => void;\n update: (value: number, payload?: Record<string, string>) => void;\n stop: () => void;\n };\n Presets: {\n shades_classic: unknown;\n };\n };\n\n const bar = new cliProgress.SingleBar(\n {\n format: \"{task} [{bar}] {percentage}% | {status}\",\n barCompleteChar: \"█\",\n barIncompleteChar: \"░\",\n hideCursor: true,\n barsize: 24,\n },\n cliProgress.Presets.shades_classic\n );\n\n bar.start(total, 0, {\n task,\n status: \"Starting...\",\n });\n\n return {\n update: (value: number, payload?: Record<string, string>) => bar.update(value, payload),\n stop: () => bar.stop(),\n };\n}\n","#!/usr/bin/env node\n\nimport { runConsoleContext } from \"../commands/console-context\";\n\nrunConsoleContext().catch((error) => {\n console.error(`❌ ${(error as Error).message}`);\n process.exit(1);\n});\n"],"mappings":"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","names":["import_node_path","import_node_child_process","path","path"]}
|
|
1
|
+
{"version":3,"sources":["../../src/commands/console-context.ts","../../src/core/constants.ts","../../src/core/platform.ts","../../src/core/package-manager.ts","../../src/core/exec.ts","../../src/core/git.ts","../../src/core/jest.ts","../../src/core/parsing.ts","../../src/core/export.ts","../../src/core/cli.ts","../../src/core/ui.ts","../../src/bin/console-context.ts"],"sourcesContent":["import path from \"node:path\";\n\nimport {\n buildJestArgsForMode,\n CONSOLE_LOG_TYPES,\n createSpinner,\n displayBanner,\n displayHelp,\n exitWithError,\n extractConsoleType,\n getDisplayTimestamp,\n handleExportOrDisplay,\n isCodeSnippetLine,\n isConsoleTypeLine,\n isStackTraceLine,\n JEST_PATTERNS,\n logWarning,\n parseExportCliArgs,\n runJest,\n shouldShowUI,\n stripAnsi,\n validateCliArgs,\n VALID_MODES,\n} from \"../core\";\n\ntype ParsedWarning = {\n type: string;\n testFile: string;\n messages: string[];\n};\n\nfunction parseConsoleWarnings(rawOutput: string): ParsedWarning[] {\n const lines = rawOutput.split(\"\\n\");\n const warnings: ParsedWarning[] = [];\n\n const state: {\n currentTestFile: string | null;\n currentWarning: ParsedWarning | null;\n pendingWarnings: ParsedWarning[];\n } = {\n currentTestFile: null,\n currentWarning: null,\n pendingWarnings: [],\n };\n\n const flushCurrentWarning = () => {\n if (!state.currentWarning) return;\n\n if (state.currentWarning.testFile === \"unknown\" && state.currentTestFile) {\n state.currentWarning.testFile = state.currentTestFile;\n }\n\n warnings.push(state.currentWarning);\n state.pendingWarnings.push(state.currentWarning);\n state.currentWarning = null;\n };\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n if (JEST_PATTERNS.TEST_FILE.test(trimmed)) {\n const match = trimmed.match(JEST_PATTERNS.TEST_FILE);\n if (match) {\n state.currentTestFile = path.basename(match[2]);\n for (const warning of state.pendingWarnings) {\n if (warning.testFile === \"unknown\") warning.testFile = state.currentTestFile;\n }\n }\n flushCurrentWarning();\n continue;\n }\n\n if (trimmed === \"● Console\") {\n continue;\n }\n\n if (isConsoleTypeLine(line)) {\n flushCurrentWarning();\n state.currentWarning = {\n type: extractConsoleType(line) ?? \"console.warn\",\n testFile: state.currentTestFile ?? \"unknown\",\n messages: [],\n };\n continue;\n }\n\n if (!state.currentWarning) continue;\n if (isCodeSnippetLine(line)) continue;\n if (isStackTraceLine(line)) continue;\n\n const cleanMessage = stripAnsi(line).trim();\n if (cleanMessage.length > 0) {\n state.currentWarning.messages.push(cleanMessage);\n }\n }\n\n flushCurrentWarning();\n\n return warnings;\n}\n\nfunction filterWarningsByType(warnings: ParsedWarning[], filter: \"errors\" | \"warns\" | null): ParsedWarning[] {\n if (filter === \"errors\") {\n return warnings.filter((w) => w.type === CONSOLE_LOG_TYPES.ERROR);\n }\n if (filter === \"warns\") {\n return warnings.filter((w) => w.type === CONSOLE_LOG_TYPES.WARN);\n }\n\n return warnings;\n}\n\nfunction groupByTestFile(warnings: ParsedWarning[]): Record<string, ParsedWarning[]> {\n const grouped: Record<string, ParsedWarning[]> = {};\n\n for (const warning of warnings) {\n const file = warning.testFile;\n if (!grouped[file]) grouped[file] = [];\n grouped[file].push(warning);\n }\n\n return grouped;\n}\n\nfunction sortFilesByWarningCount(grouped: Record<string, ParsedWarning[]>): Array<[string, ParsedWarning[]]> {\n const entries = Object.entries(grouped);\n entries.sort((a, b) => b[1].length - a[1].length);\n\n return entries;\n}\n\nfunction formatWarningsOutput(\n grouped: Record<string, ParsedWarning[]>,\n timestamp: string,\n stats: { total: number; byType: Record<string, number> }\n): string {\n const lines: string[] = [];\n lines.push(\"=== CONSOLE WARNINGS CONTEXT BEGIN ===\", \"\", `📅 Run Date: ${timestamp}`, \"\");\n\n const sortedEntries = sortFilesByWarningCount(grouped);\n const totalFiles = sortedEntries.length;\n\n if (totalFiles === 0) {\n lines.push(\"✅ No console warnings found!\");\n } else {\n lines.push(\n `⚠️ Found ${stats.total} warning(s) in ${totalFiles} test file(s)`,\n \"\",\n \"📊 Summary by Type:\",\n ` - console.error: ${stats.byType[CONSOLE_LOG_TYPES.ERROR] ?? 0} occurrence(s)`,\n ` - console.warn: ${stats.byType[CONSOLE_LOG_TYPES.WARN] ?? 0} occurrence(s)`,\n \"\",\n \"=\".repeat(60),\n \"\"\n );\n\n for (const [file, warnings] of sortedEntries) {\n lines.push(`📄 File: ${file}`, ` Total Warnings: ${warnings.length}`, \"\");\n\n warnings.forEach((warning, idx) => {\n lines.push(` ${idx + 1}. ${warning.type}`, \"\");\n\n if (warning.messages.length > 0) {\n lines.push(\" 📝 Message:\");\n warning.messages.forEach((msg) => lines.push(` ${msg}`));\n lines.push(\"\");\n }\n\n if (idx < warnings.length - 1) {\n lines.push(\" \" + \"-\".repeat(50), \"\");\n }\n });\n\n lines.push(\"=\".repeat(60), \"\");\n }\n }\n\n lines.push(\"=== CONSOLE WARNINGS CONTEXT END ===\");\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction calculateStatistics(warnings: ParsedWarning[]) {\n const stats = {\n total: warnings.length,\n byType: {\n [CONSOLE_LOG_TYPES.ERROR]: 0,\n [CONSOLE_LOG_TYPES.WARN]: 0,\n },\n };\n\n for (const warning of warnings) {\n if (warning.type === CONSOLE_LOG_TYPES.ERROR) {\n stats.byType[CONSOLE_LOG_TYPES.ERROR]++;\n } else if (warning.type === CONSOLE_LOG_TYPES.WARN) {\n stats.byType[CONSOLE_LOG_TYPES.WARN]++;\n }\n }\n\n return stats;\n}\n\nexport async function runConsoleContext(argv = process.argv.slice(2)): Promise<void> {\n if (argv.includes(\"-h\") || argv.includes(\"--help\")) {\n displayHelp(\"Console Context Script\", {\n description: \"Capture and format console warnings/errors from Jest output.\",\n usage: [\n \"console-context -- --all\",\n \"console-context -- --related\",\n \"console-context -- --tests\",\n ],\n options: [\n \"--all Run all tests (default)\",\n \"--related Run tests related to staged files\",\n \"--tests Run only staged test files\",\n \"--only-errors Show only console.error warnings\",\n \"--only-warns Show only console.warn warnings\",\n \"--export Export output as txt\",\n \"--export=txt|md Export output in selected format\",\n \"--no-banner Disable fancy terminal UI\",\n \"-h, --help Show this help\",\n ],\n examples: [\n \"console-context -- --related --only-errors\",\n \"console-context -- --all --export=md\",\n ],\n });\n }\n\n const noBanner = argv.includes(\"--no-banner\");\n const args = argv.filter((arg) => arg !== \"--no-banner\");\n\n const { exportFormat, exportArgs } = parseExportCliArgs(args);\n const { parsed, unknownArgs } = validateCliArgs(args, {\n mode: {\n values: [...VALID_MODES],\n default: \"--all\",\n exclusive: true,\n },\n filter: {\n values: [\"--only-errors\", \"--only-warns\"],\n exclusive: true,\n },\n });\n\n const exportArgSet = new Set(exportArgs);\n const filteredUnknownArgs = unknownArgs.filter((arg) => !exportArgSet.has(arg));\n if (filteredUnknownArgs.length > 0) {\n logWarning(`Unknown arguments ignored: ${filteredUnknownArgs.join(\", \")}`);\n }\n\n const mode = parsed.mode ?? \"--all\";\n const filter = parsed.filter === \"--only-errors\" ? \"errors\" : parsed.filter === \"--only-warns\" ? \"warns\" : null;\n\n const showUI = shouldShowUI(exportFormat, noBanner);\n if (showUI) {\n displayBanner({\n text: \"JEST\",\n subtitle: \"CONSOLE\",\n info: {\n Mode: mode,\n Filter: filter ?? \"none\",\n },\n colors: [\"yellow\", \"red\"],\n });\n }\n\n const modeKey = mode.replace(\"--\", \"\") as \"all\" | \"related\" | \"tests\";\n\n let jestArgs: string[] = [];\n try {\n jestArgs = await buildJestArgsForMode(modeKey);\n } catch (error) {\n exitWithError((error as Error).message);\n }\n\n const spinner = showUI ? createSpinner(\"Capturing console warnings...\", \"yellow\") : null;\n spinner?.start();\n\n const result = await runJest(jestArgs, {\n disableVerbose: true,\n ignoreErrors: true,\n });\n\n let warnings = parseConsoleWarnings(result.output);\n warnings = filterWarningsByType(warnings, filter);\n\n if (spinner) {\n if (warnings.length > 0) {\n spinner.warn(`Found ${warnings.length} warning(s)`);\n } else {\n spinner.succeed(\"No console warnings found\");\n }\n }\n\n const grouped = groupByTestFile(warnings);\n const stats = calculateStatistics(warnings);\n const timestamp = getDisplayTimestamp();\n const formatted = formatWarningsOutput(grouped, timestamp, stats);\n\n handleExportOrDisplay(formatted, {\n exportFormat,\n prefix: \"export-console-context\",\n title: \"Console Warnings Context\",\n });\n}\n","export const VALID_MODES = [\"--all\", \"--related\", \"--tests\"] as const;\n\nexport const VALID_EXPORT_FORMATS = [\"txt\", \"md\"] as const;\n\nexport const VALID_TEST_EXTENSIONS = /\\.(test|spec)\\.(ts|tsx|js|jsx)$/;\n\nexport const CONSOLE_LOG_TYPES = {\n ERROR: \"console.error\",\n WARN: \"console.warn\",\n LOG: \"console.log\",\n DEBUG: \"console.debug\",\n} as const;\n\nexport const JEST_PATTERNS = {\n FAIL_LINE: /^FAIL\\s+/,\n PASS_LINE: /^PASS\\s+/,\n TEST_FILE: /^(PASS|FAIL)\\s+(.+\\.(test|spec)\\.tsx?)/,\n COVERAGE_LINE:\n /^(.+?)\\s+\\|\\s+([\\d.]+)\\s+\\|\\s+([\\d.]+)\\s+\\|\\s+([\\d.]+)\\s+\\|\\s+([\\d.]+)(?:\\s+\\|\\s+(.+))?$/,\n BULLET_POINT: /^●\\s+/,\n CODE_LINE: /^>?\\s*\\d*\\s*\\|/,\n STACK_TRACE: /^\\s+at\\s+/,\n};\n","export function getPlatform(): NodeJS.Platform {\n return process.platform;\n}\n\nexport function isWindows(): boolean {\n return process.platform === \"win32\";\n}\n\nexport function isMac(): boolean {\n return process.platform === \"darwin\";\n}\n\nexport function isLinux(): boolean {\n return process.platform === \"linux\";\n}\n\nexport function resolveCommand(cmd: string): string {\n if (!isWindows()) return cmd;\n\n const windowsCommands: Record<string, string> = {\n git: \"git.exe\",\n node: \"node.exe\",\n npm: \"npm.cmd\",\n npx: \"npx.cmd\",\n yarn: \"yarn.cmd\",\n pnpm: \"pnpm.cmd\",\n };\n\n return windowsCommands[cmd] ?? cmd;\n}\n","export type PackageManager = \"npm\" | \"yarn\" | \"pnpm\";\n\nexport function detectPackageManager(): PackageManager {\n if (process.env.npm_execpath?.includes(\"yarn\")) return \"yarn\";\n if (process.env.npm_execpath?.includes(\"pnpm\")) return \"pnpm\";\n\n return \"npm\";\n}\n\nexport function getJestCommand(packageManager: PackageManager | null = null): [string, string] {\n const pm = packageManager ?? detectPackageManager();\n\n switch (pm) {\n case \"yarn\":\n return [\"yarn\", \"jest\"];\n case \"pnpm\":\n return [\"pnpm\", \"jest\"];\n default:\n return [\"npx\", \"jest\"];\n }\n}\n","import { spawn } from \"node:child_process\";\n\nimport { resolveCommand } from \"./platform\";\nimport type { ExecResult } from \"../types\";\n\nexport async function execCommand(\n cmd: string,\n args: string[] = [],\n options: { shell?: boolean; ignoreErrors?: boolean } = {}\n): Promise<ExecResult> {\n return new Promise((resolve, reject) => {\n const resolvedCmd = resolveCommand(cmd);\n const child = spawn(resolvedCmd, args, {\n shell: options.shell ?? false,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout?.on(\"data\", (d) => {\n stdout += d.toString();\n });\n\n child.stderr?.on(\"data\", (d) => {\n stderr += d.toString();\n });\n\n child.on(\"close\", (code) => {\n const result: ExecResult = {\n stdout,\n stderr,\n output: `${stdout}\\n${stderr}`,\n code,\n };\n\n if (code !== 0 && !options.ignoreErrors) {\n reject(new Error(`Command failed with code ${code}: ${cmd} ${args.join(\" \")}`));\n return;\n }\n\n resolve(result);\n });\n\n child.on(\"error\", (error) => {\n reject(new Error(`Failed to execute command: ${error.message}`));\n });\n });\n}\n","import { execCommand } from \"./exec\";\nimport { VALID_TEST_EXTENSIONS } from \"./constants\";\n\nlet cachedGitAvailability: boolean | null = null;\nlet cachedStagedFiles: string[] | null = null;\nlet cachedStagedFilesAt = 0;\nconst STAGED_FILES_CACHE_TTL_MS = 1000;\n\nexport async function hasGit(): Promise<boolean> {\n if (cachedGitAvailability !== null) {\n return cachedGitAvailability;\n }\n\n try {\n const result = await execCommand(\"git\", [\"--version\"], { ignoreErrors: true });\n cachedGitAvailability = result.code === 0;\n\n return cachedGitAvailability;\n } catch {\n cachedGitAvailability = false;\n\n return false;\n }\n}\n\nexport async function getStagedFiles(): Promise<string[]> {\n const now = Date.now();\n if (cachedStagedFiles && now - cachedStagedFilesAt <= STAGED_FILES_CACHE_TTL_MS) {\n return cachedStagedFiles;\n }\n\n const gitAvailable = await hasGit();\n if (!gitAvailable) {\n throw new Error(\"Git is not installed or not available in PATH\");\n }\n\n const result = await execCommand(\"git\", [\"diff\", \"--name-only\", \"--cached\"], {\n ignoreErrors: true,\n });\n\n const files = result.stdout\n .split(\"\\n\")\n .map((f) => f.trim())\n .filter(Boolean);\n\n cachedStagedFiles = files;\n cachedStagedFilesAt = now;\n\n return files;\n}\n\nexport function filterTestFiles(files: string[]): string[] {\n return files.filter((file) => VALID_TEST_EXTENSIONS.test(file));\n}\n","import { spawn } from \"node:child_process\";\n\nimport { getJestCommand, type PackageManager } from \"./package-manager\";\nimport { isWindows, resolveCommand } from \"./platform\";\nimport { filterTestFiles, getStagedFiles } from \"./git\";\nimport type { ExecutionMode, ExecResult, RunJestOptions } from \"../types\";\n\nexport async function runJest(args: string[] = [], options: RunJestOptions = {}): Promise<ExecResult> {\n const {\n verbose = false,\n coverage = false,\n packageManager = null,\n ignoreErrors = true,\n disableVerbose = false,\n } = options;\n\n const jestCmd = getJestCommand(packageManager as PackageManager | null);\n const command = resolveCommand(jestCmd[0]);\n const jestArgs = [...jestCmd.slice(1)];\n\n if (verbose && !disableVerbose) {\n jestArgs.push(\"--verbose\");\n }\n\n if (coverage) {\n jestArgs.push(\"--coverage\");\n\n if (options.coverageReporters) {\n for (const reporter of options.coverageReporters) {\n jestArgs.push(`--coverageReporters=${reporter}`);\n }\n }\n }\n\n if (isWindows()) {\n jestArgs.push(\"--no-watchman\");\n }\n\n jestArgs.push(...args);\n\n return new Promise((resolve, reject) => {\n const child = spawn(command, jestArgs, {\n shell: false,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout.on(\"data\", (d) => {\n stdout += d.toString();\n });\n\n child.stderr.on(\"data\", (d) => {\n stderr += d.toString();\n });\n\n child.on(\"close\", (code) => {\n const result: ExecResult = {\n stdout,\n stderr,\n output: `${stdout}\\n${stderr}`,\n code,\n };\n\n if (code !== 0 && !ignoreErrors) {\n reject(new Error(`Jest failed with code ${code}`));\n return;\n }\n\n resolve(result);\n });\n\n child.on(\"error\", reject);\n });\n}\n\nexport async function buildJestArgsForMode(mode: ExecutionMode): Promise<string[]> {\n if (mode === \"all\") {\n return [];\n }\n\n const staged = await getStagedFiles();\n if (staged.length === 0) {\n throw new Error(`No staged files found for mode: ${mode}`);\n }\n\n if (mode === \"tests\") {\n const testFiles = filterTestFiles(staged);\n if (testFiles.length === 0) {\n throw new Error(\"No test files found in staged files\");\n }\n\n return testFiles;\n }\n\n return [\"--findRelatedTests\", ...staged];\n}\n","import { CONSOLE_LOG_TYPES, JEST_PATTERNS } from \"./constants\";\n\nexport function stripAnsi(text: string): string {\n return text.replace(/\\x1b\\[[0-9;]*m/g, \"\");\n}\n\nexport function isCodeSnippetLine(line: string): boolean {\n return JEST_PATTERNS.CODE_LINE.test(stripAnsi(line).trim());\n}\n\nexport function isStackTraceLine(line: string): boolean {\n return JEST_PATTERNS.STACK_TRACE.test(stripAnsi(line));\n}\n\nexport function isConsoleTypeLine(line: string): boolean {\n const clean = stripAnsi(line).trim();\n return Object.values(CONSOLE_LOG_TYPES).includes(clean as (typeof CONSOLE_LOG_TYPES)[keyof typeof CONSOLE_LOG_TYPES]);\n}\n\nexport function extractConsoleType(line: string): string | null {\n const clean = stripAnsi(line).trim();\n return Object.values(CONSOLE_LOG_TYPES).find((type) => type === clean) ?? null;\n}\n","import { writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport { VALID_EXPORT_FORMATS } from \"./constants\";\nimport type { ExportFormat, OutputOptions } from \"../types\";\n\nexport function getDisplayTimestamp(locale = \"en-US\"): string {\n return new Date().toLocaleString(locale, {\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: false,\n });\n}\n\nexport function getFilenameTimestamp(): string {\n const now = new Date();\n const pad = (value: number) => String(value).padStart(2, \"0\");\n\n return (\n [now.getFullYear(), pad(now.getMonth() + 1), pad(now.getDate())].join(\"-\") +\n \"_\" +\n [pad(now.getHours()), pad(now.getMinutes()), pad(now.getSeconds())].join(\"-\")\n );\n}\n\nexport function buildTimestampedPath(prefix: string, extension: string, dir = process.cwd()): string {\n const timestamp = getFilenameTimestamp();\n const filename = `${prefix}-${timestamp}.${extension}`;\n\n return path.resolve(dir, filename);\n}\n\nexport function formatAsMarkdown(content: string, title: string, timestamp: string | null = null): string {\n const lines = [`# ${title}`, \"\"];\n\n if (timestamp) {\n lines.push(`Generated: ${timestamp}`, \"\");\n }\n\n lines.push(\"```text\", content.trimEnd(), \"```\", \"\");\n\n return lines.join(\"\\n\");\n}\n\nexport function exportToFile(\n content: string,\n options: { prefix: string; format: ExportFormat; title?: string; dir?: string }\n): string {\n const { prefix, format, title, dir = process.cwd() } = options;\n const filePath = buildTimestampedPath(prefix, format, dir);\n\n let finalContent = content;\n if (format === \"md\" && title) {\n finalContent = formatAsMarkdown(content, title, getDisplayTimestamp());\n }\n\n writeFileSync(filePath, finalContent, \"utf-8\");\n\n return filePath;\n}\n\nexport function parseExportCliArgs(args: string[]): { exportFormat: ExportFormat | null; exportArgs: string[] } {\n let exportFormat: ExportFormat | null = null;\n const exportArgs: string[] = [];\n\n for (const arg of args) {\n if (arg === \"--export\") {\n exportFormat = \"txt\";\n exportArgs.push(arg);\n continue;\n }\n\n if (!arg.startsWith(\"--export=\")) {\n continue;\n }\n\n const value = arg.slice(\"--export=\".length).trim().toLowerCase();\n if (!value || !VALID_EXPORT_FORMATS.includes(value as ExportFormat)) {\n throw new Error(`Invalid value for --export: ${value || \"(empty)\"}. Valid values: txt, md`);\n }\n\n exportFormat = value as ExportFormat;\n exportArgs.push(arg);\n }\n\n return { exportFormat, exportArgs };\n}\n\nexport function handleExportOrDisplay(content: string, config: OutputOptions): string | null {\n const { exportFormat, prefix, title } = config;\n\n if (!exportFormat) {\n console.log(content);\n\n return null;\n }\n\n const outputPath = exportToFile(content, {\n prefix,\n format: exportFormat,\n title,\n });\n\n console.log(`Output exported to: ${outputPath}`);\n\n return outputPath;\n}\n","type SchemaEntry = {\n values?: string[];\n default?: string;\n exclusive?: boolean;\n prefix?: string;\n allowedValues?: string[];\n};\n\nexport function validateCliArgs(\n args: string[],\n schema: Record<string, SchemaEntry>\n): { parsed: Record<string, string | undefined>; unknownArgs: string[] } {\n const parsed: Record<string, string | undefined> = {};\n const unknownArgs: string[] = [];\n\n for (const [key, config] of Object.entries(schema)) {\n if (config.default !== undefined) {\n parsed[key] = config.default;\n }\n }\n\n for (const arg of args) {\n let matched = false;\n\n for (const [key, config] of Object.entries(schema)) {\n if (config.values?.includes(arg)) {\n if (config.exclusive && parsed[key] !== undefined && parsed[key] !== config.default) {\n throw new Error(`Multiple values provided for ${key}: ${parsed[key]} and ${arg}`);\n }\n\n parsed[key] = arg;\n matched = true;\n break;\n }\n\n if (config.prefix && arg.startsWith(config.prefix)) {\n const value = arg.slice(config.prefix.length).trim().toLowerCase();\n\n if (!value) {\n parsed[key] = \"true\";\n matched = true;\n break;\n }\n\n if (config.allowedValues && !config.allowedValues.includes(value)) {\n throw new Error(\n `Invalid value for ${config.prefix}: ${value}. Valid values: ${config.allowedValues.join(\", \")}`\n );\n }\n\n parsed[key] = value;\n matched = true;\n break;\n }\n }\n\n if (!matched && arg.startsWith(\"--\")) {\n unknownArgs.push(arg);\n }\n }\n\n return { parsed, unknownArgs };\n}\n\nexport function displayHelp(\n title: string,\n content: { description?: string; usage?: string[]; options?: string[]; examples?: string[] }\n): never {\n console.log(`\\n${title}\\n`);\n\n if (content.description) {\n console.log(`${content.description}\\n`);\n }\n\n if (content.usage?.length) {\n console.log(\"Usage:\");\n content.usage.forEach((line) => console.log(` ${line}`));\n console.log(\"\");\n }\n\n if (content.options?.length) {\n console.log(\"Options:\");\n content.options.forEach((line) => console.log(` ${line}`));\n console.log(\"\");\n }\n\n if (content.examples?.length) {\n console.log(\"Examples:\");\n content.examples.forEach((line) => console.log(` ${line}`));\n console.log(\"\");\n }\n\n process.exit(0);\n}\n\nexport function exitWithError(message: string, code = 1): never {\n console.error(`❌ ${message}`);\n process.exit(code);\n}\n\nexport function logWarning(message: string): void {\n console.warn(`⚠️ ${message}`);\n}\n\nexport function logInfo(message: string): void {\n console.log(`ℹ️ ${message}`);\n}\n\nexport function logSuccess(message: string): void {\n console.log(`✅ ${message}`);\n}\n","import { getDisplayTimestamp } from \"./export\";\n\ntype Spinner = {\n start: () => Spinner;\n stop: () => Spinner;\n succeed: (message?: string) => Spinner;\n warn: (message?: string) => Spinner;\n fail: (message?: string) => Spinner;\n};\n\ntype ProgressBar = {\n update: (value: number, payload?: Record<string, string>) => void;\n stop: () => void;\n};\n\nconst NOOP_PROGRESS_BAR: ProgressBar = {\n update: () => {},\n stop: () => {},\n};\n\nlet hasWarnedSpinnerFallback = false;\nlet hasWarnedProgressFallback = false;\n\nexport function shouldShowUI(exportMode: string | null, noBanner = false): boolean {\n return !exportMode && !noBanner && Boolean(process.stdout.isTTY);\n}\n\nexport function displayBanner(config: {\n text: string;\n subtitle?: string;\n info?: Record<string, string>;\n colors?: string[];\n font?: string;\n}): void {\n const { text, subtitle, info = {}, colors = [\"cyan\"], font = \"block\" } = config;\n const bannerText = [text, subtitle].filter(Boolean).join(\" \").trim();\n\n // Lazy load to avoid breaking non-interactive execution.\n const cfonts = require(\"cfonts\") as {\n render: (message: string, options: Record<string, unknown>) => { string: string };\n };\n const boxenModule = require(\"boxen\") as\n | ((text: string, options: Record<string, unknown>) => string)\n | { default: (text: string, options: Record<string, unknown>) => string };\n const boxen = typeof boxenModule === \"function\" ? boxenModule : boxenModule.default;\n\n const renderedBanner = cfonts.render(bannerText, {\n font,\n colors,\n align: \"left\",\n background: \"transparent\",\n letterSpacing: 1,\n lineHeight: 1,\n space: false,\n maxLength: \"0\",\n env: \"node\",\n });\n\n const infoLine = Object.entries(info)\n .map(([key, value]) => `${key}: ${value}`)\n .join(\" | \");\n\n const contentLines = [renderedBanner.string.trimEnd()];\n if (infoLine) {\n contentLines.push(\"\", ` ${infoLine}`);\n }\n contentLines.push(` Date: ${getDisplayTimestamp()}`);\n\n const boxed = boxen(contentLines.join(\"\\n\"), {\n padding: {\n top: 0,\n right: 1,\n bottom: 0,\n left: 1,\n },\n margin: {\n top: 0,\n right: 0,\n bottom: 1,\n left: 0,\n },\n borderStyle: \"round\",\n borderColor: colors[0] ?? \"cyan\",\n });\n\n console.log(boxed);\n}\n\nexport function createSpinner(text: string, color: string = \"cyan\"): Spinner {\n try {\n const ora = require(\"ora\") as (config: Record<string, unknown>) => Spinner;\n\n return ora({ text, color, spinner: \"dots\" });\n } catch {\n if (!hasWarnedSpinnerFallback) {\n hasWarnedSpinnerFallback = true;\n console.warn(\"Warning: spinner UI unavailable, continuing without spinner.\");\n }\n\n return {\n start: () => NOOP_SPINNER,\n stop: () => NOOP_SPINNER,\n succeed: () => NOOP_SPINNER,\n warn: () => NOOP_SPINNER,\n fail: () => NOOP_SPINNER,\n } as Spinner;\n }\n}\n\nconst NOOP_SPINNER: Spinner = {\n start: () => NOOP_SPINNER,\n stop: () => NOOP_SPINNER,\n succeed: () => NOOP_SPINNER,\n warn: () => NOOP_SPINNER,\n fail: () => NOOP_SPINNER,\n};\n\nexport function createProgressBar(total = 100, task = \"Progress\"): ProgressBar {\n if (!hasWarnedProgressFallback) {\n hasWarnedProgressFallback = true;\n console.warn(\n `Warning: progress bar UI is no longer used. Ignoring createProgressBar(${total}, ${JSON.stringify(task)}).`\n );\n }\n\n return NOOP_PROGRESS_BAR;\n}\n","#!/usr/bin/env node\n\nimport { runConsoleContext } from \"../commands/console-context\";\n\nrunConsoleContext().catch((error) => {\n console.error(`❌ ${(error as Error).message}`);\n process.exit(1);\n});\n"],"mappings":"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","names":["import_node_path","import_node_child_process","path","path"]}
|
|
@@ -42,6 +42,18 @@ var JEST_PATTERNS = {
|
|
|
42
42
|
function isWindows() {
|
|
43
43
|
return process.platform === "win32";
|
|
44
44
|
}
|
|
45
|
+
function resolveCommand(cmd) {
|
|
46
|
+
if (!isWindows()) return cmd;
|
|
47
|
+
const windowsCommands = {
|
|
48
|
+
git: "git.exe",
|
|
49
|
+
node: "node.exe",
|
|
50
|
+
npm: "npm.cmd",
|
|
51
|
+
npx: "npx.cmd",
|
|
52
|
+
yarn: "yarn.cmd",
|
|
53
|
+
pnpm: "pnpm.cmd"
|
|
54
|
+
};
|
|
55
|
+
return windowsCommands[cmd] ?? cmd;
|
|
56
|
+
}
|
|
45
57
|
|
|
46
58
|
// src/core/package-manager.ts
|
|
47
59
|
function detectPackageManager() {
|
|
@@ -75,6 +87,7 @@ async function runJest(args = [], options = {}) {
|
|
|
75
87
|
disableVerbose = false
|
|
76
88
|
} = options;
|
|
77
89
|
const jestCmd = getJestCommand(packageManager);
|
|
90
|
+
const command = resolveCommand(jestCmd[0]);
|
|
78
91
|
const jestArgs = [...jestCmd.slice(1)];
|
|
79
92
|
if (verbose && !disableVerbose) {
|
|
80
93
|
jestArgs.push("--verbose");
|
|
@@ -92,8 +105,8 @@ async function runJest(args = [], options = {}) {
|
|
|
92
105
|
}
|
|
93
106
|
jestArgs.push(...args);
|
|
94
107
|
return new Promise((resolve, reject) => {
|
|
95
|
-
const child = (0, import_node_child_process2.spawn)(
|
|
96
|
-
shell:
|
|
108
|
+
const child = (0, import_node_child_process2.spawn)(command, jestArgs, {
|
|
109
|
+
shell: false
|
|
97
110
|
});
|
|
98
111
|
let stdout = "";
|
|
99
112
|
let stderr = "";
|
|
@@ -272,6 +285,7 @@ function logWarning(message) {
|
|
|
272
285
|
}
|
|
273
286
|
|
|
274
287
|
// src/core/ui.ts
|
|
288
|
+
var hasWarnedSpinnerFallback = false;
|
|
275
289
|
function shouldShowUI(exportMode, noBanner = false) {
|
|
276
290
|
return !exportMode && !noBanner && Boolean(process.stdout.isTTY);
|
|
277
291
|
}
|
|
@@ -316,27 +330,31 @@ function displayBanner(config) {
|
|
|
316
330
|
});
|
|
317
331
|
console.log(boxed);
|
|
318
332
|
}
|
|
319
|
-
function
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
{
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
update: (value, payload) => bar.update(value, payload),
|
|
337
|
-
stop: () => bar.stop()
|
|
338
|
-
};
|
|
333
|
+
function createSpinner(text, color = "cyan") {
|
|
334
|
+
try {
|
|
335
|
+
const ora = require("ora");
|
|
336
|
+
return ora({ text, color, spinner: "dots" });
|
|
337
|
+
} catch {
|
|
338
|
+
if (!hasWarnedSpinnerFallback) {
|
|
339
|
+
hasWarnedSpinnerFallback = true;
|
|
340
|
+
console.warn("Warning: spinner UI unavailable, continuing without spinner.");
|
|
341
|
+
}
|
|
342
|
+
return {
|
|
343
|
+
start: () => NOOP_SPINNER,
|
|
344
|
+
stop: () => NOOP_SPINNER,
|
|
345
|
+
succeed: () => NOOP_SPINNER,
|
|
346
|
+
warn: () => NOOP_SPINNER,
|
|
347
|
+
fail: () => NOOP_SPINNER
|
|
348
|
+
};
|
|
349
|
+
}
|
|
339
350
|
}
|
|
351
|
+
var NOOP_SPINNER = {
|
|
352
|
+
start: () => NOOP_SPINNER,
|
|
353
|
+
stop: () => NOOP_SPINNER,
|
|
354
|
+
succeed: () => NOOP_SPINNER,
|
|
355
|
+
warn: () => NOOP_SPINNER,
|
|
356
|
+
fail: () => NOOP_SPINNER
|
|
357
|
+
};
|
|
340
358
|
|
|
341
359
|
// src/commands/coverage-context.ts
|
|
342
360
|
function parseCoverage(text) {
|
|
@@ -442,25 +460,24 @@ async function runCoverageContext(argv = process.argv.slice(2)) {
|
|
|
442
460
|
const showUI = shouldShowUI(exportFormat, noBanner);
|
|
443
461
|
if (showUI) {
|
|
444
462
|
displayBanner({
|
|
445
|
-
text: "
|
|
463
|
+
text: "JEST",
|
|
464
|
+
subtitle: "COVERAGE",
|
|
446
465
|
info: {
|
|
447
466
|
Threshold: `>=${threshold}%`
|
|
448
467
|
},
|
|
449
468
|
colors: ["magenta", "blue"]
|
|
450
469
|
});
|
|
451
470
|
}
|
|
452
|
-
const
|
|
453
|
-
|
|
471
|
+
const spinner = showUI ? createSpinner("Running Jest coverage...", "magenta") : null;
|
|
472
|
+
spinner?.start();
|
|
454
473
|
const result = await runJest([], {
|
|
455
474
|
coverage: true,
|
|
456
475
|
coverageReporters: ["text", "text-summary"],
|
|
457
476
|
ignoreErrors: true
|
|
458
477
|
});
|
|
459
|
-
bar?.update(70, { status: "Parsing output..." });
|
|
460
478
|
const rows = parseCoverage(result.output);
|
|
461
479
|
if (rows.length === 0) {
|
|
462
|
-
|
|
463
|
-
bar?.stop();
|
|
480
|
+
spinner?.warn("No coverage rows parsed");
|
|
464
481
|
handleExportOrDisplay("No coverage rows parsed from Jest output.", {
|
|
465
482
|
exportFormat,
|
|
466
483
|
prefix: "export-coverage-context",
|
|
@@ -470,9 +487,8 @@ async function runCoverageContext(argv = process.argv.slice(2)) {
|
|
|
470
487
|
}
|
|
471
488
|
const incomplete = filterIncomplete(rows, threshold);
|
|
472
489
|
const grouped = groupByFolder(incomplete);
|
|
473
|
-
bar?.update(100, { status: "Done" });
|
|
474
|
-
bar?.stop();
|
|
475
490
|
if (Object.keys(grouped).length === 0) {
|
|
491
|
+
spinner?.succeed(`All files meet threshold >= ${threshold}%`);
|
|
476
492
|
handleExportOrDisplay(`All files meet threshold >= ${threshold}%`, {
|
|
477
493
|
exportFormat,
|
|
478
494
|
prefix: "export-coverage-context",
|
|
@@ -481,6 +497,7 @@ async function runCoverageContext(argv = process.argv.slice(2)) {
|
|
|
481
497
|
return;
|
|
482
498
|
}
|
|
483
499
|
const formatted = formatCoverageOutput(grouped);
|
|
500
|
+
spinner?.warn(`Found ${incomplete.length} file(s) below threshold`);
|
|
484
501
|
handleExportOrDisplay(formatted, {
|
|
485
502
|
exportFormat,
|
|
486
503
|
prefix: "export-coverage-context",
|