|
1 | 1 | import { existsSync, promises as fs } from 'fs'
|
2 | 2 | import type { ViteDevServer } from 'vite'
|
| 3 | +import { normalizePath } from 'vite' |
3 | 4 | import { relative, toNamespacedPath } from 'pathe'
|
4 | 5 | import fg from 'fast-glob'
|
5 | 6 | import mm from 'micromatch'
|
6 | 7 | import c from 'picocolors'
|
7 | 8 | import { ViteNodeRunner } from 'vite-node/client'
|
8 | 9 | import { ViteNodeServer } from 'vite-node/server'
|
9 |
| -import type { ArgumentsType, CoverageProvider, Reporter, ResolvedConfig, UserConfig } from '../types' |
| 10 | +import type { ArgumentsType, CoverageProvider, OnServerRestartHandler, Reporter, ResolvedConfig, UserConfig } from '../types' |
10 | 11 | import { SnapshotManager } from '../integrations/snapshot/manager'
|
11 | 12 | import { clearTimeout, deepMerge, hasFailed, noop, setTimeout, slash } from '../utils'
|
12 | 13 | import { getCoverageProvider } from '../integrations/coverage'
|
@@ -48,7 +49,7 @@ export class Vitest {
|
48 | 49 | this.logger = new Logger(this)
|
49 | 50 | }
|
50 | 51 |
|
51 |
| - private _onRestartListeners: Array<() => void> = [] |
| 52 | + private _onRestartListeners: OnServerRestartHandler[] = [] |
52 | 53 |
|
53 | 54 | async setServer(options: UserConfig, server: ViteDevServer) {
|
54 | 55 | this.unregisterWatcher?.()
|
@@ -81,12 +82,29 @@ export class Vitest {
|
81 | 82 | },
|
82 | 83 | })
|
83 | 84 |
|
| 85 | + if (this.config.watch) { |
| 86 | + // hijack server restart |
| 87 | + const serverRestart = server.restart |
| 88 | + server.restart = async (...args) => { |
| 89 | + await Promise.all(this._onRestartListeners.map(fn => fn())) |
| 90 | + return await serverRestart(...args) |
| 91 | + } |
| 92 | + |
| 93 | + // since we set `server.hmr: false`, Vite does not auto restart itself |
| 94 | + server.watcher.on('change', async (file) => { |
| 95 | + file = normalizePath(file) |
| 96 | + const isConfig = file === server.config.configFile |
| 97 | + if (isConfig) { |
| 98 | + await Promise.all(this._onRestartListeners.map(fn => fn('config'))) |
| 99 | + await serverRestart() |
| 100 | + } |
| 101 | + }) |
| 102 | + } |
| 103 | + |
84 | 104 | this.reporters = await createReporters(resolved.reporters, this.runner)
|
85 | 105 |
|
86 | 106 | this.runningPromise = undefined
|
87 | 107 |
|
88 |
| - this._onRestartListeners.forEach(fn => fn()) |
89 |
| - |
90 | 108 | await this.coverageProvider?.clean(this.config.coverage.clean)
|
91 | 109 |
|
92 | 110 | this.cache.results.setConfig(resolved.root, resolved.cache)
|
@@ -331,13 +349,6 @@ export class Vitest {
|
331 | 349 |
|
332 | 350 | this.isFirstRun = false
|
333 | 351 |
|
334 |
| - // add previously failed files |
335 |
| - // if (RERUN_FAILED) { |
336 |
| - // ctx.state.getFiles().forEach((file) => { |
337 |
| - // if (file.result?.state === 'fail') |
338 |
| - // changedTests.add(file.filepath) |
339 |
| - // }) |
340 |
| - // } |
341 | 352 | this.snapshot.clear()
|
342 | 353 | const files = Array.from(this.changedTests)
|
343 | 354 | this.changedTests.clear()
|
@@ -523,7 +534,7 @@ export class Vitest {
|
523 | 534 | return code.includes('import.meta.vitest')
|
524 | 535 | }
|
525 | 536 |
|
526 |
| - onServerRestarted(fn: () => void) { |
| 537 | + onServerRestart(fn: OnServerRestartHandler) { |
527 | 538 | this._onRestartListeners.push(fn)
|
528 | 539 | }
|
529 | 540 | }
|
0 commit comments