Skip to content

Commit 003c0be

Browse files
sheremet-vaAriPerkkio
andauthoredJan 15, 2025··
fix(watch): don't indicate exit when no matching files (#7246)
Co-authored-by: Ari Perkkiö <ari.perkkio@gmail.com>
1 parent 48645bf commit 003c0be

17 files changed

+150
-64
lines changed
 

‎packages/vitest/src/node/core.ts

+5-9
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { VitestPackageInstaller } from './packageInstaller'
3434
import { createPool } from './pool'
3535
import { TestProject } from './project'
3636
import { BlobReporter, readBlobs } from './reporters/blob'
37+
import { HangingProcessReporter } from './reporters/hanging-process'
3738
import { createBenchmarkReporters, createReporters } from './reporters/utils'
3839
import { VitestSpecifications } from './specifications'
3940
import { StateManager } from './state'
@@ -564,8 +565,6 @@ export class Vitest {
564565
// Report coverage for uncovered files
565566
await this.reportCoverage(coverage, true)
566567

567-
this.logger.printNoTestFound(filters)
568-
569568
if (throwAnError) {
570569
throw new FilesNotFoundError(this.mode)
571570
}
@@ -671,11 +670,6 @@ export class Vitest {
671670
}
672671

673672
private async runFiles(specs: TestSpecification[], allTestsRun: boolean): Promise<TestRunResult> {
674-
const filepaths = specs.map(spec => spec.moduleId)
675-
this.state.collectPaths(filepaths)
676-
677-
await this.report('onPathsCollected', filepaths)
678-
await this.report('onSpecsCollected', specs.map(spec => spec.toJSON()))
679673
await this._testRun.start(specs)
680674

681675
// previous run
@@ -1140,7 +1134,7 @@ export class Vitest {
11401134
this.state.getProcessTimeoutCauses().forEach(cause => console.warn(cause))
11411135

11421136
if (!this.pool) {
1143-
const runningServers = [this.vite, ...this.resolvedProjects.map(p => p.vite)].filter(Boolean).length
1137+
const runningServers = [this._vite, ...this.resolvedProjects.map(p => p._vite)].filter(Boolean).length
11441138

11451139
if (runningServers === 1) {
11461140
console.warn('Tests closed successfully but something prevents Vite server from exiting')
@@ -1152,7 +1146,9 @@ export class Vitest {
11521146
console.warn('Tests closed successfully but something prevents the main process from exiting')
11531147
}
11541148

1155-
console.warn('You can try to identify the cause by enabling "hanging-process" reporter. See https://vitest.dev/config/#reporters')
1149+
if (!this.reporters.some(r => r instanceof HangingProcessReporter)) {
1150+
console.warn('You can try to identify the cause by enabling "hanging-process" reporter. See https://vitest.dev/config/#reporters')
1151+
}
11561152
}
11571153

11581154
process.exit()

‎packages/vitest/src/node/logger.ts

+25-18
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,29 @@ export class Logger {
128128

129129
printNoTestFound(filters?: string[]) {
130130
const config = this.ctx.config
131+
132+
if (config.watch && (config.changed || config.related?.length)) {
133+
this.log(`No affected ${config.mode} files found\n`)
134+
}
135+
else if (config.watch) {
136+
this.log(
137+
c.red(`No ${config.mode} files found. You can change the file name pattern by pressing "p"\n`),
138+
)
139+
}
140+
else {
141+
if (config.passWithNoTests) {
142+
this.log(`No ${config.mode} files found, exiting with code 0\n`)
143+
}
144+
else {
145+
this.error(
146+
c.red(`No ${config.mode} files found, exiting with code 1\n`),
147+
)
148+
}
149+
}
150+
131151
const comma = c.dim(', ')
132152
if (filters?.length) {
133-
this.console.error(c.dim('filter: ') + c.yellow(filters.join(comma)))
153+
this.console.error(c.dim('filter: ') + c.yellow(filters.join(comma)))
134154
}
135155
const projectsFilter = toArray(config.project)
136156
if (projectsFilter.length) {
@@ -140,9 +160,9 @@ export class Logger {
140160
}
141161
this.ctx.projects.forEach((project) => {
142162
const config = project.config
143-
const output = (project.isRootProject() || !project.name) ? '' : `[${project.name}]`
144-
if (output) {
145-
this.console.error(c.bgCyan(`${output} Config`))
163+
const printConfig = !project.isRootProject() && project.name
164+
if (printConfig) {
165+
this.console.error(`\n${formatProjectName(project.name)}\n`)
146166
}
147167
if (config.include) {
148168
this.console.error(
@@ -165,20 +185,7 @@ export class Logger {
165185
)
166186
}
167187
})
168-
169-
if (config.watch && (config.changed || config.related?.length)) {
170-
this.log(`No affected ${config.mode} files found\n`)
171-
}
172-
else {
173-
if (config.passWithNoTests) {
174-
this.log(`No ${config.mode} files found, exiting with code 0\n`)
175-
}
176-
else {
177-
this.error(
178-
c.red(`\nNo ${config.mode} files found, exiting with code 1`),
179-
)
180-
}
181-
}
188+
this.console.error()
182189
}
183190

184191
printBanner() {

‎packages/vitest/src/node/project.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export class TestProject {
6565
/** @internal */ vitenode!: ViteNodeServer
6666
/** @internal */ typechecker?: Typechecker
6767
/** @internal */ _config?: ResolvedConfig
68+
/** @internal */ _vite?: ViteDevServer
6869

6970
private runner!: ViteNodeRunner
7071

@@ -75,7 +76,6 @@ export class TestProject {
7576

7677
private _globalSetups?: GlobalSetupFile[]
7778
private _provided: ProvidedContext = {} as any
78-
private _vite?: ViteDevServer
7979

8080
constructor(
8181
/** @deprecated */

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

+6-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,12 @@ export abstract class BaseReporter implements Reporter {
5858

5959
onFinished(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
6060
this.end = performance.now()
61-
this.reportSummary(files, errors)
61+
if (!files.length && !errors.length) {
62+
this.ctx.logger.printNoTestFound(this.ctx.filenamePattern)
63+
}
64+
else {
65+
this.reportSummary(files, errors)
66+
}
6267
}
6368

6469
onTaskUpdate(packs: TaskResultPack[]) {

‎packages/vitest/src/node/reporters/default.ts

+7-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import type { File } from '@vitest/runner'
21
import type { Vitest } from '../core'
2+
import type { TestSpecification } from '../spec'
33
import type { BaseOptions } from './base'
44
import type { ReportedHookContext, TestCase, TestModule } from './reported-tasks'
55
import { BaseReporter } from './base'
@@ -29,6 +29,10 @@ export class DefaultReporter extends BaseReporter {
2929
}
3030
}
3131

32+
onTestRunStart(specifications: ReadonlyArray<TestSpecification>) {
33+
this.summary?.onTestRunStart(specifications)
34+
}
35+
3236
onTestModuleQueued(file: TestModule) {
3337
this.summary?.onTestModuleQueued(file)
3438
}
@@ -72,17 +76,9 @@ export class DefaultReporter extends BaseReporter {
7276
this.renderSucceed = paths.length <= 1
7377
}
7478
}
75-
76-
this.summary?.onPathsCollected(paths)
77-
}
78-
79-
onWatcherRerun(files: string[], trigger?: string) {
80-
this.summary?.onWatcherRerun()
81-
super.onWatcherRerun(files, trigger)
8279
}
8380

84-
onFinished(files?: File[], errors?: unknown[]) {
85-
this.summary?.onFinished()
86-
super.onFinished(files, errors)
81+
onTestRunEnd() {
82+
this.summary?.onTestRunEnd()
8783
}
8884
}

‎packages/vitest/src/node/reporters/json.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ export class JsonReporter implements Reporter {
110110
const numTodoTests = tests.filter(t => t.mode === 'todo').length
111111
const testResults: Array<JsonTestResult> = []
112112

113-
const success = numFailedTestSuites === 0 && numFailedTests === 0
113+
const success = !!(files.length > 0 || this.ctx.config.passWithNoTests) && numFailedTestSuites === 0 && numFailedTests === 0
114114

115115
for (const file of files) {
116116
const tests = getTests([file])

‎packages/vitest/src/node/reporters/renderers/windowedRenderer.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export class WindowRenderer {
5959

6060
start() {
6161
this.finished = false
62-
this.renderInterval = setInterval(() => this.flushBuffer(), this.options.interval)
62+
this.renderInterval = setInterval(() => this.flushBuffer(), this.options.interval).unref()
6363
}
6464

6565
stop() {

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

+5-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { Vitest } from '../core'
2+
import type { TestSpecification } from '../spec'
23
import type { Reporter } from '../types/reporter'
34
import type { ReportedHookContext, TestCase, TestModule } from './reported-tasks'
45
import c from 'tinyrainbow'
@@ -75,29 +76,25 @@ export class SummaryReporter implements Reporter {
7576
getWindow: () => this.createSummary(),
7677
})
7778

78-
this.startTimers()
79-
8079
this.ctx.onClose(() => {
8180
clearInterval(this.durationInterval)
8281
this.renderer.stop()
8382
})
8483
}
8584

86-
onPathsCollected(paths?: string[]) {
87-
this.modules.total = (paths || []).length
88-
}
89-
90-
onWatcherRerun() {
85+
onTestRunStart(specifications: ReadonlyArray<TestSpecification>) {
9186
this.runningModules.clear()
9287
this.finishedModules.clear()
9388
this.modules = emptyCounters()
9489
this.tests = emptyCounters()
9590

9691
this.startTimers()
9792
this.renderer.start()
93+
94+
this.modules.total = specifications.length
9895
}
9996

100-
onFinished() {
97+
onTestRunEnd() {
10198
this.runningModules.clear()
10299
this.finishedModules.clear()
103100
this.renderer.finish()

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

+5
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ export class TestRun {
1212
constructor(private vitest: Vitest) {}
1313

1414
async start(specifications: TestSpecification[]) {
15+
const filepaths = specifications.map(spec => spec.moduleId)
16+
this.vitest.state.collectPaths(filepaths)
17+
18+
await this.vitest.report('onPathsCollected', Array.from(new Set(filepaths)))
19+
await this.vitest.report('onSpecsCollected', specifications.map(spec => spec.toJSON()))
1520
await this.vitest.report('onTestRunStart', [...specifications])
1621
}
1722

‎test/config/fixtures/browser-custom-html/vitest.config.correct.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export default defineConfig({
44
test: {
55
include: ['browser-basic.test.ts'],
66
browser: {
7-
name: 'chromium',
7+
instances: [{ browser: 'chromium' }],
88
enabled: true,
99
headless: true,
1010
provider: 'playwright',

‎test/config/fixtures/browser-custom-html/vitest.config.custom-transformIndexHtml.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export default defineConfig({
3030
test: {
3131
include: ['./browser-custom.test.ts'],
3232
browser: {
33-
name: 'chromium',
33+
instances: [{ browser: 'chromium' }],
3434
enabled: true,
3535
headless: true,
3636
provider: 'playwright',

‎test/config/fixtures/browser-custom-html/vitest.config.default-transformIndexHtml.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export default defineConfig({
3030
test: {
3131
include: ['./browser-custom.test.ts'],
3232
browser: {
33-
name: 'chromium',
33+
instances: [{ browser: 'chromium' }],
3434
enabled: true,
3535
headless: true,
3636
provider: 'playwright',

‎test/config/fixtures/browser-custom-html/vitest.config.error-hook.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export default defineConfig({
1212
test: {
1313
include: ['./browser-basic.test.ts'],
1414
browser: {
15-
name: 'chromium',
15+
instances: [{ browser: 'chromium' }],
1616
enabled: true,
1717
headless: true,
1818
provider: 'playwright',

‎test/config/fixtures/browser-custom-html/vitest.config.non-existing.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { defineConfig } from 'vitest/config';
33
export default defineConfig({
44
test: {
55
browser: {
6-
name: 'chromium',
6+
instances: [{ browser: 'chromium' }],
77
enabled: true,
88
headless: true,
99
provider: 'playwright',

‎test/core/vite.config.ts

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ export default defineConfig({
6363
setupFiles: [
6464
'./test/setup.ts',
6565
],
66+
reporters: [['default', { summary: true }], 'hanging-process'],
6667
testNamePattern: '^((?!does not include test that).)*$',
6768
coverage: {
6869
provider: 'istanbul',

‎test/reporters/tests/json.test.ts

+87
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,93 @@ describe('json reporter', async () => {
3838
expect(result).toMatchSnapshot()
3939
}, 40000)
4040

41+
it('generates empty json with success: false', async () => {
42+
const { stdout } = await runVitest({
43+
reporters: 'json',
44+
root,
45+
includeTaskLocation: true,
46+
}, ['json-non-existing-files'])
47+
48+
const json = JSON.parse(stdout)
49+
json.startTime = 0
50+
expect(json).toMatchInlineSnapshot(`
51+
{
52+
"numFailedTestSuites": 0,
53+
"numFailedTests": 0,
54+
"numPassedTestSuites": 0,
55+
"numPassedTests": 0,
56+
"numPendingTestSuites": 0,
57+
"numPendingTests": 0,
58+
"numTodoTests": 0,
59+
"numTotalTestSuites": 0,
60+
"numTotalTests": 0,
61+
"snapshot": {
62+
"added": 0,
63+
"didUpdate": false,
64+
"failure": false,
65+
"filesAdded": 0,
66+
"filesRemoved": 0,
67+
"filesRemovedList": [],
68+
"filesUnmatched": 0,
69+
"filesUpdated": 0,
70+
"matched": 0,
71+
"total": 0,
72+
"unchecked": 0,
73+
"uncheckedKeysByFile": [],
74+
"unmatched": 0,
75+
"updated": 0,
76+
},
77+
"startTime": 0,
78+
"success": false,
79+
"testResults": [],
80+
}
81+
`)
82+
})
83+
84+
it('generates empty json with success: true', async () => {
85+
const { stdout } = await runVitest({
86+
reporters: 'json',
87+
root,
88+
includeTaskLocation: true,
89+
passWithNoTests: true,
90+
}, ['json-non-existing-files'])
91+
92+
const json = JSON.parse(stdout)
93+
json.startTime = 0
94+
expect(json).toMatchInlineSnapshot(`
95+
{
96+
"numFailedTestSuites": 0,
97+
"numFailedTests": 0,
98+
"numPassedTestSuites": 0,
99+
"numPassedTests": 0,
100+
"numPendingTestSuites": 0,
101+
"numPendingTests": 0,
102+
"numTodoTests": 0,
103+
"numTotalTestSuites": 0,
104+
"numTotalTests": 0,
105+
"snapshot": {
106+
"added": 0,
107+
"didUpdate": false,
108+
"failure": false,
109+
"filesAdded": 0,
110+
"filesRemoved": 0,
111+
"filesRemovedList": [],
112+
"filesUnmatched": 0,
113+
"filesUpdated": 0,
114+
"matched": 0,
115+
"total": 0,
116+
"unchecked": 0,
117+
"uncheckedKeysByFile": [],
118+
"unmatched": 0,
119+
"updated": 0,
120+
},
121+
"startTime": 0,
122+
"success": true,
123+
"testResults": [],
124+
}
125+
`)
126+
})
127+
41128
it.each([
42129
['passed', 'all-passing-or-skipped'],
43130
['passed', 'all-skipped'],

‎test/reporters/tests/test-run.test.ts

+1-9
Original file line numberDiff line numberDiff line change
@@ -999,15 +999,7 @@ async function run(
999999

10001000
const { stdout, stderr } = await runInlineTests(structure, config)
10011001

1002-
if (reporterOptions?.printTestRunEvents && reporterOptions?.failed) {
1003-
if (config.passWithNoTests) {
1004-
expect(stdout).toContain('No test files found, exiting with code 0')
1005-
}
1006-
else {
1007-
expect(stderr).toContain('No test files found, exiting with code 1')
1008-
}
1009-
}
1010-
else if (!reporterOptions?.printTestRunEvents) {
1002+
if (!reporterOptions?.printTestRunEvents && !reporterOptions?.failed) {
10111003
expect(stdout).toBe('')
10121004
expect(stderr).toBe('')
10131005
}

0 commit comments

Comments
 (0)
Please sign in to comment.