diff --git a/packages/vitest/src/node/config/serializeConfig.ts b/packages/vitest/src/node/config/serializeConfig.ts index 7be23a3cb071..ca0115c32eb8 100644 --- a/packages/vitest/src/node/config/serializeConfig.ts +++ b/packages/vitest/src/node/config/serializeConfig.ts @@ -1,6 +1,7 @@ import type { TestProject } from '../project' import type { ApiConfig, SerializedConfig } from '../types/config' import { configDefaults } from '../../defaults' +import { isAgent } from '../../utils/env' export function serializeConfig(project: TestProject): SerializedConfig { const { config, globalConfig } = project @@ -146,5 +147,6 @@ export function serializeConfig(project: TestProject): SerializedConfig { config.slowTestThreshold ?? globalConfig.slowTestThreshold ?? configDefaults.slowTestThreshold, + isAgent, } } diff --git a/packages/vitest/src/node/core.ts b/packages/vitest/src/node/core.ts index c753835c9e0a..457b417ca40b 100644 --- a/packages/vitest/src/node/core.ts +++ b/packages/vitest/src/node/core.ts @@ -21,10 +21,12 @@ import { SnapshotManager } from '@vitest/snapshot/manager' import { deepClone, deepMerge, nanoid, toArray } from '@vitest/utils/helpers' import { serializeValue } from '@vitest/utils/serialize' import { join, normalize, relative } from 'pathe' +import { disableDefaultColors } from 'tinyrainbow' import { isRunnableDevEnvironment } from 'vite' import { version } from '../../package.json' with { type: 'json' } import { distDir } from '../paths' import { wildcardPatternToRegExp } from '../utils/base' +import { isAgent } from '../utils/env' import { NativeModuleRunner } from '../utils/nativeModuleRunner' import { convertTasksToEvents } from '../utils/tasks' import { Traces } from '../utils/traces' @@ -137,6 +139,10 @@ export class Vitest { cliOptions: UserConfig, options: VitestOptions = {}, ) { + if (isAgent) { + disableDefaultColors() + } + this._cliOptions = cliOptions this.logger = new Logger(this, options.stdout, options.stderr) this.packageInstaller = options.packageInstaller || new VitestPackageInstaller() diff --git a/packages/vitest/src/runtime/config.ts b/packages/vitest/src/runtime/config.ts index a50b5c0aa83d..f2e2cbbf8304 100644 --- a/packages/vitest/src/runtime/config.ts +++ b/packages/vitest/src/runtime/config.ts @@ -146,6 +146,7 @@ export interface SerializedConfig { tagsFilter: string[] | undefined strictTags: boolean slowTestThreshold: number | undefined + isAgent: boolean } export interface SerializedCoverageConfig { diff --git a/packages/vitest/src/runtime/workers/init.ts b/packages/vitest/src/runtime/workers/init.ts index b225fda7ff79..431d8da79332 100644 --- a/packages/vitest/src/runtime/workers/init.ts +++ b/packages/vitest/src/runtime/workers/init.ts @@ -3,6 +3,7 @@ import type { WorkerRequest, WorkerResponse } from '../../node/pools/types' import type { WorkerSetupContext } from '../../types/worker' import type { VitestWorker } from './types' import { serializeError } from '@vitest/utils/error' +import { disableDefaultColors } from 'tinyrainbow' import { Traces } from '../../utils/traces' import * as listeners from '../listeners' import { createRuntimeRpc } from '../rpc' @@ -49,6 +50,10 @@ export function init(worker: Options): void { process.env.VITEST_WORKER_ID = String(message.workerId) reportMemory = message.options.reportMemory + if (message.context.config.isAgent) { + disableDefaultColors() + } + traces ??= await new Traces({ enabled: message.traces.enabled, sdkPath: message.traces.sdkPath, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ac52a928ef0e..544d6e2aa361 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -118,8 +118,8 @@ catalogs: specifier: ^0.3.2 version: 0.3.2 tinyrainbow: - specifier: ^3.0.3 - version: 3.0.3 + specifier: ^3.1.0 + version: 3.1.0 tinyspy: specifier: ^4.0.4 version: 4.0.4 @@ -522,7 +522,7 @@ importers: version: 3.0.2 tinyrainbow: specifier: 'catalog:' - version: 3.0.3 + version: 3.1.0 ws: specifier: 'catalog:' version: 8.19.0 @@ -571,7 +571,7 @@ importers: version: link:../mocker tinyrainbow: specifier: 'catalog:' - version: 3.0.3 + version: 3.1.0 devDependencies: playwright: specifier: ^1.58.2 @@ -643,7 +643,7 @@ importers: version: 2.1.1 tinyrainbow: specifier: 'catalog:' - version: 3.0.3 + version: 3.1.0 devDependencies: '@types/istanbul-lib-coverage': specifier: 'catalog:' @@ -704,7 +704,7 @@ importers: version: 4.0.0-rc.1 tinyrainbow: specifier: 'catalog:' - version: 3.0.3 + version: 3.1.0 devDependencies: '@types/istanbul-lib-coverage': specifier: 'catalog:' @@ -747,7 +747,7 @@ importers: version: 6.2.2 tinyrainbow: specifier: 'catalog:' - version: 3.0.3 + version: 3.1.0 devDependencies: '@vitest/runner': specifier: workspace:* @@ -794,7 +794,7 @@ importers: dependencies: tinyrainbow: specifier: 'catalog:' - version: 3.0.3 + version: 3.1.0 devDependencies: '@types/react-is': specifier: ^19.2.0 @@ -861,7 +861,7 @@ importers: version: 0.2.15 tinyrainbow: specifier: 'catalog:' - version: 3.0.3 + version: 3.1.0 vitest: specifier: workspace:* version: link:../vitest @@ -973,7 +973,7 @@ importers: version: 2.0.0 tinyrainbow: specifier: 'catalog:' - version: 3.0.3 + version: 3.1.0 devDependencies: '@jridgewell/trace-mapping': specifier: 'catalog:' @@ -1058,7 +1058,7 @@ importers: version: 0.2.15 tinyrainbow: specifier: 'catalog:' - version: 3.0.3 + version: 3.1.0 vite: specifier: 7.1.5 version: 7.1.5(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) @@ -1475,7 +1475,7 @@ importers: version: 0.3.0 tinyrainbow: specifier: 'catalog:' - version: 3.0.3 + version: 3.1.0 tinyspy: specifier: ^4.0.4 version: 4.0.4 @@ -1580,7 +1580,7 @@ importers: version: 1.0.2 tinyrainbow: specifier: 'catalog:' - version: 3.0.3 + version: 3.1.0 vite: specifier: 7.1.5 version: 7.1.5(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass-embedded@1.97.3)(sass@1.97.3)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) @@ -9663,8 +9663,8 @@ packages: picocolors: optional: true - tinyrainbow@3.0.3: - resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} engines: {node: '>=14.0.0'} tinyspy@4.0.4: @@ -18943,7 +18943,7 @@ snapshots: optionalDependencies: picocolors: 1.1.1 - tinyrainbow@3.0.3: {} + tinyrainbow@3.1.0: {} tinyspy@4.0.4: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 779cdc8ece50..6e43aaa1dce8 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -83,7 +83,7 @@ catalog: tinyexec: ^1.0.2 tinyglobby: ^0.2.15 tinyhighlight: ^0.3.2 - tinyrainbow: ^3.0.3 + tinyrainbow: ^3.1.0 tinyspy: ^4.0.4 typescript: ^5.9.3 unocss: ^66.6.6 diff --git a/test/config/test/console-color.test.ts b/test/config/test/console-color.test.ts index b552908a199a..29a8b54c3fb0 100644 --- a/test/config/test/console-color.test.ts +++ b/test/config/test/console-color.test.ts @@ -1,5 +1,5 @@ import { expect, test } from 'vitest' -import { runVitest } from '../../test-utils' +import { runVitest, runVitestCli } from '../../test-utils' test('with color', async () => { const { stdout } = await runVitest({ @@ -30,6 +30,20 @@ test('without color', async () => { expect(stdout).not.toContain('\x1B[33mtrue\x1B[39m\n') }) +test('agent', async () => { + // Agent check is done on module import, so new process is needed + const { stdout } = await runVitestCli({ + preserveAnsi: true, + nodeOptions: { env: { AI_AGENT: 'copilot' } }, + }, '--root', 'fixtures/console-color', '--reporter', 'default') + + expect.soft(stdout).toContain('true\n') + expect.soft(stdout).not.toContain('\x1B[33mtrue\x1B[39m\n') + + expect.soft(stdout).toContain(' RUN') + expect.soft(stdout).not.toContain('\x1B[46m RUN') +}) + test.skipIf(process.platform === 'win32')('without color, forks pool in non-TTY parent', async () => { const { stdout } = await runVitest({ root: 'fixtures/console-color',