Skip to content

Commit 61ba581

Browse files
authored
chore: align test setup with core (#441)
1 parent 6085bbe commit 61ba581

File tree

3 files changed

+97
-78
lines changed

3 files changed

+97
-78
lines changed

playground/ssr-react/vite.config.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import fs from 'node:fs'
22
import path from 'node:path'
3+
import url from 'node:url'
34
import { defineConfig } from 'vite'
45
import react from '@vitejs/plugin-react'
56

7+
const _dirname = path.dirname(url.fileURLToPath(import.meta.url))
8+
69
process.env.MY_CUSTOM_SECRET = 'API_KEY_qwertyuiop'
710

811
export default defineConfig({
@@ -20,7 +23,7 @@ export default defineConfig({
2023
build: {
2124
outDir: 'dist/server',
2225
rollupOptions: {
23-
input: 'src/entry-server.jsx',
26+
input: path.resolve(_dirname, 'src/entry-server.jsx'),
2427
},
2528
},
2629
},
@@ -40,7 +43,7 @@ export default defineConfig({
4043
const appHtml = render(url)
4144
const template = await server.transformIndexHtml(
4245
url,
43-
fs.readFileSync(path.resolve('index.html'), 'utf-8'),
46+
fs.readFileSync(path.resolve(_dirname, 'index.html'), 'utf-8'),
4447
)
4548
const html = template.replace(`<!--app-html-->`, appHtml)
4649
res.setHeader('content-type', 'text/html').end(html)
@@ -52,11 +55,13 @@ export default defineConfig({
5255
},
5356
async configurePreviewServer(server) {
5457
const template = fs.readFileSync(
55-
path.resolve('dist/client/index.html'),
58+
path.resolve(_dirname, 'dist/client/index.html'),
5659
'utf-8',
5760
)
5861
const { render } = await import(
59-
new URL('./dist/server/entry-server.js', import.meta.url).href
62+
url.pathToFileURL(
63+
path.resolve(_dirname, './dist/server/entry-server.js'),
64+
)
6065
)
6166
return () => {
6267
server.middlewares.use(async (req, res, next) => {

playground/vitestGlobalSetup.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
import os from 'node:os'
21
import path from 'node:path'
32
import fs from 'fs-extra'
3+
import type { TestProject } from 'vitest/node'
44
import type { BrowserServer } from 'playwright-chromium'
55
import { chromium } from 'playwright-chromium'
66

7-
const DIR = path.join(os.tmpdir(), 'vitest_playwright_global_setup')
8-
97
let browserServer: BrowserServer | undefined
108

11-
export async function setup(): Promise<void> {
9+
export async function setup({ provide }: TestProject): Promise<void> {
1210
process.env.NODE_ENV = process.env.VITE_TEST_BUILD
1311
? 'production'
1412
: 'development'
@@ -20,8 +18,7 @@ export async function setup(): Promise<void> {
2018
: undefined,
2119
})
2220

23-
await fs.mkdirp(DIR)
24-
await fs.writeFile(path.join(DIR, 'wsEndpoint'), browserServer.wsEndpoint())
21+
provide('wsEndpoint', browserServer.wsEndpoint())
2522

2623
const tempDir = path.resolve(__dirname, '../playground-temp')
2724
await fs.ensureDir(tempDir)

playground/vitestSetup.ts

Lines changed: 85 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import type * as http from 'node:http'
2-
import { dirname, join, resolve } from 'node:path'
3-
import os from 'node:os'
2+
import path, { dirname, resolve } from 'node:path'
43
import fs from 'fs-extra'
54
import { chromium } from 'playwright-chromium'
65
import type {
6+
ConfigEnv,
77
InlineConfig,
88
Logger,
99
PluginOption,
@@ -21,8 +21,8 @@ import {
2121
preview,
2222
} from 'vite'
2323
import type { Browser, Page } from 'playwright-chromium'
24-
import type { File } from 'vitest'
25-
import { beforeAll } from 'vitest'
24+
import type { RunnerTestFile } from 'vitest'
25+
import { beforeAll, inject } from 'vitest'
2626

2727
// #region env
2828

@@ -75,32 +75,28 @@ export let browser: Browser = undefined!
7575
export let viteTestUrl: string = ''
7676
export let watcher: Rollup.RollupWatcher | undefined = undefined
7777

78-
declare module 'vite' {
79-
interface InlineConfig {
80-
testConfig?: {
81-
// relative base output use relative path
82-
// rewrite the url to truth file path
83-
baseRoute: string
84-
}
85-
}
86-
}
87-
8878
export function setViteUrl(url: string): void {
8979
viteTestUrl = url
9080
}
9181

9282
// #endregion
9383

94-
const DIR = join(os.tmpdir(), 'vitest_playwright_global_setup')
95-
9684
beforeAll(async (s) => {
97-
const suite = s as File
85+
const suite = s as RunnerTestFile
86+
87+
testPath = suite.filepath!
88+
testName = slash(testPath).match(/playground\/([\w-]+)\//)?.[1]
89+
testDir = dirname(testPath)
90+
if (testName) {
91+
testDir = path.resolve(workspaceRoot, 'playground-temp', testName)
92+
}
93+
9894
// skip browser setup for non-playground tests
9995
if (!suite.filepath.includes('playground')) {
10096
return
10197
}
10298

103-
const wsEndpoint = fs.readFileSync(join(DIR, 'wsEndpoint'), 'utf-8')
99+
const wsEndpoint = inject('wsEndpoint')
104100
if (!wsEndpoint) {
105101
throw new Error('wsEndpoint not found')
106102
}
@@ -133,19 +129,22 @@ beforeAll(async (s) => {
133129
browserErrors.push(error)
134130
})
135131

136-
testPath = suite.filepath!
137-
testName = slash(testPath).match(/playground\/([\w-]+)\//)?.[1]
138-
testDir = dirname(testPath)
139-
140132
// if this is a test placed under playground/xxx/__tests__
141133
// start a vite server in that directory.
142134
if (testName) {
143-
testDir = resolve(workspaceRoot, 'playground-temp', testName)
144-
145135
// when `root` dir is present, use it as vite's root
146136
const testCustomRoot = resolve(testDir, 'root')
147137
rootDir = fs.existsSync(testCustomRoot) ? testCustomRoot : testDir
148138

139+
// separate rootDir for variant
140+
const variantName = path.basename(path.dirname(testPath))
141+
if (variantName !== '__tests__') {
142+
const variantTestDir = testDir + '__' + variantName
143+
if (fs.existsSync(variantTestDir)) {
144+
rootDir = testDir = variantTestDir
145+
}
146+
}
147+
149148
const testCustomServe = [
150149
resolve(dirname(testPath), 'serve.ts'),
151150
resolve(dirname(testPath), 'serve.js'),
@@ -162,7 +161,6 @@ beforeAll(async (s) => {
162161
if (serve) {
163162
server = await serve()
164163
viteServer = mod.viteServer
165-
return
166164
}
167165
} else {
168166
await startDefaultServe()
@@ -189,27 +187,26 @@ beforeAll(async (s) => {
189187
}
190188
})
191189

192-
function loadConfigFromDir(dir: string) {
193-
return loadConfigFromFile(
194-
{
195-
command: isBuild ? 'build' : 'serve',
196-
mode: isBuild ? 'production' : 'development',
197-
},
198-
undefined,
199-
dir,
200-
)
201-
}
202-
203-
export async function startDefaultServe(): Promise<void> {
190+
async function loadConfig(configEnv: ConfigEnv) {
204191
let config: UserConfig | null = null
205-
// config file near the *.spec.ts
206-
const res = await loadConfigFromDir(dirname(testPath))
207-
if (res) {
208-
config = res.config
192+
193+
// config file named by convention as the *.spec.ts folder
194+
const variantName = path.basename(path.dirname(testPath))
195+
if (variantName !== '__tests__') {
196+
const configVariantPath = path.resolve(
197+
rootDir,
198+
`vite.config-${variantName}.js`,
199+
)
200+
if (fs.existsSync(configVariantPath)) {
201+
const res = await loadConfigFromFile(configEnv, configVariantPath)
202+
if (res) {
203+
config = res.config
204+
}
205+
}
209206
}
210207
// config file from test root dir
211208
if (!config) {
212-
const res = await loadConfigFromDir(rootDir)
209+
const res = await loadConfigFromFile(configEnv, undefined, rootDir)
213210
if (res) {
214211
config = res.config
215212
}
@@ -226,7 +223,6 @@ export async function startDefaultServe(): Promise<void> {
226223
usePolling: true,
227224
interval: 100,
228225
},
229-
host: true,
230226
fs: {
231227
strict: !isBuild,
232228
},
@@ -240,21 +236,20 @@ export async function startDefaultServe(): Promise<void> {
240236
},
241237
customLogger: createInMemoryLogger(serverLogs),
242238
}
239+
return mergeConfig(options, config || {})
240+
}
243241

242+
export async function startDefaultServe(): Promise<void> {
244243
setupConsoleWarnCollector(serverLogs)
245244

246245
if (!isBuild) {
247246
process.env.VITE_INLINE = 'inline-serve'
248-
const testConfig = mergeConfig(options, config || {})
249-
viteConfig = testConfig
250-
process.chdir(rootDir)
251-
viteServer = server = await (await createServer(testConfig)).listen()
252-
// use resolved port/base from server
253-
const devBase = server.config.base
254-
viteTestUrl = `http://localhost:${server.config.server.port}${
255-
devBase === '/' ? '' : devBase
256-
}`
257-
setViteUrl(viteTestUrl)
247+
const config = await loadConfig({ command: 'serve', mode: 'development' })
248+
viteServer = server = await (await createServer(config)).listen()
249+
viteTestUrl = stripTrailingSlashIfNeeded(
250+
server.resolvedUrls.local[0],
251+
server.config.base,
252+
)
258253
await page.goto(viteTestUrl)
259254
} else {
260255
process.env.VITE_INLINE = 'inline-build'
@@ -265,32 +260,41 @@ export async function startDefaultServe(): Promise<void> {
265260
resolvedConfig = config
266261
},
267262
})
268-
options.plugins = [resolvedPlugin()]
269-
const testConfig = mergeConfig(options, config || {})
270-
viteConfig = testConfig
271-
process.chdir(rootDir)
272-
if (testConfig.builder) {
273-
const builder = await createBuilder(testConfig)
263+
const buildConfig = mergeConfig(
264+
await loadConfig({ command: 'build', mode: 'production' }),
265+
{
266+
plugins: [resolvedPlugin()],
267+
},
268+
)
269+
if (buildConfig.builder) {
270+
const builder = await createBuilder(buildConfig)
274271
await builder.buildApp()
275272
} else {
276-
const rollupOutput = await build(testConfig)
273+
const rollupOutput = await build(buildConfig)
277274
const isWatch = !!resolvedConfig!.build.watch
278275
// in build watch,call startStaticServer after the build is complete
279276
if (isWatch) {
280277
watcher = rollupOutput as Rollup.RollupWatcher
281278
await notifyRebuildComplete(watcher)
282279
}
280+
if (buildConfig.__test__) {
281+
buildConfig.__test__()
282+
}
283283
}
284-
if (config && config.__test__) {
285-
config.__test__()
286-
}
284+
285+
const previewConfig = await loadConfig({
286+
command: 'serve',
287+
mode: 'development',
288+
isPreview: true,
289+
})
287290
const _nodeEnv = process.env.NODE_ENV
288-
const previewServer = await preview(testConfig)
291+
const previewServer = await preview(previewConfig)
289292
// prevent preview change NODE_ENV
290293
process.env.NODE_ENV = _nodeEnv
291-
viteTestUrl = previewServer.resolvedUrls.local[0]
292-
viteTestUrl = viteTestUrl.replace(/\/+$/, '')
293-
setViteUrl(viteTestUrl)
294+
viteTestUrl = stripTrailingSlashIfNeeded(
295+
previewServer.resolvedUrls.local[0],
296+
previewServer.config.base,
297+
)
294298
await page.goto(viteTestUrl)
295299
}
296300
}
@@ -349,7 +353,7 @@ function createInMemoryLogger(logs: string[]): Logger {
349353
function setupConsoleWarnCollector(logs: string[]) {
350354
const warn = console.warn
351355
console.warn = (...args) => {
352-
serverLogs.push(args.join(' '))
356+
logs.push(args.join(' '))
353357
return warn.call(console, ...args)
354358
}
355359
}
@@ -358,6 +362,13 @@ export function slash(p: string): string {
358362
return p.replace(/\\/g, '/')
359363
}
360364

365+
function stripTrailingSlashIfNeeded(url: string, base: string): string {
366+
if (base === '/') {
367+
return url.replace(/\/$/, '')
368+
}
369+
return url
370+
}
371+
361372
declare module 'vite' {
362373
export interface UserConfig {
363374
/**
@@ -368,3 +379,9 @@ declare module 'vite' {
368379
__test__?: () => void
369380
}
370381
}
382+
383+
declare module 'vitest' {
384+
export interface ProvidedContext {
385+
wsEndpoint: string
386+
}
387+
}

0 commit comments

Comments
 (0)