mirror of
https://github.com/vitest-dev/vitest.git
synced 2025-12-08 18:26:03 +00:00
111 lines
2.5 KiB
TypeScript
111 lines
2.5 KiB
TypeScript
import type Convert from 'ansi-to-html'
|
|
import type { RunnerTask, TestError } from 'vitest'
|
|
import { parseStacktrace } from '@vitest/utils/source-map'
|
|
import Filter from 'ansi-to-html'
|
|
import { escapeHtml } from '~/utils/escape'
|
|
|
|
declare module '@vitest/runner' {
|
|
interface TaskResult {
|
|
htmlError?: string
|
|
}
|
|
}
|
|
|
|
export function isTestFile(name: string, fileName?: string) {
|
|
return fileName && name.endsWith(fileName)
|
|
}
|
|
|
|
export async function openInEditor(name: string, line: number, column: number) {
|
|
const url = encodeURI(`${name}:${line}:${column}`)
|
|
await fetch(`/__open-in-editor?file=${url}`)
|
|
}
|
|
|
|
export function createAnsiToHtmlFilter(dark: boolean) {
|
|
return new Filter({
|
|
fg: dark ? '#FFF' : '#000',
|
|
bg: dark ? '#000' : '#FFF',
|
|
})
|
|
}
|
|
|
|
function isPrimitive(value: unknown) {
|
|
return (
|
|
value === null || (typeof value !== 'function' && typeof value !== 'object')
|
|
)
|
|
}
|
|
|
|
export function parseError(e: unknown) {
|
|
let error = e as TestError
|
|
|
|
if (isPrimitive(e)) {
|
|
error = {
|
|
message: String(error).split(/\n/g)[0],
|
|
stack: String(error),
|
|
name: '',
|
|
stacks: [],
|
|
}
|
|
}
|
|
|
|
if (!e) {
|
|
const err = new Error('unknown error')
|
|
error = {
|
|
message: err.message,
|
|
stack: err.stack,
|
|
name: '',
|
|
stacks: [],
|
|
}
|
|
}
|
|
|
|
error.stacks = parseStacktrace(error.stack || '', {
|
|
ignoreStackEntries: [],
|
|
})
|
|
|
|
return error
|
|
}
|
|
|
|
function createHtmlError(filter: Convert, error: TestError) {
|
|
let htmlError = ''
|
|
if (error.message?.includes('\x1B')) {
|
|
htmlError = `<b>${error.name}</b>: ${filter.toHtml(
|
|
escapeHtml(error.message),
|
|
)}`
|
|
}
|
|
|
|
const startStrWithX1B = error.stack?.includes('\x1B')
|
|
if (startStrWithX1B) {
|
|
if (htmlError.length > 0) {
|
|
htmlError += filter.toHtml(
|
|
escapeHtml((error.stack) as string),
|
|
)
|
|
}
|
|
else {
|
|
htmlError = `<b>${error.name}</b>: ${
|
|
error.message
|
|
}${filter.toHtml(
|
|
escapeHtml((error.stack) as string),
|
|
)}`
|
|
}
|
|
}
|
|
|
|
if (htmlError.length > 0) {
|
|
return htmlError
|
|
}
|
|
return null
|
|
}
|
|
|
|
export function mapLeveledTaskStacks(dark: boolean, tasks: RunnerTask[]) {
|
|
const filter = createAnsiToHtmlFilter(dark)
|
|
return tasks.map((t) => {
|
|
const result = t.result
|
|
if (!result || result.htmlError) {
|
|
return t
|
|
}
|
|
const errors = result.errors
|
|
?.map(error => createHtmlError(filter, error))
|
|
.filter(error => error != null)
|
|
.join('<br><br>')
|
|
if (errors?.length) {
|
|
result.htmlError = errors
|
|
}
|
|
return t
|
|
})
|
|
}
|