diff --git a/packages/worker-legacy/src/reporter.ts b/packages/worker-legacy/src/reporter.ts index 976a9351..7d7b8734 100644 --- a/packages/worker-legacy/src/reporter.ts +++ b/packages/worker-legacy/src/reporter.ts @@ -1,7 +1,21 @@ import type { BirpcReturn } from 'birpc' -import type { ErrorWithDiff, RunnerTestFile, TaskResultPack, UserConsoleLog } from 'vitest' +import type { + ErrorWithDiff, + RunnerTask, + RunnerTestFile, + TaskResultPack, + UserConsoleLog, +} from 'vitest' import type { ExtensionWorkerEvents, ExtensionWorkerTransport } from 'vitest-vscode-shared' -import type { BrowserCommand, Vitest as VitestCore, WorkspaceProject } from 'vitest/node' +import type { + BrowserCommand, + TestCase, + TestModule, + TestResult, + TestSuite, + Vitest as VitestCore, + WorkspaceProject, +} from 'vitest/node' import type { Reporter } from 'vitest/reporters' import { Console } from 'node:console' import { nextTick } from 'node:process' @@ -17,6 +31,7 @@ export class VSCodeReporter implements Reporter { public rpc!: BirpcReturn private vitest!: VitestCore private setupFilePaths: string[] + private silent: boolean | 'passed-only' = false constructor(options: VSCodeReporterOptions) { this.setupFilePaths = options.setupFilePaths @@ -31,6 +46,7 @@ export class VSCodeReporter implements Reporter { onInit(vitest: VitestCore) { this.vitest = vitest + this.silent = vitest.config.silent const server = vitest.server.config.server this.setupFilePaths.forEach((setupFile) => { if (!server.fs.allow.includes(setupFile)) server.fs.allow.push(setupFile) @@ -95,7 +111,11 @@ export class VSCodeReporter implements Reporter { this.rpc = rpc } - onUserConsoleLog(log: UserConsoleLog) { + onUserConsoleLog(log: UserConsoleLog, taskState?: TestResult['state']) { + if (!this.shouldLog(log, taskState)) { + return + } + // Parse stack trace to extract file location for inline display const extendedLog = log as any if (log.origin) { @@ -118,6 +138,50 @@ export class VSCodeReporter implements Reporter { return this.rpc.onConsoleLog(extendedLog) } + onTestCaseResult(testCase: TestCase): void { + if (testCase.result().state === 'failed') { + this.logFailedTask(getRunnerTask(testCase)) + } + } + + onTestSuiteResult(testSuite: TestSuite): void { + if (testSuite.state() === 'failed') { + this.logFailedTask(getRunnerTask(testSuite)) + } + } + + onTestModuleEnd(testModule: TestModule): void { + if (testModule.state() === 'failed') { + this.logFailedTask(getRunnerTask(testModule)) + } + } + + private logFailedTask(task: RunnerTask) { + if (this.vitest.config.silent === 'passed-only') { + for (const log of task.logs || []) { + this.onUserConsoleLog(log, 'failed') + } + } + } + + shouldLog(log: UserConsoleLog, taskState?: TestResult['state']): boolean { + if (this.silent === true) { + return false + } + + if (this.silent === 'passed-only' && taskState !== 'failed') { + return false + } + + if (this.vitest.config.onConsoleLog) { + const shouldLog = this.vitest.config.onConsoleLog(log.content, log.type) + if (shouldLog === false) { + return false + } + } + return true + } + private logPromises = new Set>() sendTerminalLog(type: 'stderr' | 'stdout', message: string) { if (!this.rpc) { @@ -239,3 +303,7 @@ export class VSCodeReporter implements Reporter { function isPrimitive(value: unknown) { return value === null || (typeof value !== 'function' && typeof value !== 'object') } + +function getRunnerTask(value: any): RunnerTask { + return value.task +} diff --git a/packages/worker/src/reporter.ts b/packages/worker/src/reporter.ts index f447b34d..d91536a7 100644 --- a/packages/worker/src/reporter.ts +++ b/packages/worker/src/reporter.ts @@ -4,10 +4,14 @@ import type { BrowserCommand, Reporter, ResolvedConfig, + RunnerTask, RunnerTestFile, + TestCase, TestModule, TestProject, + TestResult, TestSpecification, + TestSuite, Vite, Vitest as VitestCore, } from 'vitest/node' @@ -24,6 +28,7 @@ export class VSCodeReporter implements Reporter { private debuggerAttached: boolean | undefined = undefined private coverageData: Record | undefined = undefined + private silent: boolean | 'passed-only' = false constructor(meta: WorkerInitMetadata, debug: WorkerRunnerOptions['debug']) { this.setupFilePaths = meta.setupFilePaths @@ -36,6 +41,7 @@ export class VSCodeReporter implements Reporter { onInit(vitest: VitestCore) { this.vitest = vitest this.configureAttachDebugging(vitest) + this.silent = vitest.config.silent vitest.projects.forEach((project) => { this.ensureSetupFileIsAllowed(project.vite.config) @@ -59,7 +65,11 @@ export class VSCodeReporter implements Reporter { project.browser!.parent.commands.__vscode_waitForDebugger = __vscode_waitForDebugger } - onUserConsoleLog(log: UserConsoleLog) { + onUserConsoleLog(log: UserConsoleLog, taskState?: TestResult['state']) { + if (!this.shouldLog(log, taskState)) { + return + } + // Parse stack trace to extract file location for inline display const extendedLog = log as any if (log.origin) { @@ -89,6 +99,52 @@ export class VSCodeReporter implements Reporter { return this.rpc.onConsoleLog(extendedLog) } + onTestCaseResult(testCase: TestCase): void { + if (testCase.result().state === 'failed') { + this.logFailedTask(getRunnerTask(testCase)) + } + } + + onTestSuiteResult(testSuite: TestSuite): void { + if (testSuite.state() === 'failed') { + this.logFailedTask(getRunnerTask(testSuite)) + } + } + + onTestModuleEnd(testModule: TestModule): void { + if (testModule.state() === 'failed') { + this.logFailedTask(getRunnerTask(testModule)) + } + } + + protected logFailedTask(task: RunnerTask): void { + if (this.silent === 'passed-only') { + for (const log of task.logs || []) { + this.onUserConsoleLog(log, 'failed') + } + } + } + + shouldLog(log: UserConsoleLog, taskState?: TestResult['state']): boolean { + if (this.silent === true) { + return false + } + + if (this.silent === 'passed-only' && taskState !== 'failed') { + return false + } + + if (this.vitest.config.onConsoleLog) { + const task = log.taskId ? this.vitest.state.idMap.get(log.taskId) : undefined + const entity = task && this.vitest.state.getReportedEntity(task) + const shouldLog = this.vitest.config.onConsoleLog(log.content, log.type, entity) + if (shouldLog === false) { + return false + } + } + return true + } + onTaskUpdate(packs: RunnerTaskResultPack[]) { this.rpc.onTaskUpdate( // remove the meta because it is not used, @@ -213,3 +269,7 @@ export class VSCodeReporter implements Reporter { function getEntityJSONTask(entity: TestModule) { return (entity as any).task as RunnerTestFile } + +function getRunnerTask(value: any): RunnerTask { + return value.task +}