test: refactor cli tests (#3357)

* refactor: add untility for waiting until condition completed

* test: cli

* test: separate config of generate and build in cli test

* test: increase timeout of cli test slightly

* refactor: move waitUntil to test utils

* fix: use waitUntil in test utils
This commit is contained in:
Clark Du 2018-06-06 13:31:43 +01:00 committed by Pooya Parsa
parent 2e6d503f76
commit 3c54d26c76
9 changed files with 178 additions and 54 deletions

12
test/fixtures/cli/cli.build.config.js vendored Normal file
View File

@ -0,0 +1,12 @@
import consola from 'consola'
export default {
hooks(hook) {
hook('build:done', builder => {
consola.success('Compiled successfully')
})
hook('listen', (server, { port, host }) => {
consola.success(`Listening on http://${host}:${port}`)
})
}
}

21
test/fixtures/cli/cli.build.test.js vendored Normal file
View File

@ -0,0 +1,21 @@
import { exec } from 'child_process'
import { resolve } from 'path'
import { promisify } from 'util'
const execify = promisify(exec)
const rootDir = __dirname
const nuxtBin = resolve(__dirname, '..', '..', '..', 'bin', 'nuxt')
describe('cli build', () => {
test('nuxt build', async () => {
const { stdout } = await execify(`node ${nuxtBin} build ${rootDir} -c cli.build.config.js`)
expect(stdout.includes('Compiled successfully')).toBe(true)
}, 80000)
test('nuxt build -> error config', async () => {
await expect(execify(`node ${nuxtBin} build ${rootDir} -c config.js`)).rejects.toMatchObject({
stdout: expect.stringContaining('Could not load config file: config.js')
})
})
})

17
test/fixtures/cli/cli.gen.config.js vendored Normal file
View File

@ -0,0 +1,17 @@
import consola from 'consola'
export default {
buildDir: '.nuxt-generate/.build',
generate: {
dir: '.nuxt-generate/.generate'
},
hooks(hook) {
hook('generate:done', (generator, errors) => {
if (!errors || errors.length === 0) {
consola.success('Generated successfully')
} else {
consola.error('Generated failed')
}
})
}
}

15
test/fixtures/cli/cli.gen.test.js vendored Normal file
View File

@ -0,0 +1,15 @@
import { exec } from 'child_process'
import { resolve } from 'path'
import { promisify } from 'util'
const execify = promisify(exec)
const rootDir = __dirname
const nuxtBin = resolve(__dirname, '..', '..', '..', 'bin', 'nuxt')
describe('cli generate', () => {
test('nuxt generate', async () => {
const { stdout } = await execify(`node ${nuxtBin} generate ${rootDir} -c cli.gen.config.js`)
expect(stdout.includes('Generated successfully')).toBe(true)
}, 80000)
})

3
test/fixtures/cli/pages/index.vue vendored Normal file
View File

@ -0,0 +1,3 @@
<template>
<div>CLI Test</div>
</template>

View File

@ -0,0 +1,63 @@
import { spawn } from 'child_process'
import { resolve } from 'path'
import { getPort, rp, waitUntil } from '../utils'
let port
const rootDir = resolve(__dirname, '..', 'fixtures/cli')
const url = route => 'http://localhost:' + port + route
const nuxtBin = resolve(__dirname, '..', '..', 'bin', 'nuxt')
describe('cli', () => {
test('nuxt start', async () => {
let stdout = ''
let error
let exitCode
const env = process.env
env.PORT = port = await getPort()
const nuxtStart = spawn('node', [nuxtBin, 'start', rootDir], { env })
nuxtStart.stdout.on('data', data => {
stdout += data
})
nuxtStart.on('error', err => {
error = err
})
nuxtStart.on('close', code => {
exitCode = code
})
// Wait max 20s for the starting
let timeout = await waitUntil(() => stdout.includes('Listening on'))
if (timeout === true) {
error = 'server failed to start successfully in 20 seconds'
}
expect(error).toBe(undefined)
expect(stdout.includes('Listening on')).toBe(true)
const html = await rp(url('/'))
expect(html).toMatch(('<div>CLI Test</div>'))
nuxtStart.kill()
// Wait max 10s for the process to be killed
timeout = await waitUntil(() => exitCode !== undefined, 10)
if (timeout === true) {
console.warn( // eslint-disable-line no-console
`we were unable to automatically kill the child process with pid: ${
nuxtStart.pid
}`
)
}
expect(exitCode).toBe(null)
})
})

View File

@ -1,48 +1,29 @@
import { exec, spawn } from 'child_process'
import { spawn } from 'child_process'
import { resolve } from 'path'
import { promisify } from 'util'
import { Utils, rp } from '../utils'
const execify = promisify(exec)
const rootDir = resolve(__dirname, '..', 'fixtures/basic')
import { getPort, rp, waitUntil } from '../utils'
let port
const rootDir = resolve(__dirname, '..', 'fixtures/cli')
const url = route => 'http://localhost:' + port + route
const nuxtBin = resolve(__dirname, '..', '..', 'bin', 'nuxt')
describe.skip('cli', () => {
test('nuxt build', async () => {
const { stdout } = await execify(`node ${nuxtBin} build ${rootDir}`)
expect(stdout.includes('Compiled successfully')).toBe(true)
})
test('nuxt build -> error config', async () => {
await expect(execify(`node ${nuxtBin} build ${rootDir} -c config.js`)).rejects.toMatchObject({
stderr: expect.stringContaining('Could not load config file')
})
})
describe('cli', () => {
test('nuxt start', async () => {
let stdout = ''
// let stderr = ''
let error
let exitCode
const env = process.env
env.PORT = port
env.PORT = port = await getPort()
const nuxtStart = spawn('node', [nuxtBin, 'start', rootDir], { env: env })
const nuxtStart = spawn('node', [nuxtBin, 'start', rootDir], { env })
nuxtStart.stdout.on('data', data => {
stdout += data
})
nuxtStart.stderr.on('data', data => {
// stderr += data
})
nuxtStart.on('error', err => {
error = err
})
@ -51,37 +32,27 @@ describe.skip('cli', () => {
exitCode = code
})
// Give the process max 20s to start
let iterator = 0
while (!stdout.includes('OPEN') && iterator < 80) {
await Utils.waitFor(250)
iterator++
}
// Wait max 20s for the starting
let timeout = await waitUntil(() => stdout.includes('Listening on'))
if (iterator === 80) {
test.log('WARN: server failed to start successfully in 20 seconds')
if (timeout === true) {
error = 'server failed to start successfully in 20 seconds'
}
expect(error).toBe(undefined)
expect(stdout.includes('OPEN')).toBe(true)
expect(stdout.includes('Listening on')).toBe(true)
const html = await rp(url('/users/1'))
expect(html.includes('<h1>User: 1</h1>')).toBe(true)
const html = await rp(url('/'))
expect(html).toMatch(('<div>CLI Test</div>'))
nuxtStart.kill()
// Wait max 10s for the process to be killed
iterator = 0
// eslint-disable-next-line no-unmodified-loop-condition
while (exitCode === undefined && iterator < 40) {
await Utils.waitFor(250)
iterator++
}
timeout = await waitUntil(() => exitCode !== undefined, 10)
if (iterator >= 40) {
// eslint-disable-line no-console
test.log(
`WARN: we were unable to automatically kill the child process with pid: ${
if (timeout === true) {
console.warn( // eslint-disable-line no-console
`we were unable to automatically kill the child process with pid: ${
nuxtStart.pid
}`
)
@ -89,10 +60,4 @@ describe.skip('cli', () => {
expect(exitCode).toBe(null)
})
test('nuxt generate', async () => {
const { stdout } = await execify(`node ${nuxtBin} generate ${rootDir}`)
expect(stdout.includes('vue-ssr-client-manifest.json')).toBe(true)
})
})

View File

@ -1,5 +1,5 @@
import path from 'path'
import { Utils } from '../utils'
import { Utils, waitUntil } from '../utils'
describe('utils', () => {
test('encodeHtml', () => {
@ -23,6 +23,11 @@ describe('utils', () => {
await Utils.waitFor()
})
test('waitUntil', async () => {
expect(await waitUntil(() => true, 0.1, 100)).toBe(false)
expect(await waitUntil(() => false, 0.1, 100)).toBe(true)
})
test('timeout (promise)', async () => {
const result = await Utils.timeout(Promise.resolve('time not run out'), 100)
expect(result).toBe('time not run out')

View File

@ -31,3 +31,26 @@ export const loadFixture = function loadFixture(fixture, overrides) {
return defaultsDeep({}, overrides, config)
}
/**
* Prepare an object to pass to the createSportsSelectionView function
* @param {Function} condition return true to stop the waiting
* @param {Number} duration seconds totally wait
* @param {Number} interval milliseconds interval to check the condition
*
* @returns {Boolean} true: timeout, false: condition becomes true within total time
*/
export const waitUntil = async function waitUntil(condition, duration = 20, interval = 250) {
let iterator = 0
const steps = Math.floor(duration * 1000 / interval)
while (!condition() && iterator < steps) {
await Utils.waitFor(interval)
iterator++
}
if (iterator === steps) {
return true
}
return false
}