Skip to content

Commit 194ede2

Browse files
committed
feat: customize test.name color in reporters
1 parent 29084f1 commit 194ede2

File tree

23 files changed

+117
-56
lines changed

23 files changed

+117
-56
lines changed

packages/browser/src/node/plugin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ export default (parentServer: ParentBrowserProject, base = '/'): Plugin[] => {
383383
{
384384
name: 'vitest:browser:in-source-tests',
385385
transform(code, id) {
386-
const project = parentServer.vitest.getProjectByName(parentServer.config.name)
386+
const project = parentServer.vitest.getProjectByName(parentServer.config.name.name)
387387
if (!project._isCachedTestFile(id) || !code.includes('import.meta.vitest')) {
388388
return
389389
}

packages/ui/client/components/FileDetails.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ debouncedWatch(
137137
)
138138
139139
const projectNameColor = computed(() => {
140-
return getProjectNameColor(current.value?.file.projectName)
140+
return getProjectNameColor(current.value?.file.projectName, undefined)
141141
})
142142
143143
const projectNameTextColor = computed(() => {

packages/ui/client/utils/task.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,21 @@ export function caseInsensitiveMatch(target: string, str2: string) {
1818
return target.toLowerCase().includes(str2.toLowerCase())
1919
}
2020

21-
export function getProjectNameColor(name: string | undefined) {
21+
export function getProjectNameColor(name: string | undefined, color?: 'Black' | 'Red' | 'Green' | 'Yellow' | 'Blue' | 'Magenta' | 'Cyan' | 'White') {
2222
if (!name) {
2323
return ''
2424
}
25-
const index = name
26-
.split('')
27-
.reduce((acc, v, idx) => acc + v.charCodeAt(0) + idx, 0)
28-
const colors = ['yellow', 'cyan', 'green', 'magenta']
29-
return colors[index % colors.length]
25+
let background = color?.toLowerCase() as Lowercase<NonNullable<typeof color>> | undefined
26+
27+
if (!background) {
28+
const index = name
29+
.split('')
30+
.reduce((acc, v, idx) => acc + v.charCodeAt(0) + idx, 0)
31+
32+
const colors = ['yellow', 'cyan', 'green', 'magenta'] as const
33+
34+
background = colors[index % colors.length]
35+
}
36+
37+
return background
3038
}

packages/vitest/src/api/setup.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ export function setup(ctx: Vitest, _server?: ViteDevServer): void {
121121
const spec = await ctx.globTestSpecifications()
122122
return spec.map(spec => [
123123
{
124-
name: spec.project.config.name,
124+
name: spec.project.config.name.name,
125125
root: spec.project.config.root,
126126
},
127127
spec.moduleId,

packages/vitest/src/node/config/resolveConfig.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ export function resolveConfig(
144144

145145
resolved.project = toArray(resolved.project)
146146
resolved.provide ??= {}
147+
resolved.name ??= { name: '', color: null }
147148

148149
const inspector = resolved.inspect || resolved.inspectBrk
149150

@@ -732,7 +733,7 @@ export function resolveConfig(
732733
let cacheDir = VitestCache.resolveCacheDir(
733734
'',
734735
viteConfig.cacheDir,
735-
resolved.name,
736+
resolved.name.name,
736737
)
737738

738739
if (resolved.cache && resolved.cache.dir) {
@@ -747,7 +748,7 @@ export function resolveConfig(
747748
cacheDir = VitestCache.resolveCacheDir(
748749
resolved.root,
749750
resolved.cache.dir,
750-
resolved.name,
751+
resolved.name.name,
751752
)
752753
}
753754

@@ -918,7 +919,7 @@ function isPlaywrightChromiumOnly(vitest: Vitest, config: ResolvedConfig) {
918919
return false
919920
}
920921
for (const instance of browser.instances) {
921-
const name = instance.name || (config.name ? `${config.name} (${instance.browser})` : instance.browser)
922+
const name = instance.name || (config.name ? `${config.name.name} (${instance.browser})` : instance.browser)
922923
// browser config is filtered out
923924
if (!vitest.matchesProjectFilter(name)) {
924925
continue

packages/vitest/src/node/config/serializeConfig.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export function serializeConfig(
4242
retry: config.retry,
4343
disableConsoleIntercept: config.disableConsoleIntercept,
4444
root: config.root,
45-
name: config.name,
45+
name: config.name.name,
4646
globals: config.globals,
4747
snapshotEnvironment: config.snapshotEnvironment,
4848
passWithNoTests: config.passWithNoTests,

packages/vitest/src/node/logger.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ export class Logger {
164164
const config = project.config
165165
const printConfig = !project.isRootProject() && project.name
166166
if (printConfig) {
167-
this.console.error(`\n${formatProjectName(project.name)}\n`)
167+
this.console.error(`\n${formatProjectName(project)}\n`)
168168
}
169169
if (config.include) {
170170
this.console.error(
@@ -243,7 +243,7 @@ export class Logger {
243243

244244
const output = project.isRootProject()
245245
? ''
246-
: formatProjectName(project.name)
246+
: formatProjectName(project)
247247
const provider = project.browser.provider.name
248248
const providerString = provider === 'preview' ? '' : ` by ${c.reset(c.bold(provider))}`
249249
this.log(

packages/vitest/src/node/plugins/utils.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ export function resolveOptimizerConfig(
5959
(n: string) => !exclude.includes(n),
6060
)
6161

62-
newConfig.cacheDir = (testConfig.cache !== false && testConfig.cache?.dir) || VitestCache.resolveCacheDir(root, viteCacheDir, testConfig.name)
62+
const projectName = typeof testConfig.name === 'string' ? testConfig.name : testConfig.name?.name
63+
64+
newConfig.cacheDir = (testConfig.cache !== false && testConfig.cache?.dir) || VitestCache.resolveCacheDir(root, viteCacheDir, projectName)
6365
newConfig.optimizeDeps = {
6466
...viteOptions,
6567
...testOptions,

packages/vitest/src/node/plugins/workspace.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,11 @@ export function WorkspaceVitestPlugin(
4343
const testConfig = viteConfig.test || {}
4444

4545
const root = testConfig.root || viteConfig.root || options.root
46-
let name = testConfig.name
46+
47+
let { name, color } = (!testConfig.name || typeof testConfig.name === 'string')
48+
? { name: testConfig.name, color: null }
49+
: testConfig.name
50+
4751
if (!name) {
4852
if (typeof options.workspacePath === 'string') {
4953
// if there is a package.json, read the name from it
@@ -136,7 +140,7 @@ export function WorkspaceVitestPlugin(
136140
},
137141
},
138142
test: {
139-
name,
143+
name: { name, color },
140144
},
141145
};
142146

packages/vitest/src/node/project.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type { WorkspaceSpec as DeprecatedWorkspaceSpec } from './pool'
1414
import type { Reporter } from './reporters'
1515
import type { ParentProjectBrowser, ProjectBrowser } from './types/browser'
1616
import type {
17+
ProjectName,
1718
ResolvedConfig,
1819
SerializedConfig,
1920
TestProjectInlineConfiguration,
@@ -191,8 +192,15 @@ export class TestProject {
191192
/**
192193
* The name of the project or an empty string if not set.
193194
*/
194-
public get name(): string {
195-
return this.config.name || ''
195+
public get name(): ProjectName['name'] {
196+
return this.config.name.name || ''
197+
}
198+
199+
/**
200+
* The color used when reporting tasks of this project.
201+
*/
202+
public get color(): ProjectName['color'] {
203+
return this.config.name.color
196204
}
197205

198206
/**
@@ -585,7 +593,7 @@ export class TestProject {
585593

586594
/** @deprecated use `name` instead */
587595
public getName(): string {
588-
return this.config.name || ''
596+
return this.config.name.name || ''
589597
}
590598

591599
/** @deprecated internal */
@@ -684,7 +692,7 @@ export class TestProject {
684692
/** @internal */
685693
static _createBasicProject(vitest: Vitest): TestProject {
686694
const project = new TestProject(
687-
vitest.config.name || vitest.config.root,
695+
vitest.config.name.name || vitest.config.root,
688696
vitest,
689697
)
690698
project.vitenode = vitest.vitenode

packages/vitest/src/node/reporters/base.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ export abstract class BaseReporter implements Reporter {
235235
}
236236

237237
if (testModule.project.name) {
238-
title += ` ${formatProjectName(testModule.project.name, '')}`
238+
title += ` ${formatProjectName(testModule.project)}`
239239
}
240240

241241
return ` ${title} ${testModule.task.name} ${suffix}`
@@ -552,7 +552,9 @@ export abstract class BaseReporter implements Reporter {
552552
}
553553

554554
const groupName = getFullName(group, c.dim(' > '))
555-
this.log(` ${formatProjectName(bench.file.projectName)}${bench.name}${c.dim(` - ${groupName}`)}`)
555+
const project = this.ctx.projects.find(p => p.name === bench.file.projectName)
556+
557+
this.log(` ${formatProjectName(project)}${bench.name}${c.dim(` - ${groupName}`)}`)
556558

557559
const siblings = group.tasks
558560
.filter(i => i.meta.benchmark && i.result?.benchmark && i !== bench)
@@ -601,6 +603,7 @@ export abstract class BaseReporter implements Reporter {
601603
for (const task of tasks) {
602604
const filepath = (task as File)?.filepath || ''
603605
const projectName = (task as File)?.projectName || task.file?.projectName || ''
606+
const project = this.ctx.projects.find(p => p.name === projectName)
604607

605608
let name = getFullName(task, c.dim(' > '))
606609

@@ -609,7 +612,7 @@ export abstract class BaseReporter implements Reporter {
609612
}
610613

611614
this.ctx.logger.error(
612-
`${c.bgRed(c.bold(' FAIL '))} ${formatProjectName(projectName)}${name}`,
615+
`${c.bgRed(c.bold(' FAIL '))} ${formatProjectName(project)}${name}`,
613616
)
614617
}
615618

packages/vitest/src/node/reporters/benchmark/reporter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export class BenchmarkReporter extends DefaultReporter {
6565
const duration = testTask.task.result?.duration || 0
6666

6767
if (benches.length > 0 && benches.every(t => t.result?.state !== 'run' && t.result?.state !== 'queued')) {
68-
let title = `\n ${getStateSymbol(testTask.task)} ${formatProjectName(testTask.project.name)}${getFullName(testTask.task, c.dim(' > '))}`
68+
let title = `\n ${getStateSymbol(testTask.task)} ${formatProjectName(testTask.project)}${getFullName(testTask.task, c.dim(' > '))}`
6969

7070
if (duration != null && duration > this.ctx.config.slowTestThreshold) {
7171
title += c.yellow(` ${Math.round(duration)}${c.dim('ms')}`)

packages/vitest/src/node/reporters/renderers/utils.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { Task } from '@vitest/runner'
22
import type { SnapshotSummary } from '@vitest/snapshot'
33
import type { Formatter } from 'tinyrainbow'
4+
import type { ProjectName } from '../../types/config'
45
import { stripVTControlCharacters } from 'node:util'
56
import { slash } from '@vitest/utils'
67
import { basename, dirname, isAbsolute, relative } from 'pathe'
@@ -223,20 +224,27 @@ export function formatTime(time: number): string {
223224
return `${Math.round(time)}ms`
224225
}
225226

226-
export function formatProjectName(name: string | undefined, suffix = ' '): string {
227-
if (!name) {
227+
export function formatProjectName(project?: Partial<ProjectName>, suffix = ' '): string {
228+
if (!project?.name) {
228229
return ''
229230
}
230231
if (!c.isColorSupported) {
231232
return `|${name}|${suffix}`
232233
}
233-
const index = name
234-
.split('')
235-
.reduce((acc, v, idx) => acc + v.charCodeAt(0) + idx, 0)
236234

237-
const colors = [c.bgYellow, c.bgCyan, c.bgGreen, c.bgMagenta]
235+
let background = project.color && c[`bg${project.color}`]
238236

239-
return c.black(colors[index % colors.length](` ${name} `)) + suffix
237+
if (!background) {
238+
const index = project.name
239+
.split('')
240+
.reduce((acc, v, idx) => acc + v.charCodeAt(0) + idx, 0)
241+
242+
const colors = [c.bgYellow, c.bgCyan, c.bgGreen, c.bgMagenta]
243+
244+
background = colors[index % colors.length]
245+
}
246+
247+
return c.black(background(` ${project.name} `)) + suffix
240248
}
241249

242250
export function withLabel(color: 'red' | 'green' | 'blue' | 'cyan' | 'yellow', label: string, message?: string) {

packages/vitest/src/node/reporters/summary.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ interface SlowTask {
3434
interface RunningModule extends Pick<Counter, 'total' | 'completed'> {
3535
filename: TestModule['task']['name']
3636
projectName: TestModule['project']['name']
37+
projectColor: TestModule['project']['color']
3738
hook?: Omit<SlowTask, 'hook'>
3839
tests: Map<TestCase['id'], SlowTask>
3940
typecheck: boolean
@@ -278,7 +279,7 @@ export class SummaryReporter implements Reporter {
278279
const typecheck = testFile.typecheck ? `${c.bgBlue(c.bold(' TS '))} ` : ''
279280
summary.push(
280281
c.bold(c.yellow(` ${F_POINTER} `))
281-
+ formatProjectName(testFile.projectName)
282+
+ formatProjectName({ name: testFile.projectName, color: testFile.projectColor })
282283
+ typecheck
283284
+ testFile.filename
284285
+ c.dim(!testFile.completed && !testFile.total
@@ -382,6 +383,7 @@ function initializeStats(module: TestModule): RunningModule {
382383
completed: 0,
383384
filename: module.task.name,
384385
projectName: module.project.name,
386+
projectColor: module.project.color,
385387
tests: new Map(),
386388
typecheck: !!module.task.meta.typecheck,
387389
}

packages/vitest/src/node/reporters/verbose.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export class VerboseReporter extends DefaultReporter {
3838
let title = ` ${getStateSymbol(test.task)} `
3939

4040
if (test.project.name) {
41-
title += formatProjectName(test.project.name)
41+
title += formatProjectName(test.project)
4242
}
4343

4444
title += getFullName(test.task, c.dim(' > '))

packages/vitest/src/node/spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export class TestSpecification {
5050
this[0] = project
5151
this[1] = moduleId
5252
this[2] = { pool }
53-
const name = project.config.name
53+
const name = project.config.name?.name
5454
const hashName = pool !== 'typescript'
5555
? name
5656
: name
@@ -81,7 +81,7 @@ export class TestSpecification {
8181
toJSON(): SerializedTestSpecification {
8282
return [
8383
{
84-
name: this.project.config.name,
84+
name: this.project.config.name.name,
8585
root: this.project.config.root,
8686
},
8787
this.moduleId,

packages/vitest/src/node/state.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ export class StateManager {
139139
const fileTask = createFileTask(
140140
path,
141141
project.config.root,
142-
project.config.name,
142+
project.config.name.name,
143143
)
144144
fileTask.local = true
145145
TestModule.register(fileTask, project)
@@ -149,7 +149,7 @@ export class StateManager {
149149
return
150150
}
151151
const filtered = files.filter(
152-
file => file.projectName !== project.config.name,
152+
file => file.projectName !== project.config.name.name,
153153
)
154154
// always keep a File task, so we can associate logs with it
155155
if (!filtered.length) {
@@ -222,7 +222,7 @@ export class StateManager {
222222
this.collectFiles(
223223
project,
224224
files.map(filepath =>
225-
createFileTask(filepath, project.config.root, project.config.name),
225+
createFileTask(filepath, project.config.root, project.config.name.name),
226226
),
227227
)
228228
}

packages/vitest/src/node/types/browser.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ type UnsupportedProperties =
7171
| 'environmentOptions'
7272
| 'server'
7373
| 'benchmark'
74+
| 'name'
7475

7576
export interface BrowserInstanceOption extends BrowserProviderOptions,
7677
Omit<ProjectConfig, UnsupportedProperties>,
@@ -87,6 +88,8 @@ export interface BrowserInstanceOption extends BrowserProviderOptions,
8788
* Name of the browser
8889
*/
8990
browser: string
91+
92+
name?: string
9093
}
9194

9295
export interface BrowserConfigOptions {

0 commit comments

Comments
 (0)