Skip to content

Commit bf3db00

Browse files
authored
chore: refactor pretty printer + tests (#25)
* chore: refactor pretty printer * add tests for pretty printer * singualr/plural fix
1 parent bff82d9 commit bf3db00

File tree

5 files changed

+348
-32
lines changed

5 files changed

+348
-32
lines changed

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"files.trimTrailingWhitespaceInRegexAndStrings": false
3+
}

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.test.ts

Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
import { test, expect } from '@playwright/test'
2+
import { print_lines as print, PrintLinesDependencies, type StyleTextFn, TextStyle } from './pretty'
3+
import { Report } from '../program'
4+
import { CoverageResult } from '../../lib'
5+
import { CliArguments } from '../arguments'
6+
import { PrettifiedChunk } from '../../lib/prettify'
7+
8+
// test matrix
9+
// ------------------------------
10+
// overall line coverage success
11+
// overall line coverage fail
12+
// per-file line coverage success
13+
// per-file line coverage fail
14+
// show all
15+
// show violations
16+
// show none
17+
18+
function style_text_fn(_style: TextStyle | TextStyle[], text: string): string {
19+
return text
20+
}
21+
22+
const min_line_coverage_failure = {
23+
min_line_coverage: {
24+
ok: false,
25+
expected: 1,
26+
actual: 0.502222222222,
27+
} satisfies Report['report']['min_line_coverage'],
28+
}
29+
30+
const min_line_coverage_success = {
31+
min_line_coverage: {
32+
ok: true,
33+
expected: 0,
34+
actual: 0.5022222222,
35+
} satisfies Report['report']['min_line_coverage'],
36+
}
37+
38+
const min_file_line_coverage_unset = {
39+
min_file_line_coverage: {
40+
ok: true,
41+
actual: 0.5,
42+
} satisfies Report['report']['min_file_line_coverage'],
43+
}
44+
45+
const min_file_line_coverage_success = {
46+
min_file_line_coverage: {
47+
ok: true,
48+
actual: 1,
49+
expected: 0.5,
50+
} satisfies Report['report']['min_file_line_coverage'],
51+
}
52+
53+
const min_file_line_coverage_failure = {
54+
min_file_line_coverage: {
55+
ok: false,
56+
actual: 0.5,
57+
expected: 1,
58+
} satisfies Report['report']['min_file_line_coverage'],
59+
}
60+
61+
const show_none = { 'show-uncovered': 'none' } as CliArguments
62+
const show_all = { 'show-uncovered': 'all' } as CliArguments
63+
const show_violations = { 'show-uncovered': 'violations' } as CliArguments
64+
65+
const context_empty = {
66+
context: {
67+
coverage: {} as CoverageResult,
68+
},
69+
}
70+
71+
const context_with_failures = {
72+
context: {
73+
coverage: {
74+
line_coverage_ratio: 0.4022222,
75+
covered_lines: 10,
76+
total_lines: 11,
77+
coverage_per_stylesheet: [
78+
{
79+
url: 'example.com',
80+
line_coverage_ratio: 1,
81+
text: `z {
82+
color: yellow
83+
}`,
84+
chunks: [
85+
{
86+
start_line: 1,
87+
end_line: 3,
88+
is_covered: true,
89+
},
90+
],
91+
},
92+
{
93+
url: 'example.com',
94+
line_coverage_ratio: 8 / 19,
95+
covered_lines: 8,
96+
total_lines: 19,
97+
text: `a {
98+
color: red;
99+
}
100+
101+
a1 {
102+
color: blue;
103+
}
104+
105+
b {
106+
color: red;
107+
}
108+
109+
b1 {
110+
color: blue;
111+
}
112+
113+
c {
114+
color: red;
115+
}`,
116+
chunks: [
117+
{
118+
start_line: 1,
119+
end_line: 3,
120+
is_covered: false,
121+
},
122+
{
123+
start_line: 4,
124+
end_line: 8,
125+
is_covered: true,
126+
},
127+
{
128+
start_line: 9,
129+
end_line: 11,
130+
is_covered: false,
131+
},
132+
{
133+
start_line: 12,
134+
end_line: 16,
135+
is_covered: true,
136+
},
137+
{
138+
start_line: 17,
139+
end_line: 19,
140+
is_covered: false,
141+
},
142+
],
143+
},
144+
],
145+
} as CoverageResult,
146+
},
147+
}
148+
149+
const dependencies = { styleText: style_text_fn, print_width: 60 } satisfies PrintLinesDependencies
150+
151+
test.describe('only --min-line-coverage', () => {
152+
test('success', () => {
153+
const report = {
154+
...context_empty,
155+
report: {
156+
ok: true,
157+
...min_line_coverage_success,
158+
...min_file_line_coverage_unset,
159+
},
160+
} satisfies Report
161+
let result = print(report, show_none, dependencies)
162+
expect(result).toEqual(['Success: total line coverage is 50.22%'])
163+
})
164+
165+
test('failure', () => {
166+
const report = {
167+
...context_empty,
168+
report: {
169+
ok: false,
170+
...min_line_coverage_failure,
171+
...min_file_line_coverage_unset,
172+
},
173+
} satisfies Report
174+
let result = print(report, show_none, dependencies)
175+
expect(result).toEqual(['Failed: line coverage is 50.22%% which is lower than the threshold of 1'])
176+
})
177+
})
178+
179+
test.describe('with --min-file-line-coverage', () => {
180+
test('--min-line-coverage: success; --min-file-line-coverage: success; --show: none', () => {
181+
let report = {
182+
...context_empty,
183+
report: {
184+
ok: true,
185+
...min_line_coverage_success,
186+
...min_file_line_coverage_success,
187+
},
188+
} satisfies Report
189+
let result = print(report, show_none, dependencies)
190+
expect(result).toEqual(['Success: total line coverage is 50.22%', 'Success: all files pass minimum line coverage of 50.00%'])
191+
})
192+
193+
test.describe('--min-line-coverage: success; --min-file-line-coverage: failure; --show: none', () => {
194+
let report = {
195+
...context_with_failures,
196+
report: {
197+
ok: false,
198+
...min_line_coverage_success,
199+
...min_file_line_coverage_failure,
200+
},
201+
} satisfies Report
202+
let result = print(report, show_none, dependencies)
203+
204+
test('coverage: pass', () => {
205+
expect(result[0]).toEqual('Success: total line coverage is 50.22%')
206+
})
207+
test('file-coverage: fail', () => {
208+
expect(result[1]).toEqual('Failed: 1 file does not meet the minimum line coverage of 100% (minimum coverage was 50.00%)')
209+
})
210+
test('shows hint to --show=violations', () => {
211+
expect(result[2]).toEqual(" Hint: set --show-uncovered=violations to see which files didn't pass")
212+
})
213+
test('no files shown', () => {
214+
expect(result).toHaveLength(3)
215+
})
216+
})
217+
218+
test.describe('--min-line-coverage: success; --min-file-line-coverage: failure; --show: violations', () => {
219+
let report = {
220+
...context_with_failures,
221+
report: {
222+
ok: false,
223+
...min_line_coverage_success,
224+
...min_file_line_coverage_failure,
225+
},
226+
} satisfies Report
227+
let result = print(report, show_violations, dependencies)
228+
229+
test('coverage: pass', () => {
230+
expect(result[0]).toEqual('Success: total line coverage is 50.22%')
231+
})
232+
test('file-coverage: fail', () => {
233+
expect(result[1]).toEqual('Failed: 1 file does not meet the minimum line coverage of 100% (minimum coverage was 50.00%)')
234+
})
235+
test('does not show hint to --show=violations', () => {
236+
expect(result[2]).not.toEqual(" Hint: set --show-uncovered=violations to see which files didn't pass")
237+
})
238+
test.describe('shows file details', () => {
239+
let lines = result.slice(2)
240+
241+
test('shows header block', () => {
242+
expect(lines[0]).toEqual('─'.repeat(60))
243+
expect(lines[4]).toEqual(lines[0])
244+
})
245+
test('shows file name', () => {
246+
expect(lines[1]).toEqual('example.com')
247+
})
248+
test('shows coverage info', () => {
249+
expect(lines[2]).toEqual('Coverage: 42.11%, 8/19 lines covered')
250+
})
251+
test('shows hint with how many lines to cover to reach threshold', () => {
252+
expect(lines[3]).toEqual('Tip: cover 11 more lines to meet the file threshold of 100%')
253+
})
254+
test('result snapshot', () => {
255+
let snapshot = lines.join('\n')
256+
expect(snapshot).toEqual(
257+
`
258+
────────────────────────────────────────────────────────────
259+
example.com
260+
Coverage: 42.11%, 8/19 lines covered
261+
Tip: cover 11 more lines to meet the file threshold of 100%
262+
────────────────────────────────────────────────────────────
263+
1 ━ a {
264+
2 ━ color: red;
265+
3 ━ }
266+
4 │
267+
5 │ a1 {
268+
6 │ color: blue;
269+
7 │ }
270+
8 │
271+
9 ━ b {
272+
10 ━ color: red;
273+
11 ━ }
274+
12 │
275+
13 │ b1 {
276+
14 │ color: blue;
277+
15 │ }
278+
16 │
279+
17 ━ c {
280+
18 ━ color: red;
281+
19 ━ }`.trim(),
282+
)
283+
})
284+
})
285+
})
286+
})

0 commit comments

Comments
 (0)