Skip to content
Permalink
Browse files

fix: dont force exit when it was explicitly disabled (#4973)

* fix: remove slash from warning text

* fix: dont force-exit when explicitly disabled

chore: add tests for force-exit behaviour

* feat: default option value can be fn
  • Loading branch information...
pimlie authored and clarkdo committed Feb 8, 2019
1 parent 3d2deac commit 4b82aa9d84a79076cc76ed837e4ec1bbc7830582
@@ -13,9 +13,6 @@ export default class NuxtCommand {
}
this.cmd = cmd

// If the cmd is a server then dont forcibly exit when the cmd has finished
this.isServer = cmd.isServer !== undefined ? cmd.isServer : Boolean(this.cmd.options.hostname)

this._argv = Array.from(argv)
this._parsedArgv = null // Lazy evaluate
}
@@ -48,9 +45,9 @@ export default class NuxtCommand {

const runResolve = Promise.resolve(this.cmd.run(this))

// TODO: For v3 set timeout to 0 when force-exit === true
if (!this.isServer || this.argv['force-exit']) {
runResolve.then(() => forceExit(this.cmd.name, forceExitTimeout))
if (this.argv['force-exit']) {
const forceExitByUser = this.isUserSuppliedArg('force-exit')
runResolve.then(() => forceExit(this.cmd.name, forceExitByUser ? false : forceExitTimeout))
}

return runResolve
@@ -102,6 +99,14 @@ export default class NuxtCommand {
return new Generator(nuxt, builder)
}

isUserSuppliedArg(option) {
return this._argv.includes(`--${option}`) || this._argv.includes(`--no-${option}`)
}

_getDefaultOptionValue(option) {
return typeof option.default === 'function' ? option.default(this.cmd) : option.default
}

_getMinimistOptions() {
const minimistOptions = {
alias: {},
@@ -120,7 +125,7 @@ export default class NuxtCommand {
minimistOptions[option.type].push(option.alias || name)
}
if (option.default) {
minimistOptions.default[option.alias || name] = option.default
minimistOptions.default[option.alias || name] = this._getDefaultOptionValue(option)
}
}

@@ -135,7 +140,7 @@ export default class NuxtCommand {
const option = this.cmd.options[name]

let optionHelp = '--'
optionHelp += option.type === 'boolean' && option.default ? 'no-' : ''
optionHelp += option.type === 'boolean' && this._getDefaultOptionValue(option) ? 'no-' : ''
optionHelp += name
if (option.alias) {
optionHelp += `, -${option.alias}`
@@ -28,11 +28,12 @@ export default {
}
}
},
// TODO: Change this to default: false in Nuxt v3 (see related todo's)
'force-exit': {
type: 'boolean',
default: true,
description: 'Do not force Nuxt.js to exit after the command has finished (this option has no effect on commands which start a server)'
default(cmd) {
return ['build', 'generate'].includes(cmd.name)
},
description: 'Whether Nuxt.js should force exit after the command has finished'
},
version: {
alias: 'v',
@@ -140,10 +140,10 @@ export function normalizeArg(arg, defaultValue) {
}

export function forceExit(cmdName, timeout) {
if (timeout) {
if (timeout !== false) {
const exitTimeout = setTimeout(() => {
const msg = `The command 'nuxt ${cmdName}' finished but did not exit after ${timeout}s
This is most likely not caused by a bug in Nuxt.js\
This is most likely not caused by a bug in Nuxt.js
Make sure to cleanup all timers and listeners you or your plugins/modules start.
Nuxt.js will now force exit
@@ -1,37 +1,36 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`cli/command builds help text 1`] = `
" Usage: nuxt this is how you do it
" Usage: nuxt this is how you do it
[options]

a very long description that should wrap
to the next line because is not longer
a very long description that should wrap
to the next line because is not longer
than the terminal width

Options:

--spa, -s Launch in SPA mode
--universal, -u Launch in Universal
--universal, -u Launch in Universal
mode (default)
--config-file, -c Path to Nuxt.js
--config-file, -c Path to Nuxt.js
config file (default: nuxt.config.js)
--modern, -m Build/Start app for
modern browsers, e.g. server, client and
--modern, -m Build/Start app for
modern browsers, e.g. server, client and
false
--no-force-exit Do not force Nuxt.js
to exit after the command has finished
(this option has no effect on commands
which start a server)
--version, -v Display the Nuxt
--force-exit Whether Nuxt.js
should force exit after the command has
finished
--version, -v Display the Nuxt
version
--help, -h Display this message
--port, -p Port number on which
--port, -p Port number on which
to start the application
--hostname, -H Hostname on which to
--hostname, -H Hostname on which to
start the application
--unix-socket, -n Path to a UNIX socket
--foo very long option that
is longer than the terminal width and
--foo very long option that
is longer than the terminal width and
should wrap to the next line

"
@@ -74,4 +74,36 @@ describe('build', () => {

expect(options.modern).toBe(true)
})

test('build force-exits by default', async () => {
mockGetNuxt()
mockGetBuilder(Promise.resolve())

const cmd = NuxtCommand.from(build, ['build', '.'])
await cmd.run()

expect(utils.forceExit).toHaveBeenCalledTimes(1)
expect(utils.forceExit).toHaveBeenCalledWith('build', 5)
})

test('build can set force exit explicitly', async () => {
mockGetNuxt()
mockGetBuilder(Promise.resolve())

const cmd = NuxtCommand.from(build, ['build', '.', '--force-exit'])
await cmd.run()

expect(utils.forceExit).toHaveBeenCalledTimes(1)
expect(utils.forceExit).toHaveBeenCalledWith('build', false)
})

test('build can disable force exit explicitly', async () => {
mockGetNuxt()
mockGetBuilder(Promise.resolve())

const cmd = NuxtCommand.from(build, ['build', '.', '--no-force-exit'])
await cmd.run()

expect(utils.forceExit).not.toHaveBeenCalled()
})
})
@@ -6,7 +6,6 @@ jest.mock('../../src/commands')

describe('cli', () => {
beforeAll(() => {
// TODO: Below spyOn can be removed in v3 when force-exit is default false
jest.spyOn(utils, 'forceExit').mockImplementation(() => {})
})

@@ -20,6 +19,7 @@ describe('cli', () => {

await run()
expect(mockedCommand.run).toHaveBeenCalled()
expect(utils.forceExit).not.toHaveBeenCalled()
})

test('sets NODE_ENV=development for dev', async () => {
@@ -6,7 +6,6 @@ describe('dev', () => {

beforeAll(async () => {
dev = await import('../../src/commands/dev').then(m => m.default)
// TODO: Below spyOn can be removed in v3 when force-exit is default false
jest.spyOn(utils, 'forceExit').mockImplementation(() => {})
})

@@ -107,4 +106,35 @@ describe('dev', () => {

expect(consola.error).toHaveBeenCalledWith(new Error('Listen Error'))
})

test('dev doesnt force-exit by default', async () => {
mockNuxt()
mockBuilder()

const cmd = NuxtCommand.from(dev, ['dev', '.'])
await cmd.run()

expect(utils.forceExit).not.toHaveBeenCalled()
})

test('dev can set force exit explicitly', async () => {
mockNuxt()
mockBuilder()

const cmd = NuxtCommand.from(dev, ['dev', '.', '--force-exit'])
await cmd.run()

expect(utils.forceExit).toHaveBeenCalledTimes(1)
expect(utils.forceExit).toHaveBeenCalledWith('dev', false)
})

test('dev can disable force exit explicitly', async () => {
mockNuxt()
mockBuilder()

const cmd = NuxtCommand.from(dev, ['dev', '.', '--no-force-exit'])
await cmd.run()

expect(utils.forceExit).not.toHaveBeenCalled()
})
})
@@ -63,4 +63,49 @@ describe('generate', () => {

expect(options.modern).toBe('client')
})

test('generate with modern mode', async () => {
mockGetNuxt()
mockGetGenerator(Promise.resolve())

const cmd = NuxtCommand.from(generate, ['generate', '.', '--m'])

const options = await cmd.getNuxtConfig()

await cmd.run()

expect(options.modern).toBe('client')
})

test('generate force-exits by default', async () => {
mockGetNuxt()
mockGetGenerator(Promise.resolve())

const cmd = NuxtCommand.from(generate, ['generate', '.'])
await cmd.run()

expect(utils.forceExit).toHaveBeenCalledTimes(1)
expect(utils.forceExit).toHaveBeenCalledWith('generate', 5)
})

test('generate can set force exit explicitly', async () => {
mockGetNuxt()
mockGetGenerator(Promise.resolve())

const cmd = NuxtCommand.from(generate, ['generate', '.', '--force-exit'])
await cmd.run()

expect(utils.forceExit).toHaveBeenCalledTimes(1)
expect(utils.forceExit).toHaveBeenCalledWith('generate', false)
})

test('generate can disable force exit explicitly', async () => {
mockGetNuxt()
mockGetGenerator(Promise.resolve())

const cmd = NuxtCommand.from(generate, ['generate', '.', '--no-force-exit'])
await cmd.run()

expect(utils.forceExit).not.toHaveBeenCalled()
})
})
@@ -7,7 +7,6 @@ describe('start', () => {

beforeAll(async () => {
start = await import('../../src/commands/start').then(m => m.default)
// TODO: Below spyOn can be removed in v3 when force-exit is default false
jest.spyOn(utils, 'forceExit').mockImplementation(() => {})
})

@@ -35,4 +34,32 @@ describe('start', () => {
await NuxtCommand.from(start).run()
expect(consola.fatal).not.toHaveBeenCalled()
})

test('start doesnt force-exit by default', async () => {
mockGetNuxtStart()

const cmd = NuxtCommand.from(start, ['start', '.'])
await cmd.run()

expect(utils.forceExit).not.toHaveBeenCalled()
})

test('start can set force exit explicitly', async () => {
mockGetNuxtStart()

const cmd = NuxtCommand.from(start, ['start', '.', '--force-exit'])
await cmd.run()

expect(utils.forceExit).toHaveBeenCalledTimes(1)
expect(utils.forceExit).toHaveBeenCalledWith('start', false)
})

test('start can disable force exit explicitly', async () => {
mockGetNuxtStart()

const cmd = NuxtCommand.from(start, ['start', '.', '--no-force-exit'])
await cmd.run()

expect(utils.forceExit).not.toHaveBeenCalled()
})
})
@@ -18,12 +18,12 @@ jest.mock('../../src/imports', () => {
}
})

export const mockGetNuxt = (options, implementation) => {
export const mockGetNuxt = (options = {}, implementation) => {
Command.prototype.getNuxt = jest.fn().mockImplementationOnce(() => {
return Object.assign({
hook: jest.fn(),
options
}, implementation || {})
}, implementation)
})
}

0 comments on commit 4b82aa9

Please sign in to comment.
You can’t perform that action at this time.