import { browserFormat } from 'vitest/internal/browser' import { getConfig } from '../utils' import { rpc } from './rpc' import { getBrowserRunner } from './runner' const { Date, console, performance } = globalThis export function setupConsoleLogSpy(): void { const { log, info, error, dir, dirxml, trace, time, timeEnd, timeLog, warn, debug, count, countReset, } = console console.log = stdout(log) console.debug = stdout(debug) console.info = stdout(info) console.error = stderr(error) console.warn = stderr(warn) console.dir = (item, options) => { dir(item, options) sendLog('stdout', browserFormat(item)) } console.dirxml = (...args) => { dirxml(...args) sendLog('stdout', processLog(args)) } console.trace = (...args: unknown[]) => { trace(...args) const content = processLog(args) const error = new Error('$$Trace') const processor = (globalThis as any).__vitest_worker__?.onFilterStackTrace || ((s: string) => s || '') const stack = processor(error.stack || '') sendLog('stderr', `${content}\n${stack}`, true) } const timeLabels: Record = {} console.time = (label = 'default') => { time(label) const now = performance.now() timeLabels[label] = now } console.timeLog = (label = 'default') => { timeLog(label) if (!(label in timeLabels)) { sendLog('stderr', `Timer "${label}" does not exist`) } else { sendLog('stdout', `${label}: ${timeLabels[label]} ms`) } } console.timeEnd = (label = 'default') => { timeEnd(label) const end = performance.now() const start = timeLabels[label] if (!(label in timeLabels)) { sendLog('stderr', `Timer "${label}" does not exist`) } else if (typeof start !== 'undefined') { const duration = end - start sendLog('stdout', `${label}: ${duration} ms`) } } const countLabels: Record = {} console.count = (label = 'default') => { count(label) const counter = (countLabels[label] ?? 0) + 1 countLabels[label] = counter sendLog('stdout', `${label}: ${counter}`) } console.countReset = (label = 'default') => { countReset(label) countLabels[label] = 0 } } function stdout(base: (...args: unknown[]) => void) { return (...args: unknown[]) => { base(...args) // ignore shadow root logs from wdio // https://github.com/webdriverio/webdriverio/discussions/14221 if (args[0] === '[WDIO]') { if (args[1] === 'newShadowRoot' || args[1] === 'removeShadowRoot') { return } } sendLog('stdout', processLog(args)) } } function stderr(base: (...args: unknown[]) => void) { return (...args: unknown[]) => { base(...args) sendLog('stderr', processLog(args)) } } function processLog(args: unknown[]) { return browserFormat(...args) } function sendLog( type: 'stdout' | 'stderr', content: string, disableStack?: boolean, ) { if (content.startsWith('[vite]')) { return } const unknownTestId = '__vitest__unknown_test__' // @ts-expect-error untyped global const taskId = globalThis.__vitest_worker__?.current?.id ?? unknownTestId const origin = getConfig().printConsoleTrace && !disableStack ? new Error('STACK_TRACE').stack?.split('\n').slice(1).join('\n') : undefined const runner = getBrowserRunner() rpc().sendLog(runner?.method || 'run', { origin, content, browser: true, time: Date.now(), taskId, type, size: content.length, }) }