diff --git a/test/fixtures/cli/cli.build.config.js b/test/fixtures/cli/cli.build.config.js new file mode 100644 index 0000000000..ca159d392a --- /dev/null +++ b/test/fixtures/cli/cli.build.config.js @@ -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}`) + }) + } +} diff --git a/test/fixtures/cli/cli.build.test.js b/test/fixtures/cli/cli.build.test.js new file mode 100644 index 0000000000..48c6f9615f --- /dev/null +++ b/test/fixtures/cli/cli.build.test.js @@ -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') + }) + }) +}) diff --git a/test/fixtures/cli/cli.gen.config.js b/test/fixtures/cli/cli.gen.config.js new file mode 100644 index 0000000000..212a2c666f --- /dev/null +++ b/test/fixtures/cli/cli.gen.config.js @@ -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') + } + }) + } +} diff --git a/test/fixtures/cli/cli.gen.test.js b/test/fixtures/cli/cli.gen.test.js new file mode 100644 index 0000000000..4e58a1bdc5 --- /dev/null +++ b/test/fixtures/cli/cli.gen.test.js @@ -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) +}) diff --git a/test/fixtures/cli/pages/index.vue b/test/fixtures/cli/pages/index.vue new file mode 100644 index 0000000000..82cb6da1cd --- /dev/null +++ b/test/fixtures/cli/pages/index.vue @@ -0,0 +1,3 @@ + diff --git a/test/unit/cli-start.test.js b/test/unit/cli-start.test.js new file mode 100644 index 0000000000..ea8ee96970 --- /dev/null +++ b/test/unit/cli-start.test.js @@ -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(('
CLI Test
')) + + 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) + }) +}) diff --git a/test/unit/cli.test.js b/test/unit/cli.test.js index 04da799a56..ea8ee96970 100644 --- a/test/unit/cli.test.js +++ b/test/unit/cli.test.js @@ -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('

User: 1

')).toBe(true) + const html = await rp(url('/')) + expect(html).toMatch(('
CLI Test
')) 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) - }) }) diff --git a/test/unit/utils.test.js b/test/unit/utils.test.js index 1701177102..a0114ac691 100644 --- a/test/unit/utils.test.js +++ b/test/unit/utils.test.js @@ -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') diff --git a/test/utils/index.js b/test/utils/index.js index c182b1a7dd..65df9ab3c1 100644 --- a/test/utils/index.js +++ b/test/utils/index.js @@ -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 +}