@andy2639/jest-context 1.0.6 → 1.0.7
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 +6 -0
- package/dist/bin/console-context.cjs +29 -16
- package/dist/bin/console-context.cjs.map +1 -1
- package/dist/bin/console-context.mjs +2 -2
- package/dist/bin/coverage-context.cjs +30 -23
- package/dist/bin/coverage-context.cjs.map +1 -1
- package/dist/bin/coverage-context.mjs +2 -2
- package/dist/bin/jest-context-init.mjs +2 -2
- package/dist/bin/test-context.cjs +30 -21
- package/dist/bin/test-context.cjs.map +1 -1
- package/dist/bin/test-context.mjs +2 -2
- package/dist/{chunk-KGUQFDCB.mjs → chunk-2B6NO7WQ.mjs} +2 -2
- package/dist/{chunk-KGUQFDCB.mjs.map → chunk-2B6NO7WQ.mjs.map} +1 -1
- package/dist/{chunk-UE2DJICK.mjs → chunk-MRWQAVS4.mjs} +2 -2
- package/dist/{chunk-4N7XPTHJ.mjs → chunk-SSW26YOL.mjs} +30 -17
- package/dist/chunk-SSW26YOL.mjs.map +1 -0
- package/dist/{chunk-7F4YL67U.mjs → chunk-TQVH7JRM.mjs} +31 -24
- package/dist/chunk-TQVH7JRM.mjs.map +1 -0
- package/dist/{chunk-YEVAAYN5.mjs → chunk-UHFZOKGL.mjs} +31 -22
- package/dist/chunk-UHFZOKGL.mjs.map +1 -0
- package/dist/index.cjs +87 -58
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +5 -5
- package/package.json +1 -1
- package/dist/chunk-4N7XPTHJ.mjs.map +0 -1
- package/dist/chunk-7F4YL67U.mjs.map +0 -1
- package/dist/chunk-YEVAAYN5.mjs.map +0 -1
- /package/dist/{chunk-UE2DJICK.mjs.map → chunk-MRWQAVS4.mjs.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.7
|
|
4
|
+
|
|
5
|
+
- Show banner by default even when using `--export` (unless `--no-banner` is passed)
|
|
6
|
+
- Keep spinner loaders active for execution feedback in all modes, including `--no-banner`
|
|
7
|
+
- Add explicit export spinner phases (`Exporting ...`) for test, coverage, and console commands
|
|
8
|
+
|
|
3
9
|
## 1.0.6
|
|
4
10
|
|
|
5
11
|
- Update terminal banners to render in two lines with centered `JEST` title and centered command subtitle
|
|
@@ -449,7 +449,7 @@ function logWarning(message) {
|
|
|
449
449
|
// src/core/ui.ts
|
|
450
450
|
var hasWarnedSpinnerFallback = false;
|
|
451
451
|
function shouldShowUI(exportMode, noBanner = false) {
|
|
452
|
-
return !
|
|
452
|
+
return !noBanner;
|
|
453
453
|
}
|
|
454
454
|
function displayBanner(config) {
|
|
455
455
|
const { text, subtitle, info = {}, colors = ["cyan"], font = "block" } = config;
|
|
@@ -678,6 +678,25 @@ function calculateStatistics(warnings) {
|
|
|
678
678
|
}
|
|
679
679
|
return stats;
|
|
680
680
|
}
|
|
681
|
+
function outputConsoleContext(content, options) {
|
|
682
|
+
const { exportFormat } = options;
|
|
683
|
+
if (!exportFormat) {
|
|
684
|
+
handleExportOrDisplay(content, {
|
|
685
|
+
exportFormat,
|
|
686
|
+
prefix: "export-console-context",
|
|
687
|
+
title: "Console Warnings Context"
|
|
688
|
+
});
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
const exportSpinner = createSpinner("Exporting console context...", "yellow");
|
|
692
|
+
exportSpinner.start();
|
|
693
|
+
handleExportOrDisplay(content, {
|
|
694
|
+
exportFormat,
|
|
695
|
+
prefix: "export-console-context",
|
|
696
|
+
title: "Console Warnings Context"
|
|
697
|
+
});
|
|
698
|
+
exportSpinner.succeed("Console context exported");
|
|
699
|
+
}
|
|
681
700
|
async function runConsoleContext(argv = process.argv.slice(2)) {
|
|
682
701
|
if (argv.includes("-h") || argv.includes("--help")) {
|
|
683
702
|
displayHelp("Console Context Script", {
|
|
@@ -725,8 +744,8 @@ async function runConsoleContext(argv = process.argv.slice(2)) {
|
|
|
725
744
|
}
|
|
726
745
|
const mode = parsed.mode ?? "--all";
|
|
727
746
|
const filter = parsed.filter === "--only-errors" ? "errors" : parsed.filter === "--only-warns" ? "warns" : null;
|
|
728
|
-
const
|
|
729
|
-
if (
|
|
747
|
+
const showBanner = shouldShowUI(exportFormat, noBanner);
|
|
748
|
+
if (showBanner) {
|
|
730
749
|
displayBanner({
|
|
731
750
|
text: "JEST",
|
|
732
751
|
subtitle: "CONSOLE",
|
|
@@ -744,30 +763,24 @@ async function runConsoleContext(argv = process.argv.slice(2)) {
|
|
|
744
763
|
} catch (error) {
|
|
745
764
|
exitWithError(error.message);
|
|
746
765
|
}
|
|
747
|
-
const spinner =
|
|
748
|
-
spinner
|
|
766
|
+
const spinner = createSpinner("Capturing console warnings...", "yellow");
|
|
767
|
+
spinner.start();
|
|
749
768
|
const result = await runJest(jestArgs, {
|
|
750
769
|
disableVerbose: true,
|
|
751
770
|
ignoreErrors: true
|
|
752
771
|
});
|
|
753
772
|
let warnings = parseConsoleWarnings(result.output);
|
|
754
773
|
warnings = filterWarningsByType(warnings, filter);
|
|
755
|
-
if (
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
spinner.succeed("No console warnings found");
|
|
760
|
-
}
|
|
774
|
+
if (warnings.length > 0) {
|
|
775
|
+
spinner.warn(`Found ${warnings.length} warning(s)`);
|
|
776
|
+
} else {
|
|
777
|
+
spinner.succeed("No console warnings found");
|
|
761
778
|
}
|
|
762
779
|
const grouped = groupByTestFile(warnings);
|
|
763
780
|
const stats = calculateStatistics(warnings);
|
|
764
781
|
const timestamp = getDisplayTimestamp();
|
|
765
782
|
const formatted = formatWarningsOutput(grouped, timestamp, stats);
|
|
766
|
-
|
|
767
|
-
exportFormat,
|
|
768
|
-
prefix: "export-console-context",
|
|
769
|
-
title: "Console Warnings Context"
|
|
770
|
-
});
|
|
783
|
+
outputConsoleContext(formatted, { exportFormat });
|
|
771
784
|
}
|
|
772
785
|
|
|
773
786
|
// src/bin/console-context.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/commands/console-context.ts","../../src/core/constants.ts","../../src/core/platform.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","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\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport { isWindows } from \"./platform\";\nimport { filterTestFiles, getStagedFiles } from \"./git\";\nimport type { ExecutionMode, ExecResult, RunJestOptions } from \"../types\";\n\ntype ResolvedJestRunner = {\n command: string;\n argsPrefix: string[];\n};\n\nfunction resolveJestRunner(): ResolvedJestRunner {\n const cwd = process.cwd();\n const attempts: string[] = [];\n\n try {\n const jestPackageJsonPath = require.resolve(\"jest/package.json\", { paths: [cwd] });\n attempts.push(`Resolved jest package: ${jestPackageJsonPath}`);\n\n const jestPackageDir = path.dirname(jestPackageJsonPath);\n const jestPackage = JSON.parse(readFileSync(jestPackageJsonPath, \"utf-8\")) as {\n bin?: string | Record<string, string>;\n };\n\n const binField = jestPackage.bin;\n let binEntry: string | undefined;\n if (typeof binField === \"string\") {\n binEntry = binField;\n } else if (binField && typeof binField === \"object\") {\n binEntry = binField.jest ?? Object.values(binField)[0];\n }\n\n if (binEntry) {\n const binPath = path.resolve(jestPackageDir, binEntry);\n if (existsSync(binPath)) {\n return {\n command: process.execPath,\n argsPrefix: [binPath],\n };\n }\n attempts.push(`Jest bin from package.json not found: ${binPath}`);\n } else {\n attempts.push(\"Jest package.json has no usable bin field.\");\n }\n } catch {\n attempts.push(\"Could not resolve jest/package.json from current cwd.\");\n }\n\n try {\n const legacyBinPath = require.resolve(\"jest/bin/jest.js\", { paths: [cwd] });\n attempts.push(`Resolved legacy jest bin: ${legacyBinPath}`);\n return {\n command: process.execPath,\n argsPrefix: [legacyBinPath],\n };\n } catch {\n attempts.push(\"Could not resolve legacy path jest/bin/jest.js.\");\n }\n\n const localBinPath = path.resolve(cwd, \"node_modules\", \".bin\", isWindows() ? \"jest.cmd\" : \"jest\");\n if (existsSync(localBinPath)) {\n attempts.push(`Resolved local .bin executable: ${localBinPath}`);\n return {\n command: localBinPath,\n argsPrefix: [],\n };\n }\n attempts.push(`Local .bin executable not found: ${localBinPath}`);\n\n throw new Error(\n [\n \"Could not resolve Jest from the current project.\",\n \"Install `jest@^29` in the package where you run this command.\",\n \"Examples: `npm i -D jest@^29`, `pnpm add -D jest@^29`, `yarn add -D jest@^29`.\",\n `cwd: ${cwd}`,\n ...attempts,\n ].join(\"\\n\")\n );\n}\n\nexport async function runJest(args: string[] = [], options: RunJestOptions = {}): Promise<ExecResult> {\n const {\n verbose = false,\n coverage = false,\n ignoreErrors = true,\n disableVerbose = false,\n } = options;\n\n const runner = resolveJestRunner();\n const command = runner.command;\n const jestArgs = [...runner.argsPrefix];\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\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 renderedTitle = cfonts.render(text, {\n font,\n colors: [colors[0] ?? \"cyan\"],\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 renderedSubtitle = subtitle\n ? cfonts.render(subtitle, {\n font,\n colors: [colors[1] ?? colors[0] ?? \"cyan\"],\n align: \"left\",\n background: \"transparent\",\n letterSpacing: 1,\n lineHeight: 1,\n space: false,\n maxLength: \"0\",\n env: \"node\",\n })\n : null;\n\n const stripAnsi = (value: string): string => value.replace(/\\x1b\\[[0-9;]*m/g, \"\");\n const centerLines = (lines: string[], width: number): string[] => {\n return lines.map((line) => {\n const visibleLength = stripAnsi(line).length;\n const leftPad = Math.max(0, Math.floor((width - visibleLength) / 2));\n\n return `${\" \".repeat(leftPad)}${line}`;\n });\n };\n\n const titleLines = renderedTitle.string.trimEnd().split(\"\\n\");\n const subtitleLines = renderedSubtitle ? renderedSubtitle.string.trimEnd().split(\"\\n\") : [];\n const centeredWidth = Math.max(\n ...titleLines.map((line) => stripAnsi(line).length),\n ...(subtitleLines.length > 0 ? subtitleLines : [\"\"]).map((line) => stripAnsi(line).length)\n );\n\n const infoLine = Object.entries(info)\n .map(([key, value]) => `${key}: ${value}`)\n .join(\" | \");\n\n const contentLines = [...centerLines(titleLines, centeredWidth)];\n if (subtitleLines.length > 0) {\n contentLines.push(\"\", ...centerLines(subtitleLines, centeredWidth));\n }\n\n contentLines.push(\"\");\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","import_node_fs","import_node_path","path","stripAnsi","path"]}
|
|
1
|
+
{"version":3,"sources":["../../src/commands/console-context.ts","../../src/core/constants.ts","../../src/core/platform.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\nfunction outputConsoleContext(content: string, options: { exportFormat: \"txt\" | \"md\" | null }): void {\n const { exportFormat } = options;\n\n if (!exportFormat) {\n handleExportOrDisplay(content, {\n exportFormat,\n prefix: \"export-console-context\",\n title: \"Console Warnings Context\",\n });\n\n return;\n }\n\n const exportSpinner = createSpinner(\"Exporting console context...\", \"yellow\");\n exportSpinner.start();\n\n handleExportOrDisplay(content, {\n exportFormat,\n prefix: \"export-console-context\",\n title: \"Console Warnings Context\",\n });\n\n exportSpinner.succeed(\"Console context exported\");\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 showBanner = shouldShowUI(exportFormat, noBanner);\n if (showBanner) {\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 = createSpinner(\"Capturing console warnings...\", \"yellow\");\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 (warnings.length > 0) {\n spinner.warn(`Found ${warnings.length} warning(s)`);\n } else {\n spinner.succeed(\"No console warnings found\");\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 outputConsoleContext(formatted, { exportFormat });\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","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\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport { isWindows } from \"./platform\";\nimport { filterTestFiles, getStagedFiles } from \"./git\";\nimport type { ExecutionMode, ExecResult, RunJestOptions } from \"../types\";\n\ntype ResolvedJestRunner = {\n command: string;\n argsPrefix: string[];\n};\n\nfunction resolveJestRunner(): ResolvedJestRunner {\n const cwd = process.cwd();\n const attempts: string[] = [];\n\n try {\n const jestPackageJsonPath = require.resolve(\"jest/package.json\", { paths: [cwd] });\n attempts.push(`Resolved jest package: ${jestPackageJsonPath}`);\n\n const jestPackageDir = path.dirname(jestPackageJsonPath);\n const jestPackage = JSON.parse(readFileSync(jestPackageJsonPath, \"utf-8\")) as {\n bin?: string | Record<string, string>;\n };\n\n const binField = jestPackage.bin;\n let binEntry: string | undefined;\n if (typeof binField === \"string\") {\n binEntry = binField;\n } else if (binField && typeof binField === \"object\") {\n binEntry = binField.jest ?? Object.values(binField)[0];\n }\n\n if (binEntry) {\n const binPath = path.resolve(jestPackageDir, binEntry);\n if (existsSync(binPath)) {\n return {\n command: process.execPath,\n argsPrefix: [binPath],\n };\n }\n attempts.push(`Jest bin from package.json not found: ${binPath}`);\n } else {\n attempts.push(\"Jest package.json has no usable bin field.\");\n }\n } catch {\n attempts.push(\"Could not resolve jest/package.json from current cwd.\");\n }\n\n try {\n const legacyBinPath = require.resolve(\"jest/bin/jest.js\", { paths: [cwd] });\n attempts.push(`Resolved legacy jest bin: ${legacyBinPath}`);\n return {\n command: process.execPath,\n argsPrefix: [legacyBinPath],\n };\n } catch {\n attempts.push(\"Could not resolve legacy path jest/bin/jest.js.\");\n }\n\n const localBinPath = path.resolve(cwd, \"node_modules\", \".bin\", isWindows() ? \"jest.cmd\" : \"jest\");\n if (existsSync(localBinPath)) {\n attempts.push(`Resolved local .bin executable: ${localBinPath}`);\n return {\n command: localBinPath,\n argsPrefix: [],\n };\n }\n attempts.push(`Local .bin executable not found: ${localBinPath}`);\n\n throw new Error(\n [\n \"Could not resolve Jest from the current project.\",\n \"Install `jest@^29` in the package where you run this command.\",\n \"Examples: `npm i -D jest@^29`, `pnpm add -D jest@^29`, `yarn add -D jest@^29`.\",\n `cwd: ${cwd}`,\n ...attempts,\n ].join(\"\\n\")\n );\n}\n\nexport async function runJest(args: string[] = [], options: RunJestOptions = {}): Promise<ExecResult> {\n const {\n verbose = false,\n coverage = false,\n ignoreErrors = true,\n disableVerbose = false,\n } = options;\n\n const runner = resolveJestRunner();\n const command = runner.command;\n const jestArgs = [...runner.argsPrefix];\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 !noBanner;\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\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 renderedTitle = cfonts.render(text, {\n font,\n colors: [colors[0] ?? \"cyan\"],\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 renderedSubtitle = subtitle\n ? cfonts.render(subtitle, {\n font,\n colors: [colors[1] ?? colors[0] ?? \"cyan\"],\n align: \"left\",\n background: \"transparent\",\n letterSpacing: 1,\n lineHeight: 1,\n space: false,\n maxLength: \"0\",\n env: \"node\",\n })\n : null;\n\n const stripAnsi = (value: string): string => value.replace(/\\x1b\\[[0-9;]*m/g, \"\");\n const centerLines = (lines: string[], width: number): string[] => {\n return lines.map((line) => {\n const visibleLength = stripAnsi(line).length;\n const leftPad = Math.max(0, Math.floor((width - visibleLength) / 2));\n\n return `${\" \".repeat(leftPad)}${line}`;\n });\n };\n\n const titleLines = renderedTitle.string.trimEnd().split(\"\\n\");\n const subtitleLines = renderedSubtitle ? renderedSubtitle.string.trimEnd().split(\"\\n\") : [];\n const centeredWidth = Math.max(\n ...titleLines.map((line) => stripAnsi(line).length),\n ...(subtitleLines.length > 0 ? subtitleLines : [\"\"]).map((line) => stripAnsi(line).length)\n );\n\n const infoLine = Object.entries(info)\n .map(([key, value]) => `${key}: ${value}`)\n .join(\" | \");\n\n const contentLines = [...centerLines(titleLines, centeredWidth)];\n if (subtitleLines.length > 0) {\n contentLines.push(\"\", ...centerLines(subtitleLines, centeredWidth));\n }\n\n contentLines.push(\"\");\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","import_node_fs","import_node_path","path","stripAnsi","path"]}
|
|
@@ -317,7 +317,7 @@ function logWarning(message) {
|
|
|
317
317
|
// src/core/ui.ts
|
|
318
318
|
var hasWarnedSpinnerFallback = false;
|
|
319
319
|
function shouldShowUI(exportMode, noBanner = false) {
|
|
320
|
-
return !
|
|
320
|
+
return !noBanner;
|
|
321
321
|
}
|
|
322
322
|
function displayBanner(config) {
|
|
323
323
|
const { text, subtitle, info = {}, colors = ["cyan"], font = "block" } = config;
|
|
@@ -485,6 +485,25 @@ function formatCoverageOutput(grouped) {
|
|
|
485
485
|
}
|
|
486
486
|
return output.trim();
|
|
487
487
|
}
|
|
488
|
+
function outputCoverageContext(content, options) {
|
|
489
|
+
const { exportFormat } = options;
|
|
490
|
+
if (!exportFormat) {
|
|
491
|
+
handleExportOrDisplay(content, {
|
|
492
|
+
exportFormat,
|
|
493
|
+
prefix: "export-coverage-context",
|
|
494
|
+
title: "Coverage Context"
|
|
495
|
+
});
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
const exportSpinner = createSpinner("Exporting coverage context...", "magenta");
|
|
499
|
+
exportSpinner.start();
|
|
500
|
+
handleExportOrDisplay(content, {
|
|
501
|
+
exportFormat,
|
|
502
|
+
prefix: "export-coverage-context",
|
|
503
|
+
title: "Coverage Context"
|
|
504
|
+
});
|
|
505
|
+
exportSpinner.succeed("Coverage context exported");
|
|
506
|
+
}
|
|
488
507
|
async function runCoverageContext(argv = process.argv.slice(2)) {
|
|
489
508
|
if (argv.includes("-h") || argv.includes("--help")) {
|
|
490
509
|
displayHelp("Coverage Context Script", {
|
|
@@ -515,8 +534,8 @@ async function runCoverageContext(argv = process.argv.slice(2)) {
|
|
|
515
534
|
logWarning(`Unknown arguments ignored: ${filteredUnknownArgs.join(", ")}`);
|
|
516
535
|
}
|
|
517
536
|
const threshold = parsed.threshold ? Number(parsed.threshold) : 100;
|
|
518
|
-
const
|
|
519
|
-
if (
|
|
537
|
+
const showBanner = shouldShowUI(exportFormat, noBanner);
|
|
538
|
+
if (showBanner) {
|
|
520
539
|
displayBanner({
|
|
521
540
|
text: "JEST",
|
|
522
541
|
subtitle: "COVERAGE",
|
|
@@ -526,8 +545,8 @@ async function runCoverageContext(argv = process.argv.slice(2)) {
|
|
|
526
545
|
colors: ["magenta", "blue"]
|
|
527
546
|
});
|
|
528
547
|
}
|
|
529
|
-
const spinner =
|
|
530
|
-
spinner
|
|
548
|
+
const spinner = createSpinner("Running Jest coverage...", "magenta");
|
|
549
|
+
spinner.start();
|
|
531
550
|
const result = await runJest([], {
|
|
532
551
|
coverage: true,
|
|
533
552
|
coverageReporters: ["text", "text-summary"],
|
|
@@ -535,32 +554,20 @@ async function runCoverageContext(argv = process.argv.slice(2)) {
|
|
|
535
554
|
});
|
|
536
555
|
const rows = parseCoverage(result.output);
|
|
537
556
|
if (rows.length === 0) {
|
|
538
|
-
spinner
|
|
539
|
-
|
|
540
|
-
exportFormat,
|
|
541
|
-
prefix: "export-coverage-context",
|
|
542
|
-
title: "Coverage Context"
|
|
543
|
-
});
|
|
557
|
+
spinner.warn("No coverage rows parsed");
|
|
558
|
+
outputCoverageContext("No coverage rows parsed from Jest output.", { exportFormat });
|
|
544
559
|
return;
|
|
545
560
|
}
|
|
546
561
|
const incomplete = filterIncomplete(rows, threshold);
|
|
547
562
|
const grouped = groupByFolder(incomplete);
|
|
548
563
|
if (Object.keys(grouped).length === 0) {
|
|
549
|
-
spinner
|
|
550
|
-
|
|
551
|
-
exportFormat,
|
|
552
|
-
prefix: "export-coverage-context",
|
|
553
|
-
title: "Coverage Context"
|
|
554
|
-
});
|
|
564
|
+
spinner.succeed(`All files meet threshold >= ${threshold}%`);
|
|
565
|
+
outputCoverageContext(`All files meet threshold >= ${threshold}%`, { exportFormat });
|
|
555
566
|
return;
|
|
556
567
|
}
|
|
557
568
|
const formatted = formatCoverageOutput(grouped);
|
|
558
|
-
spinner
|
|
559
|
-
|
|
560
|
-
exportFormat,
|
|
561
|
-
prefix: "export-coverage-context",
|
|
562
|
-
title: "Coverage Context"
|
|
563
|
-
});
|
|
569
|
+
spinner.warn(`Found ${incomplete.length} file(s) below threshold`);
|
|
570
|
+
outputCoverageContext(formatted, { exportFormat });
|
|
564
571
|
}
|
|
565
572
|
|
|
566
573
|
// src/bin/coverage-context.ts
|