feat(test-utils): test in development mode (#3753)

This commit is contained in:
pooya parsa 2022-03-17 22:31:06 +01:00 committed by GitHub
parent 2590ae39d3
commit a50b8ca712
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 58 additions and 15 deletions

View File

@ -1,6 +1,6 @@
import { fileURLToPath } from 'url' import { fileURLToPath } from 'url'
import { describe, expect, it } from 'vitest' import { describe, expect, it } from 'vitest'
import { setup, $fetch } from '@nuxt/test-utils' import { setup, $fetch, isDev } from '@nuxt/test-utils'
describe('example', async () => { describe('example', async () => {
await setup({ await setup({
@ -11,4 +11,10 @@ describe('example', async () => {
it('Renders Hello Nuxt', async () => { it('Renders Hello Nuxt', async () => {
expect(await $fetch('/')).toMatch('Hello Nuxt!') expect(await $fetch('/')).toMatch('Hello Nuxt!')
}) })
if (isDev()) {
it('[dev] ensure vite client script is added', async () => {
expect(await $fetch('/')).toMatch('/_nuxt/@vite/client"')
})
}
}) })

View File

@ -4,7 +4,7 @@ import { defineNuxtCommand } from './index'
export default defineNuxtCommand({ export default defineNuxtCommand({
meta: { meta: {
name: 'test', name: 'test',
usage: 'npx nuxi test', usage: 'npx nuxi test [--dev] [--watch] [rootDir]',
description: 'Run tests' description: 'Run tests'
}, },
async invoke (args) { async invoke (args) {
@ -12,7 +12,9 @@ export default defineNuxtCommand({
const rootDir = resolve(args._[0] || '.') const rootDir = resolve(args._[0] || '.')
const { runTests } = await importTestUtils() const { runTests } = await importTestUtils()
await runTests({ await runTests({
rootDir rootDir,
dev: !!args.dev,
watch: !!args.watch
}) })
} }
}) })

View File

@ -10,6 +10,7 @@ export default defineBuildConfig({
externals: [ externals: [
'vitest', 'vitest',
'playwright', 'playwright',
'playwright-core' 'playwright-core',
'listhen'
] ]
}) })

View File

@ -10,6 +10,7 @@ export function createTestContext (options: Partial<TestOptions>): TestContext {
fixture: 'fixture', fixture: 'fixture',
configFile: 'nuxt.config', configFile: 'nuxt.config',
setupTimeout: 60000, setupTimeout: 60000,
dev: !!JSON.parse(process.env.NUXT_TEST_DEV || 'false'),
logLevel: 1, logLevel: 1,
server: options.browser, server: options.browser,
build: options.browser || options.server, build: options.browser || options.server,
@ -35,3 +36,8 @@ export function setTestContext (context: TestContext): TestContext {
currentContext = context currentContext = context
return currentContext return currentContext
} }
export function isDev () {
const ctx = useTestContext()
return ctx.options.dev
}

View File

@ -50,6 +50,7 @@ export async function loadFixture () {
ctx.nuxt = await kit.loadNuxt({ ctx.nuxt = await kit.loadNuxt({
cwd: ctx.options.rootDir, cwd: ctx.options.rootDir,
dev: ctx.options.dev,
overrides: ctx.options.nuxtConfig, overrides: ctx.options.nuxtConfig,
configFile: ctx.options.configFile configFile: ctx.options.configFile
}) })

View File

@ -1,5 +1,7 @@
export interface RunTestOptions { export interface RunTestOptions {
rootDir: string, rootDir: string,
dev?: boolean,
watch?: boolean
runner?: 'vitest' runner?: 'vitest'
} }
@ -13,13 +15,19 @@ export async function runTests (opts: RunTestOptions) {
if (opts.runner !== 'vitest') { if (opts.runner !== 'vitest') {
throw new Error(`Unsupported runner: ${opts.runner}. Currently only vitest runner is supported.`) throw new Error(`Unsupported runner: ${opts.runner}. Currently only vitest runner is supported.`)
} }
if (opts.dev) {
// Set default dev option for @nuxt/test-utils
process.env.NUXT_TEST_DEV = 'true'
}
const { startVitest } = await import('vitest/dist/node.js') const { startVitest } = await import('vitest/dist/node.js')
const succeeded = await startVitest( const succeeded = await startVitest(
[] /* argv */, [] /* argv */,
// Vitest options // Vitest options
{ {
root: opts.rootDir, root: opts.rootDir,
run: true run: !opts.watch
}, },
// Vite options // Vite options
{ {

View File

@ -9,17 +9,30 @@ export async function startServer () {
await stopServer() await stopServer()
const port = await getRandomPort() const port = await getRandomPort()
ctx.url = 'http://localhost:' + port ctx.url = 'http://localhost:' + port
ctx.serverProcess = execa('node', [ if (ctx.options.dev) {
// @ts-ignore ctx.listener = await ctx.nuxt.server.listen(port)
resolve(ctx.nuxt.options.nitro.output.dir, 'server/index.mjs') await waitForPort(port, { retries: 8 })
], { for (let i = 0; i < 50; i++) {
env: { await new Promise(resolve => setTimeout(resolve, 100))
...process.env, const res = await $fetch('/')
PORT: String(port), if (!res.includes('__NUXT_LOADING__')) {
NODE_ENV: 'test' return
}
} }
}) throw new Error('Timeout waiting for dev server!')
await waitForPort(port, { retries: 8 }) } else {
ctx.serverProcess = execa('node', [
resolve(ctx.nuxt.options.nitro.output.dir, 'server/index.mjs')
], {
stdio: 'inherit',
env: {
...process.env,
PORT: String(port),
NODE_ENV: 'test'
}
})
await waitForPort(port, { retries: 8 })
}
} }
export async function stopServer () { export async function stopServer () {
@ -27,6 +40,9 @@ export async function stopServer () {
if (ctx.serverProcess) { if (ctx.serverProcess) {
await ctx.serverProcess.kill() await ctx.serverProcess.kill()
} }
if (ctx.listener) {
await ctx.listener.close()
}
} }
export function fetch (path: string, options?: any) { export function fetch (path: string, options?: any) {

View File

@ -1,6 +1,7 @@
import type { Nuxt, NuxtConfig } from '@nuxt/schema' import type { Nuxt, NuxtConfig } from '@nuxt/schema'
import type { ExecaChildProcess } from 'execa' import type { ExecaChildProcess } from 'execa'
import type { Browser, LaunchOptions } from 'playwright' import type { Browser, LaunchOptions } from 'playwright'
import type { Listener } from 'listhen'
export type TestRunner = 'vitest' | 'jest' export type TestRunner = 'vitest' | 'jest'
@ -12,6 +13,7 @@ export interface TestOptions {
buildDir: string buildDir: string
nuxtConfig: NuxtConfig nuxtConfig: NuxtConfig
build: boolean build: boolean
dev: boolean
setupTimeout: number setupTimeout: number
waitFor: number waitFor: number
browser: boolean browser: boolean
@ -30,6 +32,7 @@ export interface TestContext {
browser?: Browser browser?: Browser
url?: string url?: string
serverProcess?: ExecaChildProcess serverProcess?: ExecaChildProcess
listener?: Listener
} }
export interface TestHooks { export interface TestHooks {