mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-23 14:15:13 +00:00
feat(cli): improvements and external commands (#4314)
This commit is contained in:
parent
8b366fd216
commit
0145551c3a
@ -1,3 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
require('../dist/cli.js').run()
|
||||
.catch((error) => {
|
||||
require('consola').fatal(error)
|
||||
process.exit(1)
|
||||
})
|
||||
|
@ -17,6 +17,7 @@
|
||||
"chalk": "^2.4.1",
|
||||
"consola": "^2.3.0",
|
||||
"esm": "^3.0.84",
|
||||
"execa": "^1.0.0",
|
||||
"minimist": "^1.2.0",
|
||||
"pretty-bytes": "^5.1.0",
|
||||
"std-env": "^2.2.1",
|
||||
|
@ -1,66 +1,72 @@
|
||||
import parseArgs from 'minimist'
|
||||
|
||||
import minimist from 'minimist'
|
||||
import { name, version } from '../package.json'
|
||||
import { loadNuxtConfig } from './utils'
|
||||
import { indent, foldLines, startSpaces, optionSpaces, colorize } from './utils/formatting'
|
||||
import * as commands from './commands'
|
||||
import * as imports from './imports'
|
||||
|
||||
export default class NuxtCommand {
|
||||
constructor(cmd = { name: '', usage: '', description: '', options: {} }) {
|
||||
constructor(cmd = { name: '', usage: '', description: '' }, argv = process.argv.slice(2)) {
|
||||
if (!cmd.options) {
|
||||
cmd.options = {}
|
||||
}
|
||||
this.cmd = cmd
|
||||
|
||||
this._argv = Array.from(argv)
|
||||
this._parsedArgv = null // Lazy evaluate
|
||||
}
|
||||
|
||||
static async load(name) {
|
||||
if (name in commands) {
|
||||
const cmd = await commands[name]() // eslint-disable-line import/namespace
|
||||
.then(m => m.default)
|
||||
return NuxtCommand.from(cmd)
|
||||
} else {
|
||||
// TODO dynamic module loading
|
||||
throw new Error('Command ' + name + ' could not be loaded!')
|
||||
}
|
||||
static run(cmd, argv) {
|
||||
return NuxtCommand.from(cmd, argv).run()
|
||||
}
|
||||
|
||||
static from(options) {
|
||||
if (options instanceof NuxtCommand) {
|
||||
return options
|
||||
static from(cmd, argv) {
|
||||
if (cmd instanceof NuxtCommand) {
|
||||
return cmd
|
||||
}
|
||||
return new NuxtCommand(options)
|
||||
return new NuxtCommand(cmd, argv)
|
||||
}
|
||||
|
||||
run() {
|
||||
return this.cmd.run(this)
|
||||
if (this.argv.help) {
|
||||
this.showHelp()
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
if (this.argv.version) {
|
||||
this.showVersion()
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
if (typeof this.cmd.run !== 'function') {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
return Promise.resolve(this.cmd.run(this))
|
||||
}
|
||||
|
||||
showVersion() {
|
||||
process.stdout.write(`${name} v${version}\n`)
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
showHelp() {
|
||||
process.stdout.write(this._getHelp())
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
getArgv(args) {
|
||||
const minimistOptions = this._getMinimistOptions()
|
||||
const argv = parseArgs(args || process.argv.slice(2), minimistOptions)
|
||||
|
||||
if (argv.version) {
|
||||
this.showVersion()
|
||||
} else if (argv.help) {
|
||||
this.showHelp()
|
||||
get argv() {
|
||||
if (!this._parsedArgv) {
|
||||
const minimistOptions = this._getMinimistOptions()
|
||||
this._parsedArgv = minimist(this._argv, minimistOptions)
|
||||
}
|
||||
|
||||
return argv
|
||||
return this._parsedArgv
|
||||
}
|
||||
|
||||
async getNuxtConfig(argv, extraOptions) {
|
||||
const config = await loadNuxtConfig(argv)
|
||||
async getNuxtConfig(extraOptions) {
|
||||
const config = await loadNuxtConfig(this.argv)
|
||||
const options = Object.assign(config, extraOptions || {})
|
||||
|
||||
for (const name of Object.keys(this.cmd.options)) {
|
||||
this.cmd.options[name].prepare && this.cmd.options[name].prepare(this, options, argv)
|
||||
this.cmd.options[name].prepare && this.cmd.options[name].prepare(this, options, this.argv)
|
||||
}
|
||||
|
||||
return options
|
||||
|
@ -1,4 +1,3 @@
|
||||
import consola from 'consola'
|
||||
import { common } from '../options'
|
||||
|
||||
export default {
|
||||
@ -50,37 +49,17 @@ export default {
|
||||
}
|
||||
},
|
||||
async run(cmd) {
|
||||
const argv = cmd.getArgv()
|
||||
const config = await cmd.getNuxtConfig({ dev: false })
|
||||
const nuxt = await cmd.getNuxt(config)
|
||||
|
||||
// Create production build when calling `nuxt build` (dev: false)
|
||||
const nuxt = await cmd.getNuxt(
|
||||
await cmd.getNuxtConfig(argv, { dev: false })
|
||||
)
|
||||
|
||||
let builderOrGenerator
|
||||
if (nuxt.options.mode !== 'spa' || argv.generate === false) {
|
||||
if (nuxt.options.mode !== 'spa' || cmd.argv.generate === false) {
|
||||
// Build only
|
||||
builderOrGenerator = (await cmd.getBuilder(nuxt)).build()
|
||||
const builder = await cmd.getBuilder(nuxt)
|
||||
await builder.build()
|
||||
} else {
|
||||
// Build + Generate for static deployment
|
||||
builderOrGenerator = (await cmd.getGenerator(nuxt)).generate({
|
||||
build: true
|
||||
})
|
||||
const generator = await cmd.getGenerator(nuxt)
|
||||
await generator.generate({ build: true })
|
||||
}
|
||||
|
||||
return builderOrGenerator
|
||||
.then(() => {
|
||||
// In analyze mode wait for plugin
|
||||
// emitting assets and opening browser
|
||||
if (
|
||||
nuxt.options.build.analyze === true ||
|
||||
typeof nuxt.options.build.analyze === 'object'
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
process.exit(0)
|
||||
})
|
||||
.catch(err => consola.fatal(err))
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ export default {
|
||||
},
|
||||
|
||||
async run(cmd) {
|
||||
const argv = cmd.getArgv()
|
||||
const argv = cmd.argv
|
||||
await this.startDev(cmd, argv)
|
||||
},
|
||||
|
||||
@ -26,10 +26,7 @@ export default {
|
||||
},
|
||||
|
||||
async _startDev(cmd, argv) {
|
||||
// Load config
|
||||
const config = await cmd.getNuxtConfig(argv, { dev: true })
|
||||
|
||||
// Initialize nuxt instance
|
||||
const config = await cmd.getNuxtConfig({ dev: true })
|
||||
const nuxt = await cmd.getNuxt(config)
|
||||
|
||||
// Setup hooks
|
||||
|
@ -1,4 +1,3 @@
|
||||
import consola from 'consola'
|
||||
import { common } from '../options'
|
||||
import { normalizeArg } from '../utils'
|
||||
|
||||
@ -36,19 +35,13 @@ export default {
|
||||
}
|
||||
},
|
||||
async run(cmd) {
|
||||
const argv = cmd.getArgv()
|
||||
const config = await cmd.getNuxtConfig({ dev: false })
|
||||
const nuxt = await cmd.getNuxt(config)
|
||||
const generator = await cmd.getGenerator(nuxt)
|
||||
|
||||
const generator = await cmd.getGenerator(
|
||||
await cmd.getNuxt(
|
||||
await cmd.getNuxtConfig(argv, { dev: false })
|
||||
)
|
||||
)
|
||||
|
||||
return generator.generate({
|
||||
await generator.generate({
|
||||
init: true,
|
||||
build: argv.build
|
||||
}).then(() => {
|
||||
process.exit(0)
|
||||
}).catch(err => consola.fatal(err))
|
||||
build: cmd.argv.build
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,25 @@
|
||||
import consola from 'consola'
|
||||
import NuxtCommand from '../command'
|
||||
import getCommand from '../commands'
|
||||
import listCommands from '../list'
|
||||
import { common } from '../options'
|
||||
import NuxtCommand from '../command'
|
||||
|
||||
export default {
|
||||
name: 'help',
|
||||
description: 'Shows help for <command>',
|
||||
usage: 'help <command>',
|
||||
options: {
|
||||
help: common.help,
|
||||
version: common.version
|
||||
},
|
||||
async run(cmd) {
|
||||
const argv = cmd.getArgv()._
|
||||
const name = argv[0] || null
|
||||
const name = cmd._argv[0]
|
||||
if (!name) {
|
||||
return listCommands().then(() => process.exit(0))
|
||||
return listCommands()
|
||||
}
|
||||
const command = await NuxtCommand.load(name)
|
||||
const command = await getCommand(name)
|
||||
if (command) {
|
||||
command.showHelp()
|
||||
NuxtCommand.from(command).showHelp()
|
||||
} else {
|
||||
consola.info(`Unknown command: ${name}`)
|
||||
}
|
||||
|
@ -1,5 +1,14 @@
|
||||
export const start = () => import('./start')
|
||||
export const dev = () => import('./dev')
|
||||
export const build = () => import('./build')
|
||||
export const generate = () => import('./generate')
|
||||
export const help = () => import('./help')
|
||||
const commands = {
|
||||
start: () => import('./start'),
|
||||
dev: () => import('./dev'),
|
||||
build: () => import('./build'),
|
||||
generate: () => import('./generate'),
|
||||
help: () => import('./help')
|
||||
}
|
||||
|
||||
export default function getCommand(name) {
|
||||
if (!commands[name]) {
|
||||
return Promise.resolve(null)
|
||||
}
|
||||
return commands[name]().then(m => m.default)
|
||||
}
|
||||
|
@ -10,16 +10,11 @@ export default {
|
||||
...server
|
||||
},
|
||||
async run(cmd) {
|
||||
const argv = cmd.getArgv()
|
||||
|
||||
// Create production build when calling `nuxt build`
|
||||
const nuxt = await cmd.getNuxt(
|
||||
await cmd.getNuxtConfig(argv, { dev: false, _start: true })
|
||||
)
|
||||
const config = await cmd.getNuxtConfig({ dev: false, _start: true })
|
||||
const nuxt = await cmd.getNuxt(config)
|
||||
|
||||
// Listen and show ready banner
|
||||
return nuxt.server.listen().then(() => {
|
||||
showBanner(nuxt)
|
||||
})
|
||||
await nuxt.server.listen()
|
||||
showBanner(nuxt)
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
import chalk from 'chalk'
|
||||
import NuxtCommand from './command'
|
||||
import { indent, foldLines, startSpaces, optionSpaces, colorize } from './utils/formatting'
|
||||
import getCommand from './commands'
|
||||
|
||||
export default async function listCommands() {
|
||||
const commandsOrder = ['dev', 'build', 'generate', 'start', 'help']
|
||||
|
||||
// Load all commands
|
||||
const _commands = await Promise.all(
|
||||
commandsOrder.map(cmd => NuxtCommand.load(cmd))
|
||||
commandsOrder.map(cmd => getCommand(cmd))
|
||||
)
|
||||
|
||||
let maxLength = 0
|
||||
|
@ -28,6 +28,7 @@ export default {
|
||||
}
|
||||
},
|
||||
version: {
|
||||
alias: 'v',
|
||||
type: 'boolean',
|
||||
description: 'Display the Nuxt version'
|
||||
},
|
||||
|
@ -1,31 +1,42 @@
|
||||
import consola from 'consola'
|
||||
import fs from 'fs'
|
||||
import execa from 'execa'
|
||||
import NuxtCommand from './command'
|
||||
import * as commands from './commands'
|
||||
import setup from './setup'
|
||||
import listCommands from './list'
|
||||
import getCommand from './commands'
|
||||
|
||||
export default function run() {
|
||||
const defaultCommand = 'dev'
|
||||
let cmd = process.argv[2]
|
||||
export default async function run(_argv) {
|
||||
// Read from process.argv
|
||||
const argv = _argv ? Array.from(_argv) : process.argv.slice(2)
|
||||
|
||||
if (commands[cmd]) { // eslint-disable-line import/namespace
|
||||
process.argv.splice(2, 1)
|
||||
} else {
|
||||
if (process.argv.includes('--help') || process.argv.includes('-h')) {
|
||||
listCommands().then(() => process.exit(0))
|
||||
return
|
||||
}
|
||||
cmd = defaultCommand
|
||||
// Check for internal command
|
||||
let cmd = await getCommand(argv[0])
|
||||
|
||||
// Matching `nuxt` or `nuxt [dir]` or `nuxt -*` for `nuxt dev` shortcut
|
||||
if (!cmd && (!argv[0] || argv[0][0] === '-' || fs.existsSync(argv[0]))) {
|
||||
argv.unshift('dev')
|
||||
cmd = await getCommand('dev')
|
||||
}
|
||||
|
||||
// Setup runtime
|
||||
setup({
|
||||
dev: cmd === 'dev'
|
||||
})
|
||||
// Setup env
|
||||
setup({ dev: argv[0] === 'dev' })
|
||||
|
||||
return NuxtCommand.load(cmd)
|
||||
.then(command => command.run())
|
||||
.catch((error) => {
|
||||
consola.fatal(error)
|
||||
// Try internal command
|
||||
if (cmd) {
|
||||
return NuxtCommand.run(cmd, argv.slice(1))
|
||||
}
|
||||
|
||||
// Try external command
|
||||
try {
|
||||
await execa(`nuxt-${argv[0]}`, argv.slice(1), {
|
||||
stdout: process.stdout,
|
||||
stderr: process.stderr,
|
||||
stdin: process.stdin
|
||||
})
|
||||
} catch (error) {
|
||||
if (error.code === 'ENOENT') {
|
||||
throw String(`Command not found: nuxt-${argv[0]}`)
|
||||
} else {
|
||||
throw String(`Failed to run command \`nuxt-${argv[0]}\`:\n${error}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import chalk from 'chalk'
|
||||
import prettyBytes from 'pretty-bytes'
|
||||
import env from 'std-env'
|
||||
|
||||
const _require = esm(module, {
|
||||
export const requireModule = esm(module, {
|
||||
cache: false,
|
||||
cjs: {
|
||||
cache: true,
|
||||
@ -35,7 +35,7 @@ export async function loadNuxtConfig(argv) {
|
||||
|
||||
if (existsSync(nuxtConfigFile)) {
|
||||
delete require.cache[nuxtConfigFile]
|
||||
options = _require(nuxtConfigFile) || {}
|
||||
options = requireModule(nuxtConfigFile) || {}
|
||||
if (options.default) {
|
||||
options = options.default
|
||||
}
|
||||
@ -120,6 +120,13 @@ export function showBanner(nuxt) {
|
||||
process.stdout.write(box + '\n')
|
||||
}
|
||||
|
||||
export function formatPath(filePath) {
|
||||
if (!filePath) {
|
||||
return
|
||||
}
|
||||
return filePath.replace(process.cwd() + path.sep, '')
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize string argument in command
|
||||
*
|
||||
@ -137,10 +144,3 @@ export function normalizeArg(arg, defaultValue) {
|
||||
}
|
||||
return arg
|
||||
}
|
||||
|
||||
export function formatPath(filePath) {
|
||||
if (!filePath) {
|
||||
return
|
||||
}
|
||||
return filePath.replace(process.cwd() + path.sep, '')
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ exports[`cli/command builds help text 1`] = `
|
||||
--universal, -u Launch in Universal mode (default)
|
||||
--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 false
|
||||
--version Display the Nuxt version
|
||||
--version, -v Display the Nuxt version
|
||||
--help, -h Display this message
|
||||
--port, -p Port number on which to start the application
|
||||
--hostname, -H Hostname on which to start the application
|
||||
@ -20,23 +20,3 @@ exports[`cli/command builds help text 1`] = `
|
||||
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`cli/command loads command from name 1`] = `
|
||||
" Usage: nuxt dev <dir> [options]
|
||||
|
||||
Start the application in development mode (e.g. hot-code reloading, error reporting)
|
||||
|
||||
Options:
|
||||
|
||||
--spa, -s Launch in SPA mode
|
||||
--universal, -u Launch in Universal mode (default)
|
||||
--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 false
|
||||
--version Display the Nuxt version
|
||||
--help, -h Display this message
|
||||
--port, -p Port number on which to start the application
|
||||
--hostname, -H Hostname on which to start the application
|
||||
--unix-socket, -n Path to a UNIX socket
|
||||
|
||||
"
|
||||
`;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { consola, mockGetNuxt, mockGetBuilder, mockGetGenerator, NuxtCommand } from '../utils'
|
||||
import { mockGetNuxt, mockGetBuilder, mockGetGenerator, NuxtCommand } from '../utils'
|
||||
|
||||
describe('build', () => {
|
||||
let build
|
||||
@ -8,7 +8,6 @@ describe('build', () => {
|
||||
jest.spyOn(process, 'exit').mockImplementation(code => code)
|
||||
})
|
||||
|
||||
afterAll(() => process.exit.mockRestore())
|
||||
afterEach(() => jest.resetAllMocks())
|
||||
|
||||
test('has run function', () => {
|
||||
@ -41,7 +40,6 @@ describe('build', () => {
|
||||
await NuxtCommand.from(build).run()
|
||||
|
||||
expect(generate).toHaveBeenCalled()
|
||||
expect(process.exit).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test('build with devtools', async () => {
|
||||
@ -50,12 +48,9 @@ describe('build', () => {
|
||||
})
|
||||
const builder = mockGetBuilder(Promise.resolve())
|
||||
|
||||
const cmd = NuxtCommand.from(build)
|
||||
const args = ['build', '.', '--devtools']
|
||||
const argv = cmd.getArgv(args)
|
||||
argv._ = ['.']
|
||||
const cmd = NuxtCommand.from(build, ['build', '.', '--devtools'])
|
||||
|
||||
const options = await cmd.getNuxtConfig(argv)
|
||||
const options = await cmd.getNuxtConfig(cmd.argv)
|
||||
|
||||
await cmd.run()
|
||||
|
||||
@ -69,22 +64,12 @@ describe('build', () => {
|
||||
})
|
||||
mockGetBuilder(Promise.resolve())
|
||||
|
||||
const cmd = NuxtCommand.from(build)
|
||||
const args = ['build', '.', '--m']
|
||||
const cmd = NuxtCommand.from(build, ['build', '.', '--m'])
|
||||
|
||||
const options = await cmd.getNuxtConfig(cmd.getArgv(args))
|
||||
const options = await cmd.getNuxtConfig()
|
||||
|
||||
await cmd.run()
|
||||
|
||||
expect(options.modern).toBe(true)
|
||||
})
|
||||
|
||||
test('catches error', async () => {
|
||||
mockGetNuxt({ mode: 'universal' })
|
||||
mockGetBuilder(Promise.reject(new Error('Builder Error')))
|
||||
|
||||
await NuxtCommand.from(build).run()
|
||||
|
||||
expect(consola.fatal).toHaveBeenCalledWith(new Error('Builder Error'))
|
||||
})
|
||||
})
|
||||
|
@ -1,87 +1,41 @@
|
||||
import { readdir } from 'fs'
|
||||
import { resolve } from 'path'
|
||||
import { promisify } from 'util'
|
||||
import { consola } from '../utils'
|
||||
import { run } from '../../src'
|
||||
import * as commands from '../../src/commands'
|
||||
|
||||
const readDir = promisify(readdir)
|
||||
import getCommand from '../../src/commands'
|
||||
|
||||
jest.mock('../../src/commands')
|
||||
|
||||
describe('cli', () => {
|
||||
afterEach(() => jest.resetAllMocks())
|
||||
|
||||
test('exports for all commands defined', async () => {
|
||||
const cmds = await readDir(resolve(__dirname, '..', '..', 'src', 'commands'))
|
||||
|
||||
for (let cmd of cmds) {
|
||||
if (cmd === 'index.js') {
|
||||
continue
|
||||
}
|
||||
cmd = cmd.substring(0, cmd.length - 3)
|
||||
|
||||
const cmdFn = commands[cmd] // eslint-disable-line import/namespace
|
||||
expect(cmdFn).toBeDefined()
|
||||
expect(typeof cmdFn).toBe('function')
|
||||
}
|
||||
})
|
||||
|
||||
test('calls expected method', async () => {
|
||||
const argv = process.argv
|
||||
process.argv = ['', '', 'dev']
|
||||
const defaultExport = {
|
||||
run: jest.fn().mockImplementation(() => Promise.resolve())
|
||||
const mockedCommand = {
|
||||
run: jest.fn().mockImplementation(() => Promise.resolve({}))
|
||||
}
|
||||
commands.dev.mockImplementationOnce(() => Promise.resolve({ default: defaultExport }))
|
||||
getCommand.mockImplementationOnce(() => Promise.resolve(mockedCommand))
|
||||
|
||||
await run()
|
||||
|
||||
expect(defaultExport.run).toHaveBeenCalled()
|
||||
process.argv = argv
|
||||
})
|
||||
|
||||
test('unknown calls default method', async () => {
|
||||
const argv = process.argv
|
||||
process.argv = ['', '', 'test']
|
||||
commands.dev.mockImplementationOnce(() => Promise.resolve())
|
||||
|
||||
await run()
|
||||
|
||||
expect(commands.dev).toHaveBeenCalled()
|
||||
process.argv = argv
|
||||
expect(mockedCommand.run).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test('sets NODE_ENV=development for dev', async () => {
|
||||
const nodeEnv = process.env.NODE_ENV
|
||||
process.env.NODE_ENV = ''
|
||||
commands.dev.mockImplementationOnce(() => Promise.resolve())
|
||||
|
||||
await run()
|
||||
getCommand.mockImplementationOnce(() => Promise.resolve({}))
|
||||
|
||||
await run(['dev'])
|
||||
expect(process.env.NODE_ENV).toBe('development')
|
||||
process.env.NODE_ENV = nodeEnv
|
||||
})
|
||||
|
||||
test('sets NODE_ENV=production for build', async () => {
|
||||
const argv = process.argv
|
||||
const nodeEnv = process.env.NODE_ENV
|
||||
process.argv = ['', '', 'build']
|
||||
process.env.NODE_ENV = ''
|
||||
commands.build.mockImplementationOnce(() => Promise.resolve())
|
||||
|
||||
await run()
|
||||
getCommand.mockImplementationOnce(() => Promise.resolve({}))
|
||||
|
||||
await run(['', '', 'build'])
|
||||
expect(process.env.NODE_ENV).toBe('production')
|
||||
process.argv = argv
|
||||
|
||||
process.env.NODE_ENV = nodeEnv
|
||||
})
|
||||
|
||||
test('catches fatal error', async () => {
|
||||
commands.dev.mockImplementationOnce(() => Promise.reject(new Error('Command Error')))
|
||||
|
||||
await run()
|
||||
|
||||
expect(consola.fatal).toHaveBeenCalledWith(new Error('Command Error'))
|
||||
})
|
||||
})
|
||||
|
@ -25,50 +25,38 @@ describe('cli/command', () => {
|
||||
})
|
||||
|
||||
test('parses args', () => {
|
||||
const cmd = new Command({ options: { ...common, ...server } })
|
||||
const argv = ['-c', 'test-file', '-s', '-p', '3001']
|
||||
const cmd = new Command({ options: { ...common, ...server } }, argv)
|
||||
|
||||
let args = ['-c', 'test-file', '-s', '-p', '3001']
|
||||
let argv = cmd.getArgv(args)
|
||||
expect(cmd.argv['config-file']).toBe(argv[1])
|
||||
expect(cmd.argv.spa).toBe(true)
|
||||
expect(cmd.argv.universal).toBe(false)
|
||||
expect(cmd.argv.port).toBe('3001')
|
||||
|
||||
expect(argv['config-file']).toBe(args[1])
|
||||
expect(argv.spa).toBe(true)
|
||||
expect(argv.universal).toBe(false)
|
||||
expect(argv.port).toBe('3001')
|
||||
|
||||
args = ['--no-build']
|
||||
argv = cmd.getArgv(args)
|
||||
|
||||
expect(argv.build).toBe(false)
|
||||
const cmd2 = new Command({ options: { ...common, ...server } }, ['--no-build'])
|
||||
expect(cmd2.argv.build).toBe(false)
|
||||
})
|
||||
|
||||
test('prints version automatically', () => {
|
||||
const cmd = new Command()
|
||||
test('prints version automatically', async () => {
|
||||
const cmd = new Command({}, ['--version'])
|
||||
cmd.showVersion = jest.fn()
|
||||
|
||||
const args = ['--version']
|
||||
cmd.getArgv(args)
|
||||
await cmd.run()
|
||||
|
||||
expect(cmd.showVersion).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
test('prints help automatically', () => {
|
||||
const cmd = new Command({ options: allOptions })
|
||||
test('prints help automatically', async () => {
|
||||
const cmd = new Command({ options: allOptions }, ['-h'])
|
||||
cmd.showHelp = jest.fn()
|
||||
|
||||
const args = ['-h']
|
||||
cmd.getArgv(args)
|
||||
await cmd.run()
|
||||
|
||||
expect(cmd.showHelp).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
test('returns nuxt config', async () => {
|
||||
const cmd = new Command({ options: allOptions })
|
||||
const cmd = new Command({ options: allOptions }, ['-c', 'test-file', '-a', '-p', '3001', '-q', '-H'])
|
||||
|
||||
const args = ['-c', 'test-file', '-a', '-p', '3001', '-q', '-H']
|
||||
const argv = cmd.getArgv(args)
|
||||
argv._ = ['.']
|
||||
|
||||
const options = await cmd.getNuxtConfig(argv, { testOption: true })
|
||||
const options = await cmd.getNuxtConfig({ testOption: true })
|
||||
|
||||
expect(options.testOption).toBe(true)
|
||||
expect(options.server.port).toBe(3001)
|
||||
@ -117,36 +105,19 @@ describe('cli/command', () => {
|
||||
expect(cmd._getHelp()).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('loads command from name', async () => {
|
||||
const cmd = await Command.load('dev')
|
||||
expect(cmd._getHelp()).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('show version prints to stdout and exits', () => {
|
||||
jest.spyOn(process.stdout, 'write').mockImplementation(() => {})
|
||||
jest.spyOn(process, 'exit').mockImplementationOnce(code => code)
|
||||
|
||||
const cmd = new Command()
|
||||
cmd.showVersion()
|
||||
|
||||
expect(process.stdout.write).toHaveBeenCalled()
|
||||
expect(process.exit).toHaveBeenCalled()
|
||||
|
||||
process.stdout.write.mockRestore()
|
||||
process.exit.mockRestore()
|
||||
})
|
||||
|
||||
test('show help prints to stdout and exits', () => {
|
||||
jest.spyOn(process.stdout, 'write').mockImplementation(() => {})
|
||||
jest.spyOn(process, 'exit').mockImplementationOnce(code => code)
|
||||
|
||||
const cmd = new Command()
|
||||
cmd.showHelp()
|
||||
|
||||
expect(process.stdout.write).toHaveBeenCalled()
|
||||
expect(process.exit).toHaveBeenCalled()
|
||||
|
||||
process.stdout.write.mockRestore()
|
||||
process.exit.mockRestore()
|
||||
})
|
||||
})
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { consola, mockGetNuxt, mockGetGenerator, NuxtCommand } from '../utils'
|
||||
import Command from '../../src/command'
|
||||
import { mockGetNuxt, mockGetGenerator, NuxtCommand } from '../utils'
|
||||
|
||||
describe('generate', () => {
|
||||
let generate
|
||||
@ -9,7 +8,6 @@ describe('generate', () => {
|
||||
jest.spyOn(process, 'exit').mockImplementation(code => code)
|
||||
})
|
||||
|
||||
afterAll(() => process.exit.mockRestore())
|
||||
afterEach(() => jest.resetAllMocks())
|
||||
|
||||
test('has run function', () => {
|
||||
@ -28,34 +26,21 @@ describe('generate', () => {
|
||||
|
||||
test('doesnt build with no-build', async () => {
|
||||
mockGetNuxt()
|
||||
const getArgv = Command.prototype.getArgv
|
||||
Command.prototype.getArgv = jest.fn().mockImplementationOnce(() => {
|
||||
return {
|
||||
'_': ['.'],
|
||||
rootDir: '.',
|
||||
'config-file': 'nuxt.config.js',
|
||||
build: false
|
||||
}
|
||||
})
|
||||
const generator = mockGetGenerator(Promise.resolve())
|
||||
|
||||
await NuxtCommand.from(generate).run()
|
||||
await NuxtCommand.run(generate, ['generate', '.', '--no-build'])
|
||||
|
||||
expect(generator).toHaveBeenCalled()
|
||||
expect(generator.mock.calls[0][0].build).toBe(false)
|
||||
Command.prototype.getArgv = getArgv
|
||||
})
|
||||
|
||||
test('build with devtools', async () => {
|
||||
mockGetNuxt()
|
||||
const generator = mockGetGenerator(Promise.resolve())
|
||||
|
||||
const cmd = NuxtCommand.from(generate)
|
||||
const args = ['generate', '.', '--devtools']
|
||||
const argv = cmd.getArgv(args)
|
||||
argv._ = ['.']
|
||||
const cmd = NuxtCommand.from(generate, ['generate', '.', '--devtools'])
|
||||
|
||||
const options = await cmd.getNuxtConfig(argv)
|
||||
const options = await cmd.getNuxtConfig()
|
||||
|
||||
await cmd.run()
|
||||
|
||||
@ -68,22 +53,12 @@ describe('generate', () => {
|
||||
mockGetNuxt()
|
||||
mockGetGenerator(Promise.resolve())
|
||||
|
||||
const cmd = NuxtCommand.from(generate)
|
||||
const args = ['generate', '.', '--m']
|
||||
const cmd = NuxtCommand.from(generate, ['generate', '.', '--m'])
|
||||
|
||||
const options = await cmd.getNuxtConfig(cmd.getArgv(args))
|
||||
const options = await cmd.getNuxtConfig()
|
||||
|
||||
await cmd.run()
|
||||
|
||||
expect(options.modern).toBe('client')
|
||||
})
|
||||
|
||||
test('catches error', async () => {
|
||||
mockGetNuxt()
|
||||
mockGetGenerator(Promise.reject(new Error('Generator Error')))
|
||||
|
||||
await NuxtCommand.from(generate).run()
|
||||
|
||||
expect(consola.fatal).toHaveBeenCalledWith(new Error('Generator Error'))
|
||||
})
|
||||
})
|
||||
|
65
packages/cli/test/unit/run.test.js
Normal file
65
packages/cli/test/unit/run.test.js
Normal file
@ -0,0 +1,65 @@
|
||||
import execa from 'execa'
|
||||
import run from '../../src/run'
|
||||
import getCommand from '../../src/commands'
|
||||
import NuxtCommand from '../../src/command'
|
||||
|
||||
jest.mock('execa')
|
||||
jest.mock('../../src/commands')
|
||||
jest.mock('../../src/command')
|
||||
|
||||
describe('run', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks()
|
||||
getCommand.mockImplementation(cmd => cmd === 'dev' ? ({ name: 'dev', run: jest.fn() }) : undefined)
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
test('nuxt aliases to nuxt dev', async () => {
|
||||
await run([])
|
||||
expect(getCommand).toHaveBeenCalledWith('dev')
|
||||
expect(NuxtCommand.run).toHaveBeenCalledWith(expect.anything(), [])
|
||||
})
|
||||
|
||||
test('nuxt --foo aliases to nuxt dev --foo', async () => {
|
||||
await run(['--foo'])
|
||||
expect(getCommand).toHaveBeenCalledWith('dev')
|
||||
expect(NuxtCommand.run).toHaveBeenCalledWith(expect.anything(), ['--foo'])
|
||||
})
|
||||
|
||||
test('nuxt <dir> aliases to nuxt dev <dir>', async () => {
|
||||
await run([__dirname])
|
||||
expect(getCommand).toHaveBeenCalledWith('dev')
|
||||
expect(NuxtCommand.run).toHaveBeenCalledWith(expect.anything(), [__dirname])
|
||||
})
|
||||
|
||||
test('external commands', async () => {
|
||||
await run(['custom', 'command', '--args'])
|
||||
|
||||
expect(execa).toHaveBeenCalledWith('nuxt-custom', ['command', '--args'], {
|
||||
stdout: process.stdout,
|
||||
stderr: process.stderr,
|
||||
stdin: process.stdin
|
||||
})
|
||||
})
|
||||
|
||||
test('throws error if external command not found', async () => {
|
||||
execa.mockImplementationOnce(() => {
|
||||
const e = new Error()
|
||||
e.code = 'ENOENT'
|
||||
throw e
|
||||
})
|
||||
|
||||
await expect(run(['custom', 'command', '--args']))
|
||||
.rejects.toBe('Command not found: nuxt-custom')
|
||||
})
|
||||
|
||||
test('throws error if external command failed', async () => {
|
||||
execa.mockImplementationOnce(() => { throw new Error('boo') })
|
||||
|
||||
await expect(run(['custom', 'command', '--args']))
|
||||
.rejects.toBe('Failed to run command `nuxt-custom`:\nError: boo')
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue
Block a user