Skip to content

Commit e6792a9

Browse files
authoredMay 24, 2023
fix: dot reporter scrollback buffer spam (#3415)
1 parent 9fbb8d3 commit e6792a9

File tree

1 file changed

+41
-21
lines changed

1 file changed

+41
-21
lines changed
 

‎packages/vitest/src/node/reporters/renderers/dotRenderer.ts

+41-21
Original file line numberDiff line numberDiff line change
@@ -27,54 +27,74 @@ function getIcon(task: Task) {
2727
}
2828
}
2929

30-
function render(tasks: Task[]): string {
30+
function render(tasks: Task[], width: number): string {
3131
const all = getTests(tasks)
32-
const output: string[] = []
32+
let currentIcon = pending
33+
let currentTasks = 0
34+
let previousLineWidth = 0
35+
let output = ''
3336

3437
// The log-update uses various ANSI helper utilities, e.g. ansi-warp, ansi-slice,
3538
// when printing. Passing it hundreds of single characters containing ANSI codes reduces
3639
// performances. We can optimize it by reducing amount of ANSI codes, e.g. by coloring
3740
// multiple tasks at once instead of each task separately.
38-
let currentIcon = pending
39-
let currentTasks = 0
40-
41-
const addOutput = () => output.push(currentIcon.color(currentIcon.char.repeat(currentTasks)))
41+
const addOutput = () => {
42+
const { char, color } = currentIcon
43+
const availableWidth = width - previousLineWidth
44+
if (availableWidth > currentTasks) {
45+
output += color(char.repeat(currentTasks))
46+
previousLineWidth += currentTasks
47+
}
48+
else {
49+
// We need to split the line otherwise it will mess up log-update's height calculation
50+
// and spam the scrollback buffer with dots.
51+
52+
// Fill the current line first
53+
let buf = `${char.repeat(availableWidth)}\n`
54+
const remaining = currentTasks - availableWidth
55+
56+
// Then fill as many full rows as possible
57+
const fullRows = Math.floor(remaining / width)
58+
buf += `${char.repeat(width)}\n`.repeat(fullRows)
59+
60+
// Add remaining dots which don't make a full row
61+
const partialRow = remaining % width
62+
if (partialRow > 0) {
63+
buf += char.repeat(partialRow)
64+
previousLineWidth = partialRow
65+
}
66+
else {
67+
previousLineWidth = 0
68+
}
4269

70+
output += color(buf)
71+
}
72+
}
4373
for (const task of all) {
4474
const icon = getIcon(task)
45-
const isLast = all.indexOf(task) === all.length - 1
46-
4775
if (icon === currentIcon) {
4876
currentTasks++
49-
50-
if (isLast)
51-
addOutput()
52-
5377
continue
5478
}
55-
5679
// Task mode/state has changed, add previous group to output
5780
addOutput()
5881

5982
// Start tracking new group
6083
currentTasks = 1
6184
currentIcon = icon
62-
63-
if (isLast)
64-
addOutput()
6585
}
66-
67-
return output.join('')
86+
addOutput()
87+
return output
6888
}
6989

7090
export function createDotRenderer(_tasks: Task[], options: DotRendererOptions) {
7191
let tasks = _tasks
7292
let timer: any
7393

74-
const log = options.logger.logUpdate
94+
const { logUpdate: log, outputStream } = options.logger
7595

7696
function update() {
77-
log(render(tasks))
97+
log(render(tasks, outputStream.columns))
7898
}
7999

80100
return {
@@ -94,7 +114,7 @@ export function createDotRenderer(_tasks: Task[], options: DotRendererOptions) {
94114
timer = undefined
95115
}
96116
log.clear()
97-
options.logger.log(render(tasks))
117+
options.logger.log(render(tasks, outputStream.columns))
98118
return this
99119
},
100120
clear() {

0 commit comments

Comments
 (0)
Please sign in to comment.