Skip to content

Commit 9830fbe

Browse files
committed
feat(api)!: report test file also as a suite
1 parent 716b029 commit 9830fbe

File tree

3 files changed

+229
-144
lines changed

3 files changed

+229
-144
lines changed

packages/vitest/src/node/reporters/reported-tasks.ts

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ import type {
88
import type { SerializedError, TestError } from '@vitest/utils'
99
import type { TestProject } from '../project'
1010

11+
interface ReportedTaskOptions {
12+
/**
13+
* @default true
14+
*/
15+
register?: boolean
16+
}
17+
1118
class ReportedTaskImplementation {
1219
/**
1320
* Task instance.
@@ -33,10 +40,14 @@ class ReportedTaskImplementation {
3340
public readonly location: { line: number; column: number } | undefined
3441

3542
/** @internal */
36-
protected constructor(
43+
constructor(
3744
task: RunnerTask,
3845
project: TestProject,
46+
options: ReportedTaskOptions = {},
3947
) {
48+
if (options.register !== false) {
49+
storeTask(project, task, this as unknown as TestModule | TestCase | TestSuite)
50+
}
4051
this.task = task
4152
this.project = project
4253
this.id = task.id
@@ -57,9 +68,7 @@ class ReportedTaskImplementation {
5768
* @internal
5869
*/
5970
static register(task: RunnerTask, project: TestProject) {
60-
const state = new this(task, project) as TestCase | TestSuite | TestModule
61-
storeTask(project, task, state)
62-
return state
71+
return new this(task, project) as TestCase | TestSuite | TestModule
6372
}
6473
}
6574

@@ -86,9 +95,9 @@ export class TestCase extends ReportedTaskImplementation {
8695
public readonly options: TaskOptions
8796

8897
/**
89-
* Parent suite. If the test was called directly inside the module, the parent will be the module itself.
98+
* Parent suite.
9099
*/
91-
public readonly parent: TestSuite | TestModule
100+
public readonly parent: TestSuite
92101

93102
/** @internal */
94103
protected constructor(task: RunnerTestCase, project: TestProject) {
@@ -101,7 +110,7 @@ export class TestCase extends ReportedTaskImplementation {
101110
this.parent = getReportedTask(project, suite) as TestSuite
102111
}
103112
else {
104-
this.parent = this.module
113+
this.parent = this.module.suite
105114
}
106115
this.options = buildOptions(task)
107116
}
@@ -111,7 +120,7 @@ export class TestCase extends ReportedTaskImplementation {
111120
*/
112121
public get fullName(): string {
113122
if (this.#fullName === undefined) {
114-
if (this.parent.type !== 'module') {
123+
if (this.parent.task !== this.module.task) {
115124
this.#fullName = `${this.parent.fullName} > ${this.name}`
116125
}
117126
else {
@@ -325,8 +334,12 @@ abstract class SuiteImplementation extends ReportedTaskImplementation {
325334
public readonly children: TestCollection
326335

327336
/** @internal */
328-
protected constructor(task: RunnerTestSuite | RunnerTestFile, project: TestProject) {
329-
super(task, project)
337+
protected constructor(
338+
task: RunnerTestSuite | RunnerTestFile,
339+
project: TestProject,
340+
options?: ReportedTaskOptions,
341+
) {
342+
super(task, project, options)
330343
this.children = new TestCollection(task, project)
331344
}
332345

@@ -356,31 +369,42 @@ export class TestSuite extends SuiteImplementation {
356369
public readonly module: TestModule
357370

358371
/**
359-
* Parent suite. If suite was called directly inside the module, the parent will be the module itself.
372+
* Parent suite. If suite was called directly inside the module, the parent will be undefined.
360373
*/
361-
public readonly parent: TestSuite | TestModule
374+
public readonly parent: TestSuite | undefined
362375

363376
/**
364377
* Options that suite was initiated with.
365378
*/
366379
public readonly options: TaskOptions
367380

368381
/** @internal */
369-
protected constructor(task: RunnerTestSuite, project: TestProject) {
370-
super(task, project)
382+
constructor(
383+
task: RunnerTestSuite,
384+
project: TestProject,
385+
testModule?: TestModule,
386+
options?: ReportedTaskOptions,
387+
) {
388+
super(task, project, options)
371389

372390
this.name = task.name
373-
this.module = getReportedTask(project, task.file) as TestModule
391+
this.module = testModule || getReportedTask(project, task.file) as TestModule
374392
const suite = this.task.suite
375393
if (suite) {
376394
this.parent = getReportedTask(project, suite) as TestSuite
377395
}
378-
else {
379-
this.parent = this.module
396+
else if (this.module.suite && this !== this.module.suite) {
397+
this.parent = this.module.suite
380398
}
381399
this.options = buildOptions(task)
382400
}
383401

402+
static fromTestModule(testModule: TestModule): TestSuite {
403+
return new this(testModule.task, testModule.project, testModule, {
404+
register: false,
405+
})
406+
}
407+
384408
/**
385409
* Checks if the suite has any failed tests.
386410
* This will also return `false` if suite failed during collection.
@@ -399,7 +423,7 @@ export class TestSuite extends SuiteImplementation {
399423
*/
400424
public get fullName(): string {
401425
if (this.#fullName === undefined) {
402-
if (this.parent.type !== 'module') {
426+
if (this.parent) {
403427
this.#fullName = `${this.parent.fullName} > ${this.name}`
404428
}
405429
else {
@@ -415,6 +439,7 @@ export class TestModule extends SuiteImplementation {
415439
declare public readonly task: RunnerTestFile
416440
declare public readonly location: undefined
417441
public readonly type = 'module'
442+
public readonly suite: TestSuite
418443

419444
/**
420445
* This is usually an absolute UNIX file path.
@@ -427,6 +452,7 @@ export class TestModule extends SuiteImplementation {
427452
protected constructor(task: RunnerTestFile, project: TestProject) {
428453
super(task, project)
429454
this.moduleId = task.filepath
455+
this.suite = TestSuite.fromTestModule(this)
430456
}
431457

432458
/**

packages/vitest/src/node/test-run.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ export class TestRun {
9595
}
9696

9797
if (event === 'suite-prepare' && entity.type === 'module') {
98-
return await this.vitest.report('onTestModuleStart', entity)
98+
await this.vitest.report('onTestModuleStart', entity)
99+
return await this.vitest.report('onTestSuiteReady', entity.suite)
99100
}
100101

101102
if (event === 'suite-finished') {
@@ -120,6 +121,7 @@ export class TestRun {
120121
}
121122

122123
if (entity.type === 'module') {
124+
await this.vitest.report('onTestSuiteResult', entity.suite)
123125
await this.vitest.report('onTestModuleEnd', entity)
124126
}
125127
else {

0 commit comments

Comments
 (0)