Skip to content

Commit 96765e3

Browse files
committed
chore: refactor pretty printer
1 parent bff82d9 commit 96765e3

File tree

3 files changed

+49
-29
lines changed

3 files changed

+49
-29
lines changed

src/cli/cli.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
#!/usr/bin/env node
22

3+
import { styleText } from 'node:util'
4+
import { console } from 'node:inspector'
35
import { validate_arguments, parse_arguments } from './arguments.js'
46
import { program } from './program.js'
57
import { read } from './file-reader.js'
68
import { print as pretty } from './reporters/pretty.js'
79
import { print as tap } from './reporters/tap.js'
810

911
async function cli(cli_args: string[]) {
10-
console.log(cli_args)
1112
let params = validate_arguments(parse_arguments(cli_args))
12-
console.log(params)
1313
let coverage_data = await read(params['coverage-dir'])
1414
let report = program(
1515
{
@@ -23,11 +23,10 @@ async function cli(cli_args: string[]) {
2323
process.exitCode = 1
2424
}
2525

26-
if (params.reporter === 'pretty') {
27-
pretty(report, params)
28-
} else if (params.reporter === 'tap') {
29-
tap(report, params)
26+
if (params.reporter === 'tap') {
27+
return tap(report, params)
3028
}
29+
return pretty(report, params)
3130
}
3231

3332
try {

src/cli/reporters/pretty.ts

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,43 @@ function indent(line?: string): string {
88
return (line || '').replace(/^\t+/, (tabs) => ' '.repeat(tabs.length * 4))
99
}
1010

11-
export function print({ report, context }: Report, params: CliArguments) {
11+
function percentage(ratio: number): string {
12+
return `${(ratio * 100).toFixed(2)}%`
13+
}
14+
15+
type TextStyle = 'bold' | 'red' | 'dim' | 'green'
16+
type StyleTextFn = (style: TextStyle | TextStyle[], input: string) => string
17+
18+
export function print_lines(
19+
{ report, context }: Report,
20+
params: CliArguments,
21+
{ styleText, print_width }: { styleText: StyleTextFn; print_width?: number },
22+
) {
23+
let output: (string | undefined)[] = []
24+
1225
if (report.min_line_coverage.ok) {
13-
console.log(`${styleText(['bold', 'green'], 'Success')}: total line coverage is ${(report.min_line_coverage.actual * 100).toFixed(2)}%`)
26+
output.push(`${styleText(['bold', 'green'], 'Success')}: total line coverage is ${percentage(report.min_line_coverage.actual)}%`)
1427
} else {
15-
console.error(
16-
`${styleText(['bold', 'red'], 'Failed')}: line coverage is ${(report.min_line_coverage.actual * 100).toFixed(
17-
2,
28+
output.push(
29+
`${styleText(['bold', 'red'], 'Failed')}: line coverage is ${percentage(
30+
report.min_line_coverage.actual,
1831
)}% which is lower than the threshold of ${report.min_line_coverage.expected}`,
1932
)
2033
}
2134

2235
if (report.min_file_line_coverage.expected !== undefined) {
2336
let { expected, actual, ok } = report.min_file_line_coverage
2437
if (ok) {
25-
console.log(`${styleText(['bold', 'green'], 'Success')}: all files pass minimum line coverage of ${expected * 100}%`)
38+
output.push(`${styleText(['bold', 'green'], 'Success')}: all files pass minimum line coverage of ${percentage(expected)}%`)
2639
} else {
2740
let num_files_failed = context.coverage.coverage_per_stylesheet.filter((sheet) => sheet.line_coverage_ratio < expected!).length
28-
console.error(
29-
`${styleText(['bold', 'red'], 'Failed')}: ${num_files_failed} files do not meet the minimum line coverage of ${
30-
expected * 100
31-
}% (minimum coverage was ${(actual * 100).toFixed(2)}%)`,
41+
output.push(
42+
`${styleText(['bold', 'red'], 'Failed')}: ${num_files_failed} ${
43+
num_files_failed === 1 ? 'file does' : 'files do'
44+
} not meet the minimum line coverage of ${percentage(expected)} (minimum coverage was ${percentage(actual)})`,
3245
)
3346
if (params['show-uncovered'] === 'none') {
34-
console.log(` Hint: set --show-uncovered=violations to see which files didn't pass`)
47+
output.push(` Hint: set --show-uncovered=violations to see which files didn't pass`)
3548
}
3649
}
3750
}
@@ -40,7 +53,7 @@ export function print({ report, context }: Report, params: CliArguments) {
4053
if (params['show-uncovered'] !== 'none') {
4154
const NUM_LEADING_LINES = 3
4255
const NUM_TRAILING_LINES = NUM_LEADING_LINES
43-
let terminal_width = process.stdout.columns || 80
56+
print_width = print_width ?? 80
4457
let line_number = (num: number, covered: boolean = true) => `${num.toString().padStart(5, ' ')} ${covered ? '│' : '━'} `
4558
let min_file_line_coverage = report.min_file_line_coverage.expected
4659

@@ -52,36 +65,44 @@ export function print({ report, context }: Report, params: CliArguments) {
5265
sheet.line_coverage_ratio < min_file_line_coverage &&
5366
params['show-uncovered'] === 'violations')
5467
) {
55-
console.log()
56-
console.log(styleText('dim', '─'.repeat(terminal_width)))
57-
console.log(sheet.url)
58-
console.log(`Coverage: ${(sheet.line_coverage_ratio * 100).toFixed(2)}%, ${sheet.covered_lines}/${sheet.total_lines} lines covered`)
68+
output.push()
69+
output.push(styleText('dim', '─'.repeat(print_width)))
70+
output.push(sheet.url)
71+
output.push(`Coverage: ${percentage(sheet.line_coverage_ratio)}, ${sheet.covered_lines}/${sheet.total_lines} lines covered`)
5972

6073
if (min_file_line_coverage && min_file_line_coverage !== 0 && sheet.line_coverage_ratio < min_file_line_coverage) {
6174
let lines_to_cover = min_file_line_coverage * sheet.total_lines - sheet.covered_lines
62-
console.log(`Tip: cover ${Math.ceil(lines_to_cover)} more lines to meet the file threshold of ${min_file_line_coverage * 100}%`)
75+
output.push(
76+
`Tip: cover ${Math.ceil(lines_to_cover)} more lines to meet the file threshold of ${percentage(min_file_line_coverage)}`,
77+
)
6378
}
64-
console.log(styleText('dim', '─'.repeat(terminal_width)))
79+
output.push(styleText('dim', '─'.repeat(print_width)))
6580

6681
let lines = sheet.text.split('\n')
6782

6883
for (let chunk of sheet.chunks.filter((chunk) => !chunk.is_covered)) {
6984
// Render N leading lines
7085
for (let x = Math.max(chunk.start_line - NUM_LEADING_LINES, 0); x < chunk.start_line; x++) {
71-
console.log(styleText('dim', line_number(x)), styleText('dim', indent(lines[x - 1])))
86+
output.push([styleText('dim', line_number(x)), styleText('dim', indent(lines[x - 1]))].join(''))
7287
}
7388
// Render the uncovered chunk
7489
for (let i = chunk.start_line; i <= chunk.end_line; i++) {
75-
console.log(styleText('red', line_number(i, false)), indent(lines[i - 1]))
90+
output.push([styleText('red', line_number(i, false)), indent(lines[i - 1])].join(''))
7691
}
7792
// Render N trailing lines
7893
for (let y = chunk.end_line; y < Math.min(chunk.end_line + NUM_TRAILING_LINES, lines.length); y++) {
79-
console.log(styleText('dim', line_number(y)), styleText('dim', indent(lines[y - 1])))
94+
output.push([styleText('dim', line_number(y)), styleText('dim', indent(lines[y - 1]))].join(''))
8095
}
8196
// Show empty line between blocks
82-
console.log()
97+
output.push()
8398
}
8499
}
85100
}
86101
}
102+
103+
return output
104+
}
105+
106+
export function print(report: Report, params: CliArguments): void {
107+
print_lines(report, params, { styleText, print_width: process.stdout.columns }).map((line) => console.log(line))
87108
}

src/cli/reporters/tap.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ function meta(data: Record<string | number, string | number>) {
2525
console.log(' ...')
2626
}
2727

28-
export function print({ report, context }: Report, params: CliArguments) {
28+
export function print({ report, context }: Report, params: CliArguments): void {
2929
let total_files = context.coverage.coverage_per_stylesheet.length
3030
let total_checks = total_files + 1
3131
let checks_added = 1

0 commit comments

Comments
 (0)