vite/scripts/jestPerTestSetup.ts

133 lines
3.5 KiB
TypeScript
Raw Normal View History

2020-12-20 03:33:13 +00:00
import fs from 'fs-extra'
import * as http from 'http'
import { resolve } from 'path'
import slash from 'slash'
import sirv from 'sirv'
2020-12-22 03:00:54 +00:00
import { createServer, build, ViteDevServer, UserConfig } from 'vite'
2020-12-20 03:33:13 +00:00
import { Page } from 'playwright-chromium'
const isBuildTest = !!process.env.VITE_TEST_BUILD
// injected by the test env
declare const page: Page
let server: ViteDevServer | http.Server
let tempDir: string
let err: Error
const logs = ((global as any).browserLogs = [])
2020-12-23 23:15:09 +00:00
const onConsole = (msg) => {
logs.push(msg.text())
}
2020-12-23 04:07:57 +00:00
2020-12-20 03:33:13 +00:00
beforeAll(async () => {
try {
2020-12-23 23:15:09 +00:00
page.on('console', onConsole)
2020-12-20 03:33:13 +00:00
const testPath = expect.getState().testPath
2020-12-24 17:09:38 +00:00
const testName = slash(testPath).match(/playground\/([\w-]+)\//)?.[1]
2020-12-20 03:33:13 +00:00
// if this is a test placed under playground/xxx/__tests__
// start a vite server in that directory.
if (testName) {
const playgroundRoot = resolve(__dirname, '../packages/playground')
const srcDir = resolve(playgroundRoot, testName)
tempDir = resolve(__dirname, '../temp', testName)
await fs.copy(srcDir, tempDir, {
2020-12-21 23:37:04 +00:00
dereference: true,
2020-12-20 03:33:13 +00:00
filter(file) {
2020-12-23 23:15:09 +00:00
file = slash(file)
return (
!file.includes('__tests__') &&
!file.includes('node_modules') &&
!file.match(/dist(\/|$)/)
)
2020-12-20 03:33:13 +00:00
}
})
2020-12-22 03:00:54 +00:00
const options: UserConfig = {
root: tempDir,
2020-12-22 04:15:38 +00:00
logLevel: 'error',
server: {
watch: {
2020-12-22 20:34:02 +00:00
// During tests we edit the files too fast and sometimes chokidar
// misses change events, so enforce polling for consistency
usePolling: true,
interval: 100
2020-12-22 04:15:38 +00:00
}
}
}
2020-12-20 03:33:13 +00:00
if (!isBuildTest) {
process.env.VITE_INLINE = 'inline-serve'
2020-12-22 03:00:54 +00:00
server = await (await createServer(options)).listen()
2020-12-20 03:33:13 +00:00
// use resolved port from server
const url = ((global as any).viteTestUrl = `http://localhost:${server.config.server.port}`)
2020-12-20 03:33:13 +00:00
await page.goto(url)
} else {
process.env.VITE_INLINE = 'inline-build'
2020-12-22 03:00:54 +00:00
await build(options)
const url = ((global as any).viteTestUrl = await startStaticServer())
2020-12-20 03:33:13 +00:00
await page.goto(url)
}
}
} catch (e) {
// jest doesn't exit if our setup has error here
// https://github.com/facebook/jest/issues/2713
err = e
}
})
afterAll(async () => {
2020-12-23 23:15:09 +00:00
page.off('console', onConsole)
2020-12-20 03:33:13 +00:00
if (server) {
await server.close()
}
if (err) {
throw err
}
})
function startStaticServer(): Promise<string> {
// check if the test project has base config
const configFile = resolve(tempDir, 'vite.config.js')
let config: UserConfig
try {
config = require(configFile)
} catch (e) {}
const base = config?.build?.base || ''
// @ts-ignore
if (config && config.__test__) {
// @ts-ignore
config.__test__()
}
2020-12-20 03:33:13 +00:00
// start static file server
2020-12-27 05:47:18 +00:00
const serve = sirv(resolve(tempDir, 'dist'))
const httpServer = (server = http.createServer((req, res) => {
if (req.url === '/ping') {
res.statusCode = 200
res.end('pong')
} else {
serve(req, res)
}
}))
2020-12-20 03:33:13 +00:00
let port = 5000
return new Promise((resolve, reject) => {
const onError = (e: any) => {
if (e.code === 'EADDRINUSE') {
httpServer.close()
httpServer.listen(++port)
} else {
reject(e)
}
}
httpServer.on('error', onError)
httpServer.listen(port, () => {
httpServer.removeListener('error', onError)
resolve(`http://localhost:${port}${base}`)
2020-12-20 03:33:13 +00:00
})
})
}