-
-
Notifications
You must be signed in to change notification settings - Fork 1k
/
logger.ts
118 lines (98 loc) · 3.55 KB
/
logger.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import { createLogUpdate } from 'log-update'
import c from 'picocolors'
import { version } from '../../../../package.json'
import type { ErrorWithDiff } from '../types'
import { divider } from './reporters/renderers/utils'
import type { Vitest } from './core'
import { printError } from './error'
export class Logger {
outputStream = process.stdout
errorStream = process.stderr
logUpdate = createLogUpdate(process.stdout)
private _clearScreenPending: string | undefined
constructor(
public ctx: Vitest,
public console = globalThis.console,
) {
}
log(...args: any[]) {
this._clearScreen()
this.console.log(...args)
}
error(...args: any[]) {
this._clearScreen()
this.console.error(...args)
}
warn(...args: any[]) {
this._clearScreen()
this.console.warn(...args)
}
clearScreen(message: string, force = false) {
if (this.ctx.server.config.clearScreen === false) {
this.console.log(message)
return
}
this._clearScreenPending = message
if (force)
this._clearScreen()
}
private _clearScreen() {
if (!this._clearScreenPending)
return
const log = this._clearScreenPending
this._clearScreenPending = undefined
// equivalent to ansi-escapes:
// stdout.write(ansiEscapes.cursorTo(0, 0) + ansiEscapes.eraseDown + log)
this.console.log(`\u001B[1;1H\u001B[J${log}`)
}
printError(err: unknown, fullStack = false, type?: string) {
return printError(err, this.ctx, {
fullStack,
type,
showCodeFrame: true,
})
}
printNoTestFound(filters?: string[]) {
const config = this.ctx.config
const comma = c.dim(', ')
if (filters?.length)
this.console.error(c.dim('filter: ') + c.yellow(filters.join(comma)))
if (config.include)
this.console.error(c.dim('include: ') + c.yellow(config.include.join(comma)))
if (config.exclude)
this.console.error(c.dim('exclude: ') + c.yellow(config.exclude.join(comma)))
if (config.watchExclude)
this.console.error(c.dim('watch exclude: ') + c.yellow(config.watchExclude.join(comma)))
if (config.passWithNoTests)
this.log('No test files found, exiting with code 0\n')
else
this.error(c.red('\nNo test files found, exiting with code 1'))
}
printBanner() {
this.log()
const versionTest = this.ctx.config.watch
? c.blue(`v${version}`)
: c.cyan(`v${version}`)
const mode = this.ctx.config.watch
? c.blue(' DEV ')
: c.cyan(' RUN ')
this.log(`${c.inverse(c.bold(mode))} ${versionTest} ${c.gray(this.ctx.config.root)}`)
if (this.ctx.config.ui)
this.log(c.dim(c.green(` UI started at http://${this.ctx.config.api?.host || 'localhost'}:${c.bold(`${this.ctx.server.config.server.port}`)}${this.ctx.config.uiBase}`)))
else if (this.ctx.config.api)
this.log(c.dim(c.green(` API started at http://${this.ctx.config.api?.host || 'localhost'}:${c.bold(`${this.ctx.config.api.port}`)}`)))
this.log()
}
async printUnhandledErrors(errors: unknown[]) {
const errorMessage = c.red(c.bold(
`\nVitest caught ${errors.length} unhandled error${errors.length > 1 ? 's' : ''} during the test run. This might cause false positive tests.`
+ '\nPlease, resolve all the errors to make sure your tests are not affected.',
))
this.log(c.red(divider(c.bold(c.inverse(' Unhandled Errors ')))))
this.log(errorMessage)
await Promise.all(errors.map(async (err) => {
await this.printError(err, true, (err as ErrorWithDiff).type || 'Unhandled Error')
}))
this.log(c.red(divider()))
}
}