mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-23 14:15:13 +00:00
refactor(cli): better consistency and easier unit testing (#4160)
This commit is contained in:
parent
9df5f49e07
commit
0669b68c91
@ -1,44 +1,3 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
const consola = require('consola')
|
require('../dist/cli.js').run()
|
||||||
const cli = require('../dist/cli.js')
|
|
||||||
|
|
||||||
// Global error handler
|
|
||||||
process.on('unhandledRejection', (err) => {
|
|
||||||
consola.error(err)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Exit process on fatal errors
|
|
||||||
consola.add({
|
|
||||||
log(logObj) {
|
|
||||||
if (logObj.type === 'fatal') {
|
|
||||||
process.stderr.write('Nuxt Fatal Error :(\n')
|
|
||||||
process.exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const defaultCommand = 'dev'
|
|
||||||
const commands = new Set([
|
|
||||||
defaultCommand,
|
|
||||||
'build',
|
|
||||||
'start',
|
|
||||||
'generate'
|
|
||||||
])
|
|
||||||
|
|
||||||
let cmd = process.argv[2]
|
|
||||||
|
|
||||||
if (commands.has(cmd)) {
|
|
||||||
process.argv.splice(2, 1)
|
|
||||||
} else {
|
|
||||||
cmd = defaultCommand
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply default NODE_ENV if not provided
|
|
||||||
if (!process.env.NODE_ENV) {
|
|
||||||
process.env.NODE_ENV = cmd === 'dev' ? 'development' : 'production'
|
|
||||||
}
|
|
||||||
|
|
||||||
cli[cmd]().then(m => m.default()).catch((error) => {
|
|
||||||
consola.fatal(error)
|
|
||||||
})
|
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"consola": "^1.4.4",
|
"consola": "^1.4.4",
|
||||||
"esm": "^3.0.84",
|
"esm": "^3.0.84",
|
||||||
"minimist": "^1.2.0"
|
"minimist": "^1.2.0",
|
||||||
|
"wrap-ansi": "^4.0.0"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
|
143
packages/cli/src/command.js
Normal file
143
packages/cli/src/command.js
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
import parseArgs from 'minimist'
|
||||||
|
import wrapAnsi from 'wrap-ansi'
|
||||||
|
import { name, version } from '../package.json'
|
||||||
|
import { loadNuxtConfig, indent, indentLines, foldLines } from './utils'
|
||||||
|
import { options as Options, defaultOptions as DefaultOptions } from './options'
|
||||||
|
import * as imports from './imports'
|
||||||
|
|
||||||
|
const startSpaces = 6
|
||||||
|
const optionSpaces = 2
|
||||||
|
const maxCharsPerLine = 80
|
||||||
|
|
||||||
|
export default class NuxtCommand {
|
||||||
|
constructor({ description, usage, options } = {}) {
|
||||||
|
this.description = description || ''
|
||||||
|
this.usage = usage || ''
|
||||||
|
this.options = Array.from(new Set((options || []).concat(DefaultOptions)))
|
||||||
|
}
|
||||||
|
|
||||||
|
_getMinimistOptions() {
|
||||||
|
const minimistOptions = {
|
||||||
|
alias: {},
|
||||||
|
boolean: [],
|
||||||
|
string: [],
|
||||||
|
default: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const name of this.options) {
|
||||||
|
const option = Options[name]
|
||||||
|
|
||||||
|
if (option.alias) {
|
||||||
|
minimistOptions.alias[option.alias] = name
|
||||||
|
}
|
||||||
|
if (option.type) {
|
||||||
|
minimistOptions[option.type].push(option.alias || name)
|
||||||
|
}
|
||||||
|
if (option.default) {
|
||||||
|
minimistOptions.default[option.alias || name] = option.default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return minimistOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
|
return argv
|
||||||
|
}
|
||||||
|
|
||||||
|
async getNuxtConfig(argv, extraOptions) {
|
||||||
|
const config = await loadNuxtConfig(argv)
|
||||||
|
const options = Object.assign(config, extraOptions || {})
|
||||||
|
|
||||||
|
for (const name of this.options) {
|
||||||
|
if (Options[name].handle) {
|
||||||
|
Options[name].handle(options, argv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
|
||||||
|
importCore() {
|
||||||
|
return imports.core()
|
||||||
|
}
|
||||||
|
|
||||||
|
importBuilder() {
|
||||||
|
return imports.builder()
|
||||||
|
}
|
||||||
|
|
||||||
|
importGenerator() {
|
||||||
|
return imports.generator()
|
||||||
|
}
|
||||||
|
|
||||||
|
async getNuxt(options) {
|
||||||
|
const { Nuxt } = await this.importCore()
|
||||||
|
return new Nuxt(options)
|
||||||
|
}
|
||||||
|
|
||||||
|
async getBuilder(nuxt) {
|
||||||
|
const { Builder } = await this.importBuilder()
|
||||||
|
return new Builder(nuxt)
|
||||||
|
}
|
||||||
|
|
||||||
|
async getGenerator(nuxt) {
|
||||||
|
const { Generator } = await this.importGenerator()
|
||||||
|
const { Builder } = await this.importBuilder()
|
||||||
|
return new Generator(nuxt, new Builder(nuxt))
|
||||||
|
}
|
||||||
|
|
||||||
|
_getHelp() {
|
||||||
|
const options = []
|
||||||
|
|
||||||
|
let maxOptionLength = 0
|
||||||
|
// For consistency Options determines order
|
||||||
|
for (const name in Options) {
|
||||||
|
const option = Options[name]
|
||||||
|
if (this.options.includes(name)) {
|
||||||
|
let optionHelp = '--'
|
||||||
|
optionHelp += option.type === 'boolean' && option.default ? 'no-' : ''
|
||||||
|
optionHelp += name
|
||||||
|
if (option.alias) {
|
||||||
|
optionHelp += `, -${option.alias}`
|
||||||
|
}
|
||||||
|
|
||||||
|
maxOptionLength = Math.max(maxOptionLength, optionHelp.length)
|
||||||
|
options.push([ optionHelp, option.description ])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const optionStr = options.map(([option, description]) => {
|
||||||
|
const line = option +
|
||||||
|
indent(maxOptionLength + optionSpaces - option.length) +
|
||||||
|
wrapAnsi(description, maxCharsPerLine - startSpaces - maxOptionLength - optionSpaces)
|
||||||
|
return indentLines(line, startSpaces + maxOptionLength + optionSpaces, startSpaces)
|
||||||
|
}).join('\n')
|
||||||
|
|
||||||
|
const description = foldLines(this.description, maxCharsPerLine, startSpaces)
|
||||||
|
|
||||||
|
return `
|
||||||
|
Description\n${description}
|
||||||
|
Usage
|
||||||
|
$ nuxt ${this.usage}
|
||||||
|
Options\n${optionStr}\n\n`
|
||||||
|
}
|
||||||
|
|
||||||
|
showVersion() {
|
||||||
|
process.stdout.write(`${name} v${version}\n`)
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
showHelp() {
|
||||||
|
process.stdout.write(this._getHelp())
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
|
}
|
@ -1,91 +1,46 @@
|
|||||||
import parseArgs from 'minimist'
|
|
||||||
import consola from 'consola'
|
import consola from 'consola'
|
||||||
|
import NuxtCommand from '../command'
|
||||||
import { loadNuxtConfig } from '../common/utils'
|
|
||||||
|
|
||||||
export default async function build() {
|
export default async function build() {
|
||||||
const { Nuxt } = await import('@nuxt/core')
|
const nuxtCmd = new NuxtCommand({
|
||||||
const { Builder } = await import('@nuxt/builder')
|
description: 'Compiles the application for production deployment',
|
||||||
const { Generator } = await import('@nuxt/generator')
|
usage: 'build <dir>',
|
||||||
|
options: [ 'analyze', 'quiet' ]
|
||||||
const argv = parseArgs(process.argv.slice(2), {
|
|
||||||
alias: {
|
|
||||||
h: 'help',
|
|
||||||
c: 'config-file',
|
|
||||||
a: 'analyze',
|
|
||||||
s: 'spa',
|
|
||||||
u: 'universal',
|
|
||||||
q: 'quiet'
|
|
||||||
},
|
|
||||||
boolean: ['h', 'a', 's', 'u', 'q'],
|
|
||||||
string: ['c'],
|
|
||||||
default: {
|
|
||||||
c: 'nuxt.config.js'
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if (argv.help) {
|
const argv = nuxtCmd.getArgv()
|
||||||
process.stderr.write(`
|
|
||||||
Description
|
|
||||||
Compiles the application for production deployment
|
|
||||||
Usage
|
|
||||||
$ nuxt build <dir>
|
|
||||||
Options
|
|
||||||
--analyze, -a Launch webpack-bundle-analyzer to optimize your bundles.
|
|
||||||
--spa, -s Launch in SPA mode
|
|
||||||
--universal, -u Launch in Universal mode (default)
|
|
||||||
--no-generate Don't generate static version for SPA mode (useful for nuxt start)
|
|
||||||
--config-file, -c Path to Nuxt.js config file (default: nuxt.config.js)
|
|
||||||
--quiet, -q Disable output except for errors
|
|
||||||
--help, -h Displays this message
|
|
||||||
`)
|
|
||||||
process.exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
const options = await loadNuxtConfig(argv)
|
// Create production build when calling `nuxt build` (dev: false)
|
||||||
|
const nuxt = await nuxtCmd.getNuxt(
|
||||||
// Create production build when calling `nuxt build`
|
await nuxtCmd.getNuxtConfig(argv, { dev: false })
|
||||||
options.dev = false
|
)
|
||||||
|
|
||||||
// Analyze option
|
|
||||||
options.build = options.build || {}
|
|
||||||
if (argv.analyze && typeof options.build.analyze !== 'object') {
|
|
||||||
options.build.analyze = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Silence output when using --quiet
|
|
||||||
if (argv.quiet) {
|
|
||||||
options.build.quiet = !!argv.quiet
|
|
||||||
}
|
|
||||||
|
|
||||||
const nuxt = new Nuxt(options)
|
|
||||||
const builder = new Builder(nuxt)
|
|
||||||
|
|
||||||
// Setup hooks
|
// Setup hooks
|
||||||
nuxt.hook('error', err => consola.fatal(err))
|
nuxt.hook('error', err => consola.fatal(err))
|
||||||
|
|
||||||
// Close function
|
let builderOrGenerator
|
||||||
const close = () => {
|
if (nuxt.options.mode !== 'spa' || argv.generate === false) {
|
||||||
// In analyze mode wait for plugin
|
|
||||||
// emitting assets and opening browser
|
|
||||||
if (options.build.analyze === true || typeof options.build.analyze === 'object') {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
process.exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.mode !== 'spa' || argv.generate === false) {
|
|
||||||
// Build only
|
// Build only
|
||||||
return builder
|
builderOrGenerator = (await nuxtCmd.getBuilder(nuxt)).build()
|
||||||
.build()
|
|
||||||
.then(close)
|
|
||||||
.catch(err => consola.fatal(err))
|
|
||||||
} else {
|
} else {
|
||||||
// Build + Generate for static deployment
|
// Build + Generate for static deployment
|
||||||
return new Generator(nuxt, builder)
|
builderOrGenerator = (await nuxtCmd.getGenerator(nuxt)).generate({
|
||||||
.generate({ build: true })
|
build: true
|
||||||
.then(close)
|
})
|
||||||
.catch(err => consola.fatal(err))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
}
|
}
|
||||||
|
@ -1,71 +1,29 @@
|
|||||||
import parseArgs from 'minimist'
|
|
||||||
import consola from 'consola'
|
import consola from 'consola'
|
||||||
import { loadNuxtConfig, runAsyncScript } from '../common/utils'
|
import NuxtCommand from '../command'
|
||||||
|
|
||||||
export default async function dev() {
|
export default async function dev() {
|
||||||
const { Nuxt } = await import('@nuxt/core')
|
const nuxtCmd = new NuxtCommand({
|
||||||
const { Builder } = await import('@nuxt/builder')
|
description: 'Start the application in development mode (e.g. hot-code reloading, error reporting)',
|
||||||
|
usage: 'dev <dir> -p <port number> -H <hostname>',
|
||||||
const argv = parseArgs(process.argv.slice(2), {
|
options: [ 'hostname', 'port' ]
|
||||||
alias: {
|
|
||||||
h: 'help',
|
|
||||||
H: 'hostname',
|
|
||||||
p: 'port',
|
|
||||||
c: 'config-file',
|
|
||||||
s: 'spa',
|
|
||||||
u: 'universal',
|
|
||||||
v: 'version'
|
|
||||||
},
|
|
||||||
boolean: ['h', 's', 'u', 'v'],
|
|
||||||
string: ['H', 'c'],
|
|
||||||
default: {
|
|
||||||
c: 'nuxt.config.js'
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if (argv.version) {
|
const argv = nuxtCmd.getArgv()
|
||||||
process.stderr.write('TODO' + '\n')
|
|
||||||
process.exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argv.hostname === '') {
|
|
||||||
consola.fatal('Provided hostname argument has no value')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argv.help) {
|
|
||||||
process.stderr.write(`
|
|
||||||
Description
|
|
||||||
Starts the application in development mode (hot-code reloading, error
|
|
||||||
reporting, etc)
|
|
||||||
Usage
|
|
||||||
$ nuxt dev <dir> -p <port number> -H <hostname>
|
|
||||||
Options
|
|
||||||
--port, -p A port number on which to start the application
|
|
||||||
--hostname, -H Hostname on which to start the application
|
|
||||||
--spa Launch in SPA mode
|
|
||||||
--universal Launch in Universal mode (default)
|
|
||||||
--config-file, -c Path to Nuxt.js config file (default: nuxt.config.js)
|
|
||||||
--help, -h Displays this message
|
|
||||||
`)
|
|
||||||
process.exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
const config = async () => {
|
|
||||||
// Force development mode for add hot reloading and watching changes
|
|
||||||
return Object.assign(await loadNuxtConfig(argv), { dev: true })
|
|
||||||
}
|
|
||||||
|
|
||||||
const errorHandler = (err, instance) => {
|
const errorHandler = (err, instance) => {
|
||||||
instance && instance.builder.watchServer()
|
instance && instance.builder.watchServer()
|
||||||
consola.error(err)
|
consola.error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { Nuxt } = await nuxtCmd.importCore()
|
||||||
|
const { Builder } = await nuxtCmd.importBuilder()
|
||||||
|
|
||||||
// Start dev
|
// Start dev
|
||||||
async function startDev(oldInstance) {
|
async function startDev(oldInstance) {
|
||||||
let nuxt, builder
|
let nuxt, builder
|
||||||
|
|
||||||
try {
|
try {
|
||||||
nuxt = new Nuxt(await config())
|
nuxt = new Nuxt(await nuxtCmd.getNuxtConfig(argv, { dev: true }))
|
||||||
builder = new Builder(nuxt)
|
builder = new Builder(nuxt)
|
||||||
nuxt.hook('watch:fileChanged', async (builder, fname) => {
|
nuxt.hook('watch:fileChanged', async (builder, fname) => {
|
||||||
consola.debug(`[${fname}] changed, Rebuilding the app...`)
|
consola.debug(`[${fname}] changed, Rebuilding the app...`)
|
||||||
@ -81,10 +39,10 @@ export default async function dev() {
|
|||||||
.then(() => oldInstance && oldInstance.builder.unwatch())
|
.then(() => oldInstance && oldInstance.builder.unwatch())
|
||||||
// Start build
|
// Start build
|
||||||
.then(() => builder.build())
|
.then(() => builder.build())
|
||||||
// Close old nuxt no mater if build successfully
|
// Close old nuxt no matter if build successfully
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
oldInstance && oldInstance.nuxt.close()
|
oldInstance && oldInstance.nuxt.close()
|
||||||
// Jump to eventHandler
|
// Jump to errorHandler
|
||||||
throw err
|
throw err
|
||||||
})
|
})
|
||||||
.then(() => oldInstance && oldInstance.nuxt.close())
|
.then(() => oldInstance && oldInstance.nuxt.close())
|
||||||
@ -98,5 +56,5 @@ export default async function dev() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
await runAsyncScript(startDev)
|
await startDev()
|
||||||
}
|
}
|
||||||
|
@ -1,61 +1,25 @@
|
|||||||
import parseArgs from 'minimist'
|
|
||||||
import consola from 'consola'
|
import consola from 'consola'
|
||||||
|
import NuxtCommand from '../command'
|
||||||
import { loadNuxtConfig } from '../common/utils'
|
|
||||||
|
|
||||||
export default async function generate() {
|
export default async function generate() {
|
||||||
const { Nuxt } = await import('@nuxt/core')
|
const nuxtCmd = new NuxtCommand({
|
||||||
const { Builder } = await import('@nuxt/builder')
|
description: 'Generate a static web application (server-rendered)',
|
||||||
const { Generator } = await import('@nuxt/generator')
|
usage: 'generate <dir>',
|
||||||
|
options: [ 'build' ]
|
||||||
const argv = parseArgs(process.argv.slice(2), {
|
|
||||||
alias: {
|
|
||||||
h: 'help',
|
|
||||||
c: 'config-file',
|
|
||||||
s: 'spa',
|
|
||||||
u: 'universal'
|
|
||||||
},
|
|
||||||
boolean: ['h', 's', 'u', 'build'],
|
|
||||||
string: ['c'],
|
|
||||||
default: {
|
|
||||||
c: 'nuxt.config.js',
|
|
||||||
build: true
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if (argv.help) {
|
const argv = nuxtCmd.getArgv()
|
||||||
process.stderr.write(`
|
|
||||||
Description
|
|
||||||
Generate a static web application (server-rendered)
|
|
||||||
Usage
|
|
||||||
$ nuxt generate <dir>
|
|
||||||
Options
|
|
||||||
--spa Launch in SPA mode
|
|
||||||
--universal Launch in Universal mode (default)
|
|
||||||
--config-file, -c Path to Nuxt.js config file (default: nuxt.config.js)
|
|
||||||
--help, -h Displays this message
|
|
||||||
--no-build Just run generate for faster builds when just dynamic routes changed. Nuxt build is needed before this command.
|
|
||||||
`)
|
|
||||||
process.exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
const options = await loadNuxtConfig(argv)
|
const generator = await nuxtCmd.getGenerator(
|
||||||
|
await nuxtCmd.getNuxt(
|
||||||
|
await nuxtCmd.getNuxtConfig(argv, { dev: false })
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
options.dev = false // Force production mode (no webpack middleware called)
|
return generator.generate({
|
||||||
|
|
||||||
const nuxt = new Nuxt(options)
|
|
||||||
const builder = new Builder(nuxt)
|
|
||||||
const generator = new Generator(nuxt, builder)
|
|
||||||
|
|
||||||
const generateOptions = {
|
|
||||||
init: true,
|
init: true,
|
||||||
build: argv.build
|
build: argv.build
|
||||||
}
|
}).then(() => {
|
||||||
|
process.exit(0)
|
||||||
return generator
|
}).catch(err => consola.fatal(err))
|
||||||
.generate(generateOptions)
|
|
||||||
.then(() => {
|
|
||||||
process.exit(0)
|
|
||||||
})
|
|
||||||
.catch(err => consola.fatal(err))
|
|
||||||
}
|
}
|
||||||
|
4
packages/cli/src/commands/index.js
Normal file
4
packages/cli/src/commands/index.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export const start = () => import('./start')
|
||||||
|
export const dev = () => import('./dev')
|
||||||
|
export const build = () => import('./build')
|
||||||
|
export const generate = () => import('./generate')
|
@ -1,59 +1,21 @@
|
|||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import parseArgs from 'minimist'
|
|
||||||
import consola from 'consola'
|
import consola from 'consola'
|
||||||
|
import NuxtCommand from '../command'
|
||||||
import { loadNuxtConfig } from '../common/utils'
|
|
||||||
|
|
||||||
export default async function start() {
|
export default async function start() {
|
||||||
const { Nuxt } = await import('@nuxt/core')
|
const nuxtCmd = new NuxtCommand({
|
||||||
|
description: 'Start the application in production mode (the application should be compiled with `nuxt build` first)',
|
||||||
const argv = parseArgs(process.argv.slice(2), {
|
usage: 'start <dir> -p <port number> -H <hostname>',
|
||||||
alias: {
|
options: [ 'hostname', 'port', 'unix-socket' ]
|
||||||
h: 'help',
|
|
||||||
H: 'hostname',
|
|
||||||
p: 'port',
|
|
||||||
n: 'unix-socket',
|
|
||||||
c: 'config-file',
|
|
||||||
s: 'spa',
|
|
||||||
u: 'universal'
|
|
||||||
},
|
|
||||||
boolean: ['h', 's', 'u'],
|
|
||||||
string: ['H', 'c', 'n'],
|
|
||||||
default: {
|
|
||||||
c: 'nuxt.config.js'
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if (argv.hostname === '') {
|
const argv = nuxtCmd.getArgv()
|
||||||
consola.fatal('Provided hostname argument has no value')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argv.help) {
|
// Create production build when calling `nuxt build`
|
||||||
process.stderr.write(`
|
const nuxt = await nuxtCmd.getNuxt(
|
||||||
Description
|
await nuxtCmd.getNuxtConfig(argv, { dev: false })
|
||||||
Starts the application in production mode.
|
)
|
||||||
The application should be compiled with \`nuxt build\` first.
|
|
||||||
Usage
|
|
||||||
$ nuxt start <dir> -p <port number> -H <hostname>
|
|
||||||
Options
|
|
||||||
--port, -p A 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
|
|
||||||
--spa Launch in SPA mode
|
|
||||||
--universal Launch in Universal mode (default)
|
|
||||||
--config-file, -c Path to Nuxt.js config file (default: nuxt.config.js)
|
|
||||||
--help, -h Displays this message
|
|
||||||
`)
|
|
||||||
process.exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
const options = await loadNuxtConfig(argv)
|
|
||||||
|
|
||||||
// Force production mode (no webpack middleware called)
|
|
||||||
options.dev = false
|
|
||||||
|
|
||||||
const nuxt = new Nuxt(options)
|
|
||||||
|
|
||||||
// Setup hooks
|
// Setup hooks
|
||||||
nuxt.hook('error', err => consola.fatal(err))
|
nuxt.hook('error', err => consola.fatal(err))
|
||||||
|
3
packages/cli/src/imports.js
Normal file
3
packages/cli/src/imports.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export const builder = () => import('@nuxt/builder')
|
||||||
|
export const generator = () => import('@nuxt/generator')
|
||||||
|
export const core = () => import('@nuxt/core')
|
@ -1,5 +1,10 @@
|
|||||||
export const start = () => import('./commands/start')
|
import * as _commands from './commands'
|
||||||
export const dev = () => import('./commands/dev')
|
import * as _imports from './imports'
|
||||||
|
|
||||||
export const build = () => import('./commands/build')
|
export const commands = _commands
|
||||||
export const generate = () => import('./commands/generate')
|
export const imports = _imports
|
||||||
|
|
||||||
|
export { default as setup } from './setup'
|
||||||
|
export { default as run } from './run'
|
||||||
|
|
||||||
|
export { loadNuxtConfig } from './utils'
|
||||||
|
101
packages/cli/src/options.js
Normal file
101
packages/cli/src/options.js
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
import consola from 'consola'
|
||||||
|
|
||||||
|
export const defaultOptions = [
|
||||||
|
'spa',
|
||||||
|
'universal',
|
||||||
|
'config-file',
|
||||||
|
'version',
|
||||||
|
'help'
|
||||||
|
]
|
||||||
|
|
||||||
|
export const options = {
|
||||||
|
port: {
|
||||||
|
alias: 'p',
|
||||||
|
type: 'string',
|
||||||
|
description: 'Port number on which to start the application',
|
||||||
|
handle(options, argv) {
|
||||||
|
if (argv.port) {
|
||||||
|
options.server.port = +argv.port
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hostname: {
|
||||||
|
alias: 'H',
|
||||||
|
type: 'string',
|
||||||
|
description: 'Hostname on which to start the application',
|
||||||
|
handle(options, argv) {
|
||||||
|
if (argv.hostname === '') {
|
||||||
|
consola.fatal('Provided hostname argument has no value')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'unix-socket': {
|
||||||
|
alias: 'n',
|
||||||
|
type: 'string',
|
||||||
|
description: 'Path to a UNIX socket'
|
||||||
|
},
|
||||||
|
analyze: {
|
||||||
|
alias: 'a',
|
||||||
|
type: 'boolean',
|
||||||
|
description: 'Launch webpack-bundle-analyzer to optimize your bundles',
|
||||||
|
handle(options, argv) {
|
||||||
|
// Analyze option
|
||||||
|
options.build = options.build || {}
|
||||||
|
if (argv.analyze && typeof options.build.analyze !== 'object') {
|
||||||
|
options.build.analyze = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
type: 'boolean',
|
||||||
|
default: true,
|
||||||
|
description: 'Only generate pages for dynamic routes. Nuxt has to be built once before using this option'
|
||||||
|
},
|
||||||
|
generate: {
|
||||||
|
type: 'boolean',
|
||||||
|
default: true,
|
||||||
|
description: 'Don\'t generate static version for SPA mode (useful for nuxt start)'
|
||||||
|
},
|
||||||
|
spa: {
|
||||||
|
alias: 's',
|
||||||
|
type: 'boolean',
|
||||||
|
description: 'Launch in SPA mode'
|
||||||
|
},
|
||||||
|
universal: {
|
||||||
|
alias: 'u',
|
||||||
|
type: 'boolean',
|
||||||
|
description: 'Launch in Universal mode (default)'
|
||||||
|
},
|
||||||
|
'config-file': {
|
||||||
|
alias: 'c',
|
||||||
|
type: 'string',
|
||||||
|
default: 'nuxt.config.js',
|
||||||
|
description: 'Path to Nuxt.js config file (default: nuxt.config.js)'
|
||||||
|
},
|
||||||
|
quiet: {
|
||||||
|
alias: 'q',
|
||||||
|
type: 'boolean',
|
||||||
|
description: 'Disable output except for errors',
|
||||||
|
handle(options, argv) {
|
||||||
|
// Silence output when using --quiet
|
||||||
|
options.build = options.build || {}
|
||||||
|
if (argv.quiet) {
|
||||||
|
options.build.quiet = !!argv.quiet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
verbose: {
|
||||||
|
alias: 'v',
|
||||||
|
type: 'boolean',
|
||||||
|
description: 'Show debug information'
|
||||||
|
},
|
||||||
|
version: {
|
||||||
|
type: 'boolean',
|
||||||
|
description: 'Display the Nuxt version'
|
||||||
|
},
|
||||||
|
help: {
|
||||||
|
alias: 'h',
|
||||||
|
type: 'boolean',
|
||||||
|
description: 'Display this message'
|
||||||
|
}
|
||||||
|
}
|
33
packages/cli/src/run.js
Normal file
33
packages/cli/src/run.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import consola from 'consola'
|
||||||
|
import * as commands from './commands'
|
||||||
|
import setup from './setup'
|
||||||
|
|
||||||
|
export default function run() {
|
||||||
|
const defaultCommand = 'dev'
|
||||||
|
|
||||||
|
const cmds = new Set([
|
||||||
|
defaultCommand,
|
||||||
|
'build',
|
||||||
|
'start',
|
||||||
|
'generate'
|
||||||
|
])
|
||||||
|
|
||||||
|
let cmd = process.argv[2]
|
||||||
|
|
||||||
|
if (cmds.has(cmd)) {
|
||||||
|
process.argv.splice(2, 1)
|
||||||
|
} else {
|
||||||
|
cmd = defaultCommand
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup runtime
|
||||||
|
setup({
|
||||||
|
dev: cmd === 'dev'
|
||||||
|
})
|
||||||
|
|
||||||
|
return commands[cmd]() // eslint-disable-line import/namespace
|
||||||
|
.then(m => m.default())
|
||||||
|
.catch((error) => {
|
||||||
|
consola.fatal(error)
|
||||||
|
})
|
||||||
|
}
|
32
packages/cli/src/setup.js
Normal file
32
packages/cli/src/setup.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import consola from 'consola'
|
||||||
|
|
||||||
|
let _setup = false
|
||||||
|
|
||||||
|
export default function setup({ dev }) {
|
||||||
|
// Apply default NODE_ENV if not provided
|
||||||
|
if (!process.env.NODE_ENV) {
|
||||||
|
process.env.NODE_ENV = dev ? 'development' : 'production'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_setup) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_setup = true
|
||||||
|
|
||||||
|
// Global error handler
|
||||||
|
/* istanbul ignore next */
|
||||||
|
process.on('unhandledRejection', (err) => {
|
||||||
|
consola.error(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Exit process on fatal errors
|
||||||
|
/* istanbul ignore next */
|
||||||
|
consola.add({
|
||||||
|
log(logObj) {
|
||||||
|
if (logObj.type === 'fatal') {
|
||||||
|
process.stderr.write('Nuxt Fatal Error :(\n')
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
@ -2,6 +2,7 @@ import path from 'path'
|
|||||||
import { existsSync } from 'fs'
|
import { existsSync } from 'fs'
|
||||||
import consola from 'consola'
|
import consola from 'consola'
|
||||||
import esm from 'esm'
|
import esm from 'esm'
|
||||||
|
import wrapAnsi from 'wrap-ansi'
|
||||||
|
|
||||||
const _require = esm(module, {
|
const _require = esm(module, {
|
||||||
cache: false,
|
cache: false,
|
||||||
@ -33,15 +34,6 @@ const getLatestHost = (argv) => {
|
|||||||
return { port, host, socket }
|
return { port, host, socket }
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function runAsyncScript(fn) {
|
|
||||||
try {
|
|
||||||
await fn()
|
|
||||||
} catch (err) {
|
|
||||||
consola.error(err)
|
|
||||||
consola.fatal(`Failed to run async Nuxt script!`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function loadNuxtConfig(argv) {
|
export async function loadNuxtConfig(argv) {
|
||||||
const rootDir = getRootDir(argv)
|
const rootDir = getRootDir(argv)
|
||||||
const nuxtConfigFile = getNuxtConfigFile(argv)
|
const nuxtConfigFile = getNuxtConfigFile(argv)
|
||||||
@ -50,16 +42,17 @@ export async function loadNuxtConfig(argv) {
|
|||||||
|
|
||||||
if (existsSync(nuxtConfigFile)) {
|
if (existsSync(nuxtConfigFile)) {
|
||||||
delete require.cache[nuxtConfigFile]
|
delete require.cache[nuxtConfigFile]
|
||||||
options = _require(nuxtConfigFile)
|
options = _require(nuxtConfigFile) || {}
|
||||||
if (!options) {
|
|
||||||
options = {}
|
|
||||||
}
|
|
||||||
if (options.default) {
|
if (options.default) {
|
||||||
options = options.default
|
options = options.default
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof options === 'function') {
|
if (typeof options === 'function') {
|
||||||
try {
|
try {
|
||||||
options = await options()
|
options = await options()
|
||||||
|
if (options.default) {
|
||||||
|
options = options.default
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
consola.error(error)
|
consola.error(error)
|
||||||
consola.fatal('Error while fetching async configuration')
|
consola.fatal('Error while fetching async configuration')
|
||||||
@ -68,7 +61,6 @@ export async function loadNuxtConfig(argv) {
|
|||||||
} else if (argv['config-file'] !== 'nuxt.config.js') {
|
} else if (argv['config-file'] !== 'nuxt.config.js') {
|
||||||
consola.fatal('Could not load config file: ' + argv['config-file'])
|
consola.fatal('Could not load config file: ' + argv['config-file'])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof options.rootDir !== 'string') {
|
if (typeof options.rootDir !== 'string') {
|
||||||
options.rootDir = rootDir
|
options.rootDir = rootDir
|
||||||
}
|
}
|
||||||
@ -81,9 +73,33 @@ export async function loadNuxtConfig(argv) {
|
|||||||
if (!options.server) {
|
if (!options.server) {
|
||||||
options.server = {}
|
options.server = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { port, host, socket } = getLatestHost(argv)
|
const { port, host, socket } = getLatestHost(argv)
|
||||||
options.server.port = port || options.server.port || 3000
|
options.server.port = port || options.server.port || 3000
|
||||||
options.server.host = host || options.server.host || 'localhost'
|
options.server.host = host || options.server.host || 'localhost'
|
||||||
options.server.socket = socket || options.server.socket
|
options.server.socket = socket || options.server.socket
|
||||||
|
|
||||||
return options
|
return options
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function indent(count, chr = ' ') {
|
||||||
|
return chr.repeat(count)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function indentLines(string, spaces, firstLineSpaces) {
|
||||||
|
const lines = Array.isArray(string) ? string : string.split('\n')
|
||||||
|
let s = ''
|
||||||
|
if (lines.length) {
|
||||||
|
const i0 = indent(firstLineSpaces === undefined ? spaces : firstLineSpaces)
|
||||||
|
s = i0 + lines.shift()
|
||||||
|
}
|
||||||
|
if (lines.length) {
|
||||||
|
const i = indent(spaces)
|
||||||
|
s += '\n' + lines.map(l => i + l.trim()).join('\n')
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
export function foldLines(string, maxCharsPerLine, spaces, firstLineSpaces) {
|
||||||
|
return indentLines(wrapAnsi(string, maxCharsPerLine), spaces, firstLineSpaces)
|
||||||
|
}
|
9
packages/cli/test/fixtures/nuxt.async-config.js
vendored
Normal file
9
packages/cli/test/fixtures/nuxt.async-config.js
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { resolve } from 'path'
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
// delete cache is needed because otherwise Jest will return the same
|
||||||
|
// object reference as the previous test and then mode will not be
|
||||||
|
// set correctly. jest.resetModules doesnt work for some reason
|
||||||
|
delete require.cache[resolve(__dirname, 'nuxt.config.js')]
|
||||||
|
return import('./nuxt.config.js')
|
||||||
|
}
|
1
packages/cli/test/fixtures/nuxt.async-error.js
vendored
Normal file
1
packages/cli/test/fixtures/nuxt.async-error.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
export default () => Promise.reject(new Error('Async Config Error'))
|
10
packages/cli/test/fixtures/nuxt.config.js
vendored
Normal file
10
packages/cli/test/fixtures/nuxt.config.js
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
export default {
|
||||||
|
testOption: true,
|
||||||
|
rootDir: '/some/path',
|
||||||
|
mode: 'supercharged',
|
||||||
|
server: {
|
||||||
|
host: 'nuxt-host',
|
||||||
|
port: 3001,
|
||||||
|
socket: '/var/run/nuxt.sock'
|
||||||
|
}
|
||||||
|
}
|
62
packages/cli/test/unit/build.test.js
Normal file
62
packages/cli/test/unit/build.test.js
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import { consola, mockGetNuxt, mockGetBuilder, mockGetGenerator } from '../utils'
|
||||||
|
|
||||||
|
describe('build', () => {
|
||||||
|
let build
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
build = await import('../../src/commands/build')
|
||||||
|
build = build.default
|
||||||
|
|
||||||
|
jest.spyOn(process, 'exit').mockImplementation(code => code)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
process.exit.mockRestore()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.resetAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('is function', () => {
|
||||||
|
expect(typeof build).toBe('function')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('builds on universal mode', async () => {
|
||||||
|
mockGetNuxt({
|
||||||
|
mode: 'universal',
|
||||||
|
build: {
|
||||||
|
analyze: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const builder = mockGetBuilder(Promise.resolve())
|
||||||
|
|
||||||
|
await build()
|
||||||
|
|
||||||
|
expect(builder).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('generates on spa mode', async () => {
|
||||||
|
mockGetNuxt({
|
||||||
|
mode: 'spa',
|
||||||
|
build: {
|
||||||
|
analyze: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const generate = mockGetGenerator(Promise.resolve())
|
||||||
|
|
||||||
|
await build()
|
||||||
|
|
||||||
|
expect(generate).toHaveBeenCalled()
|
||||||
|
expect(process.exit).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('catches error', async () => {
|
||||||
|
mockGetNuxt({ mode: 'universal' })
|
||||||
|
mockGetBuilder(Promise.reject(new Error('Builder Error')))
|
||||||
|
|
||||||
|
await build()
|
||||||
|
|
||||||
|
expect(consola.fatal).toHaveBeenCalledWith(new Error('Builder Error'))
|
||||||
|
})
|
||||||
|
})
|
95
packages/cli/test/unit/cli.test.js
Normal file
95
packages/cli/test/unit/cli.test.js
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
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)
|
||||||
|
|
||||||
|
consola.add = jest.fn()
|
||||||
|
|
||||||
|
const mockCommand = (cmd, p) => {
|
||||||
|
commands[cmd] = jest.fn().mockImplementationOnce(() => { // eslint-disable-line import/namespace
|
||||||
|
return Promise.resolve({
|
||||||
|
default: () => {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
expect(commands[cmd]).toBeDefined() // eslint-disable-line import/namespace
|
||||||
|
expect(typeof commands[cmd]).toBe('function') // eslint-disable-line import/namespace
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
test('calls expected method', async () => {
|
||||||
|
const argv = process.argv
|
||||||
|
process.argv = ['', '', 'dev']
|
||||||
|
mockCommand('dev', Promise.resolve())
|
||||||
|
|
||||||
|
await run()
|
||||||
|
|
||||||
|
expect(commands.dev).toHaveBeenCalled()
|
||||||
|
process.argv = argv
|
||||||
|
})
|
||||||
|
|
||||||
|
test('unknown calls default method', async () => {
|
||||||
|
const argv = process.argv
|
||||||
|
process.argv = ['', '', 'test']
|
||||||
|
mockCommand('dev', Promise.resolve())
|
||||||
|
|
||||||
|
await run()
|
||||||
|
|
||||||
|
expect(commands.dev).toHaveBeenCalled()
|
||||||
|
process.argv = argv
|
||||||
|
})
|
||||||
|
|
||||||
|
test('sets NODE_ENV=development for dev', async () => {
|
||||||
|
const nodeEnv = process.env.NODE_ENV
|
||||||
|
process.env.NODE_ENV = ''
|
||||||
|
mockCommand('dev', Promise.resolve())
|
||||||
|
|
||||||
|
await run()
|
||||||
|
|
||||||
|
expect(process.env.NODE_ENV).toBe('development')
|
||||||
|
process.env.NODE_ENV = nodeEnv
|
||||||
|
})
|
||||||
|
|
||||||
|
test('sets ODE_ENV=production for build', async () => {
|
||||||
|
const argv = process.argv
|
||||||
|
const nodeEnv = process.env.NODE_ENV
|
||||||
|
process.argv = ['', '', 'build']
|
||||||
|
process.env.NODE_ENV = ''
|
||||||
|
mockCommand('build', Promise.resolve())
|
||||||
|
|
||||||
|
await run()
|
||||||
|
|
||||||
|
expect(process.env.NODE_ENV).toBe('production')
|
||||||
|
process.argv = argv
|
||||||
|
process.env.NODE_ENV = nodeEnv
|
||||||
|
})
|
||||||
|
|
||||||
|
test('catches fatal error', async () => {
|
||||||
|
mockCommand('dev', Promise.reject(new Error('Command Error')))
|
||||||
|
|
||||||
|
await run()
|
||||||
|
|
||||||
|
expect(consola.fatal).toHaveBeenCalledWith(new Error('Command Error'))
|
||||||
|
})
|
||||||
|
})
|
169
packages/cli/test/unit/command.test.js
Normal file
169
packages/cli/test/unit/command.test.js
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
import { consola } from '../utils'
|
||||||
|
import Command from '../../src/command'
|
||||||
|
import { options as Options } from '../../src/options'
|
||||||
|
|
||||||
|
jest.mock('@nuxt/core')
|
||||||
|
jest.mock('@nuxt/builder')
|
||||||
|
jest.mock('@nuxt/generator')
|
||||||
|
|
||||||
|
describe('cli/command', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.restoreAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('adds default options', () => {
|
||||||
|
const cmd = new Command()
|
||||||
|
|
||||||
|
expect(cmd.options.length).not.toBe(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('builds minimist options', () => {
|
||||||
|
const cmd = new Command({
|
||||||
|
options: Object.keys(Options)
|
||||||
|
})
|
||||||
|
|
||||||
|
const minimistOptions = cmd._getMinimistOptions()
|
||||||
|
|
||||||
|
expect(minimistOptions.string.length).toBe(4)
|
||||||
|
expect(minimistOptions.boolean.length).toBe(9)
|
||||||
|
expect(minimistOptions.alias.c).toBe('config-file')
|
||||||
|
expect(minimistOptions.default.c).toBe(Options['config-file'].default)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('parses args', () => {
|
||||||
|
const cmd = new Command({
|
||||||
|
options: Object.keys(Options)
|
||||||
|
})
|
||||||
|
|
||||||
|
let args = ['-c', 'test-file', '-s', '-p', '3001']
|
||||||
|
let argv = cmd.getArgv(args)
|
||||||
|
|
||||||
|
expect(argv['config-file']).toBe(args[1])
|
||||||
|
expect(argv.spa).toBe(true)
|
||||||
|
expect(argv.universal).toBe(false)
|
||||||
|
expect(argv.build).toBe(true)
|
||||||
|
expect(argv.port).toBe('3001')
|
||||||
|
|
||||||
|
args = ['--no-build']
|
||||||
|
argv = cmd.getArgv(args)
|
||||||
|
|
||||||
|
expect(argv.build).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('prints version automatically', () => {
|
||||||
|
const cmd = new Command()
|
||||||
|
cmd.showVersion = jest.fn()
|
||||||
|
|
||||||
|
const args = ['--version']
|
||||||
|
cmd.getArgv(args)
|
||||||
|
|
||||||
|
expect(cmd.showVersion).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('prints help automatically', () => {
|
||||||
|
const cmd = new Command()
|
||||||
|
cmd.showHelp = jest.fn()
|
||||||
|
|
||||||
|
const args = ['-h']
|
||||||
|
cmd.getArgv(args)
|
||||||
|
|
||||||
|
expect(cmd.showHelp).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('returns nuxt config', async () => {
|
||||||
|
const cmd = new Command({
|
||||||
|
options: Object.keys(Options)
|
||||||
|
})
|
||||||
|
|
||||||
|
const args = ['-c', 'test-file', '-a', '-p', '3001', '-q', '-H']
|
||||||
|
const argv = cmd.getArgv(args)
|
||||||
|
argv._ = ['.']
|
||||||
|
|
||||||
|
const options = await cmd.getNuxtConfig(argv, { testOption: true })
|
||||||
|
|
||||||
|
expect(options.testOption).toBe(true)
|
||||||
|
expect(options.server.port).toBe(3001)
|
||||||
|
expect(options.build.quiet).toBe(true)
|
||||||
|
expect(options.build.analyze).toBe(true)
|
||||||
|
expect(consola.fatal).toHaveBeenCalledWith('Provided hostname argument has no value') // hostname check
|
||||||
|
})
|
||||||
|
|
||||||
|
test('returns Nuxt instance', async () => {
|
||||||
|
const cmd = new Command()
|
||||||
|
const nuxt = await cmd.getNuxt()
|
||||||
|
|
||||||
|
expect(nuxt.constructor.name).toBe('Nuxt')
|
||||||
|
expect(typeof nuxt.ready).toBe('function')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('returns Builder instance', async () => {
|
||||||
|
const cmd = new Command()
|
||||||
|
const builder = await cmd.getBuilder()
|
||||||
|
|
||||||
|
expect(builder.constructor.name).toBe('Builder')
|
||||||
|
expect(typeof builder.build).toBe('function')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('returns Generator instance', async () => {
|
||||||
|
const cmd = new Command()
|
||||||
|
const generator = await cmd.getGenerator()
|
||||||
|
|
||||||
|
expect(generator.constructor.name).toBe('Generator')
|
||||||
|
expect(typeof generator.generate).toBe('function')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('builds help text', () => {
|
||||||
|
const cmd = new Command({
|
||||||
|
description: 'a very long description that is longer than 80 chars and ' +
|
||||||
|
'should wrap to the next line while keeping indentation',
|
||||||
|
usage: 'this is how you do it',
|
||||||
|
options: ['build']
|
||||||
|
})
|
||||||
|
|
||||||
|
const expectedText = `
|
||||||
|
Description
|
||||||
|
a very long description that is longer than 80 chars and should wrap to the next
|
||||||
|
line while keeping indentation
|
||||||
|
Usage
|
||||||
|
$ nuxt this is how you do it
|
||||||
|
Options
|
||||||
|
--no-build Only generate pages for dynamic routes. Nuxt has to be
|
||||||
|
built once before using this option
|
||||||
|
--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)
|
||||||
|
--version Display the Nuxt version
|
||||||
|
--help, -h Display this message
|
||||||
|
|
||||||
|
`
|
||||||
|
expect(cmd._getHelp()).toBe(expectedText)
|
||||||
|
})
|
||||||
|
|
||||||
|
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()
|
||||||
|
})
|
||||||
|
})
|
114
packages/cli/test/unit/dev.test.js
Normal file
114
packages/cli/test/unit/dev.test.js
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
import { consola } from '../utils'
|
||||||
|
import { mockNuxt, mockBuilder, mockGetNuxtConfig } from '../utils/mocking'
|
||||||
|
|
||||||
|
describe('dev', () => {
|
||||||
|
let dev
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
dev = await import('../../src/commands/dev')
|
||||||
|
dev = dev.default
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.resetAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('is function', () => {
|
||||||
|
expect(typeof dev).toBe('function')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('reloads on fileChanged hook', async () => {
|
||||||
|
const Nuxt = mockNuxt()
|
||||||
|
const Builder = mockBuilder()
|
||||||
|
|
||||||
|
await dev()
|
||||||
|
|
||||||
|
expect(consola.error).not.toHaveBeenCalled()
|
||||||
|
|
||||||
|
expect(Builder.prototype.build).toHaveBeenCalled()
|
||||||
|
expect(Nuxt.prototype.listen).toHaveBeenCalled()
|
||||||
|
expect(Nuxt.prototype.showReady).toHaveBeenCalled()
|
||||||
|
expect(Builder.prototype.watchServer).toHaveBeenCalled()
|
||||||
|
|
||||||
|
jest.resetAllMocks()
|
||||||
|
|
||||||
|
const builder = new Builder()
|
||||||
|
builder.nuxt = new Nuxt()
|
||||||
|
await Nuxt.fileChangedHook(builder)
|
||||||
|
expect(consola.debug).toHaveBeenCalled()
|
||||||
|
|
||||||
|
expect(Nuxt.prototype.clearHook).toHaveBeenCalled()
|
||||||
|
expect(Builder.prototype.unwatch).toHaveBeenCalled()
|
||||||
|
expect(Builder.prototype.build).toHaveBeenCalled()
|
||||||
|
expect(Nuxt.prototype.close).toHaveBeenCalled()
|
||||||
|
expect(Nuxt.prototype.listen).toHaveBeenCalled()
|
||||||
|
expect(Nuxt.prototype.showReady).not.toHaveBeenCalled()
|
||||||
|
expect(Builder.prototype.watchServer).toHaveBeenCalled()
|
||||||
|
|
||||||
|
expect(consola.error).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('catches build error', async () => {
|
||||||
|
const Nuxt = mockNuxt()
|
||||||
|
const Builder = mockBuilder()
|
||||||
|
|
||||||
|
await dev()
|
||||||
|
jest.resetAllMocks()
|
||||||
|
|
||||||
|
// Test error on second build so we cover oldInstance stuff
|
||||||
|
const builder = new Builder()
|
||||||
|
builder.nuxt = new Nuxt()
|
||||||
|
Builder.prototype.build = jest.fn().mockImplementationOnce(() => Promise.reject(new Error('Build Error')))
|
||||||
|
await Nuxt.fileChangedHook(builder)
|
||||||
|
|
||||||
|
expect(Nuxt.prototype.close).toHaveBeenCalled()
|
||||||
|
expect(consola.error).toHaveBeenCalledWith(new Error('Build Error'))
|
||||||
|
})
|
||||||
|
|
||||||
|
test('catches watchServer error', async () => {
|
||||||
|
const Nuxt = mockNuxt()
|
||||||
|
const Builder = mockBuilder()
|
||||||
|
|
||||||
|
await dev()
|
||||||
|
jest.resetAllMocks()
|
||||||
|
|
||||||
|
const builder = new Builder()
|
||||||
|
builder.nuxt = new Nuxt()
|
||||||
|
Builder.prototype.watchServer = jest.fn().mockImplementationOnce(() => Promise.reject(new Error('watchServer Error')))
|
||||||
|
await Nuxt.fileChangedHook(builder)
|
||||||
|
|
||||||
|
expect(consola.error).toHaveBeenCalledWith(new Error('watchServer Error'))
|
||||||
|
expect(Builder.prototype.watchServer).toHaveBeenCalledTimes(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('catches error on hook error', async () => {
|
||||||
|
const Nuxt = mockNuxt()
|
||||||
|
const Builder = mockBuilder()
|
||||||
|
|
||||||
|
await dev()
|
||||||
|
jest.resetAllMocks()
|
||||||
|
|
||||||
|
mockGetNuxtConfig().mockImplementationOnce(() => {
|
||||||
|
throw new Error('Config Error')
|
||||||
|
})
|
||||||
|
const builder = new Builder()
|
||||||
|
builder.nuxt = new Nuxt()
|
||||||
|
await Nuxt.fileChangedHook(builder)
|
||||||
|
|
||||||
|
expect(consola.error).toHaveBeenCalledWith(new Error('Config Error'))
|
||||||
|
expect(Builder.prototype.watchServer).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('catches error on startDev', async () => {
|
||||||
|
mockNuxt({
|
||||||
|
listen: jest.fn().mockImplementation(() => {
|
||||||
|
throw new Error('Listen Error')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
mockBuilder()
|
||||||
|
|
||||||
|
await dev()
|
||||||
|
|
||||||
|
expect(consola.error).toHaveBeenCalledWith(new Error('Listen Error'))
|
||||||
|
})
|
||||||
|
})
|
64
packages/cli/test/unit/generate.test.js
Normal file
64
packages/cli/test/unit/generate.test.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import { consola, mockGetNuxt, mockGetGenerator } from '../utils'
|
||||||
|
import Command from '../../src/command'
|
||||||
|
|
||||||
|
describe('generate', () => {
|
||||||
|
let generate
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
generate = await import('../../src/commands/generate')
|
||||||
|
generate = generate.default
|
||||||
|
|
||||||
|
jest.spyOn(process, 'exit').mockImplementation(code => code)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
process.exit.mockRestore()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.resetAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('is function', () => {
|
||||||
|
expect(typeof generate).toBe('function')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('builds by default', async () => {
|
||||||
|
mockGetNuxt()
|
||||||
|
const generator = mockGetGenerator(Promise.resolve())
|
||||||
|
|
||||||
|
await generate()
|
||||||
|
|
||||||
|
expect(generator).toHaveBeenCalled()
|
||||||
|
expect(generator.mock.calls[0][0].build).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
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 generate()
|
||||||
|
|
||||||
|
expect(generator).toHaveBeenCalled()
|
||||||
|
expect(generator.mock.calls[0][0].build).toBe(false)
|
||||||
|
Command.prototype.getArgv = getArgv
|
||||||
|
})
|
||||||
|
|
||||||
|
test('catches error', async () => {
|
||||||
|
mockGetNuxt()
|
||||||
|
mockGetGenerator(Promise.reject(new Error('Generator Error')))
|
||||||
|
|
||||||
|
await generate()
|
||||||
|
|
||||||
|
expect(consola.fatal).toHaveBeenCalledWith(new Error('Generator Error'))
|
||||||
|
})
|
||||||
|
})
|
69
packages/cli/test/unit/start.test.js
Normal file
69
packages/cli/test/unit/start.test.js
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import fs from 'fs'
|
||||||
|
import { consola, mockGetNuxtStart, mockGetNuxtConfig } from '../utils'
|
||||||
|
|
||||||
|
describe('start', () => {
|
||||||
|
let start
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
start = await import('../../src/commands/start')
|
||||||
|
start = start.default
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
if (fs.existsSync.mockRestore) {
|
||||||
|
fs.existsSync.mockRestore()
|
||||||
|
}
|
||||||
|
|
||||||
|
jest.resetAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('is function', () => {
|
||||||
|
expect(typeof start).toBe('function')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('starts listening and calls showReady', async () => {
|
||||||
|
const { listen, showReady } = mockGetNuxtStart()
|
||||||
|
await start()
|
||||||
|
|
||||||
|
expect(listen).toHaveBeenCalled()
|
||||||
|
expect(showReady).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('no error if dist dir exists', async () => {
|
||||||
|
mockGetNuxtStart()
|
||||||
|
mockGetNuxtConfig()
|
||||||
|
jest.spyOn(fs, 'existsSync').mockImplementationOnce(() => true)
|
||||||
|
|
||||||
|
await start()
|
||||||
|
|
||||||
|
expect(consola.fatal).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fatal error if dist dir doesnt exist', async () => {
|
||||||
|
mockGetNuxtStart()
|
||||||
|
jest.spyOn(fs, 'existsSync').mockImplementationOnce(() => false)
|
||||||
|
|
||||||
|
await start()
|
||||||
|
|
||||||
|
expect(consola.fatal).toHaveBeenCalledWith('No build files found, please run `nuxt build` before launching `nuxt start`')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('no error on ssr and server bundle exists', async () => {
|
||||||
|
mockGetNuxtStart(true)
|
||||||
|
mockGetNuxtConfig()
|
||||||
|
jest.spyOn(fs, 'existsSync').mockImplementation(() => true)
|
||||||
|
|
||||||
|
await start()
|
||||||
|
|
||||||
|
expect(consola.fatal).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('fatal error on ssr and server bundle doesnt exist', async () => {
|
||||||
|
mockGetNuxtStart(true)
|
||||||
|
jest.spyOn(fs, 'existsSync').mockImplementation(() => false)
|
||||||
|
|
||||||
|
await start()
|
||||||
|
|
||||||
|
expect(consola.fatal).toHaveBeenCalledWith('No SSR build! Please start with `nuxt start --spa` or build using `nuxt build --universal`')
|
||||||
|
})
|
||||||
|
})
|
111
packages/cli/test/unit/utils.test.js
Normal file
111
packages/cli/test/unit/utils.test.js
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
import { consola } from '../utils'
|
||||||
|
import * as utils from '../../src/utils'
|
||||||
|
|
||||||
|
describe('cli/utils', () => {
|
||||||
|
afterEach(() => {
|
||||||
|
jest.resetAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('loadNuxtConfig: defaults', async () => {
|
||||||
|
const argv = {
|
||||||
|
_: ['.'],
|
||||||
|
'config-file': 'nuxt.config.js',
|
||||||
|
universal: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = await utils.loadNuxtConfig(argv)
|
||||||
|
expect(options.rootDir).toBe(process.cwd())
|
||||||
|
expect(options.mode).toBe('universal')
|
||||||
|
expect(options.server.host).toBe('localhost')
|
||||||
|
expect(options.server.port).toBe(3000)
|
||||||
|
expect(options.server.socket).not.toBeDefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('loadNuxtConfig: config-file', async () => {
|
||||||
|
const argv = {
|
||||||
|
_: [__dirname],
|
||||||
|
'config-file': '../fixtures/nuxt.config.js',
|
||||||
|
spa: true
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = await utils.loadNuxtConfig(argv)
|
||||||
|
expect(options.testOption).toBe(true)
|
||||||
|
expect(options.rootDir).toBe('/some/path')
|
||||||
|
expect(options.mode).toBe('spa')
|
||||||
|
expect(options.server.host).toBe('nuxt-host')
|
||||||
|
expect(options.server.port).toBe(3001)
|
||||||
|
expect(options.server.socket).toBe('/var/run/nuxt.sock')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('loadNuxtConfig: not-existing config-file', async () => {
|
||||||
|
const argv = {
|
||||||
|
_: [__dirname],
|
||||||
|
'config-file': '../fixtures/nuxt.doesnt-exist.js'
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = await utils.loadNuxtConfig(argv)
|
||||||
|
expect(options.testOption).not.toBeDefined()
|
||||||
|
|
||||||
|
expect(consola.fatal).toHaveBeenCalledTimes(1)
|
||||||
|
expect(consola.fatal).toHaveBeenCalledWith(expect.stringMatching(/Could not load config file/))
|
||||||
|
})
|
||||||
|
|
||||||
|
test('loadNuxtConfig: async config-file', async () => {
|
||||||
|
const argv = {
|
||||||
|
_: [__dirname],
|
||||||
|
'config-file': '../fixtures/nuxt.async-config.js',
|
||||||
|
hostname: 'async-host',
|
||||||
|
port: 3002,
|
||||||
|
'unix-socket': '/var/run/async.sock'
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = await utils.loadNuxtConfig(argv)
|
||||||
|
expect(options.testOption).toBe(true)
|
||||||
|
expect(options.mode).toBe('supercharged')
|
||||||
|
expect(options.server.host).toBe('async-host')
|
||||||
|
expect(options.server.port).toBe(3002)
|
||||||
|
expect(options.server.socket).toBe('/var/run/async.sock')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('loadNuxtConfig: async config-file with error', async () => {
|
||||||
|
const argv = {
|
||||||
|
_: [__dirname],
|
||||||
|
'config-file': '../fixtures/nuxt.async-error.js'
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = await utils.loadNuxtConfig(argv)
|
||||||
|
expect(options.testOption).not.toBeDefined()
|
||||||
|
|
||||||
|
expect(consola.error).toHaveBeenCalledTimes(1)
|
||||||
|
expect(consola.error).toHaveBeenCalledWith(new Error('Async Config Error'))
|
||||||
|
expect(consola.fatal).toHaveBeenCalledWith('Error while fetching async configuration')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('loadNuxtConfig: server env', async () => {
|
||||||
|
const env = process.env
|
||||||
|
|
||||||
|
process.env.HOST = 'env-host'
|
||||||
|
process.env.PORT = 3003
|
||||||
|
process.env.UNIX_SOCKET = '/var/run/env.sock'
|
||||||
|
|
||||||
|
const argv = {
|
||||||
|
_: [__dirname],
|
||||||
|
'config-file': '../fixtures/nuxt.config.js'
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = await utils.loadNuxtConfig(argv)
|
||||||
|
expect(options.server.host).toBe('env-host')
|
||||||
|
expect(options.server.port).toBe('3003')
|
||||||
|
expect(options.server.socket).toBe('/var/run/env.sock')
|
||||||
|
|
||||||
|
process.env = env
|
||||||
|
})
|
||||||
|
|
||||||
|
test('indent', () => {
|
||||||
|
expect(utils.indent(4)).toBe(' ')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('indent custom char', () => {
|
||||||
|
expect(utils.indent(4, '-')).toBe('----')
|
||||||
|
})
|
||||||
|
})
|
8
packages/cli/test/utils/index.js
Normal file
8
packages/cli/test/utils/index.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import consola from 'consola'
|
||||||
|
export * from './mocking'
|
||||||
|
|
||||||
|
jest.mock('consola')
|
||||||
|
|
||||||
|
export {
|
||||||
|
consola
|
||||||
|
}
|
96
packages/cli/test/utils/mocking.js
Normal file
96
packages/cli/test/utils/mocking.js
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
import Command from '../../src/command'
|
||||||
|
|
||||||
|
export const mockGetNuxt = (options, implementation) => {
|
||||||
|
Command.prototype.getNuxt = jest.fn().mockImplementationOnce(() => {
|
||||||
|
return Object.assign({
|
||||||
|
hook: jest.fn(),
|
||||||
|
options
|
||||||
|
}, implementation || {})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mockGetBuilder = (ret) => {
|
||||||
|
const build = jest.fn().mockImplementationOnce(() => {
|
||||||
|
return ret
|
||||||
|
})
|
||||||
|
|
||||||
|
Command.prototype.getBuilder = jest.fn().mockImplementationOnce(() => {
|
||||||
|
return { build }
|
||||||
|
})
|
||||||
|
|
||||||
|
return build
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mockGetGenerator = (ret) => {
|
||||||
|
const generate = jest.fn()
|
||||||
|
if (ret) {
|
||||||
|
generate.mockImplementationOnce(() => {
|
||||||
|
return ret
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Command.prototype.getGenerator = jest.fn().mockImplementationOnce(() => {
|
||||||
|
return { generate }
|
||||||
|
})
|
||||||
|
|
||||||
|
return generate
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mockGetNuxtStart = (ssr) => {
|
||||||
|
const listen = jest.fn().mockImplementationOnce(() => {
|
||||||
|
return Promise.resolve()
|
||||||
|
})
|
||||||
|
const showReady = jest.fn()
|
||||||
|
|
||||||
|
mockGetNuxt({
|
||||||
|
rootDir: '.',
|
||||||
|
render: {
|
||||||
|
ssr
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
listen,
|
||||||
|
showReady
|
||||||
|
})
|
||||||
|
|
||||||
|
return { listen, showReady }
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mockGetNuxtConfig = () => {
|
||||||
|
const spy = jest.fn()
|
||||||
|
Command.prototype.getNuxtConfig = spy
|
||||||
|
return spy
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mockNuxt = (implementation) => {
|
||||||
|
const Nuxt = function () {}
|
||||||
|
Object.assign(Nuxt.prototype, {
|
||||||
|
hook(type, fn) {
|
||||||
|
if (type === 'watch:fileChanged') {
|
||||||
|
Nuxt.fileChangedHook = fn
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clearHook: jest.fn(),
|
||||||
|
close: jest.fn(),
|
||||||
|
listen: jest.fn().mockImplementationOnce(() => Promise.resolve()),
|
||||||
|
showReady: jest.fn().mockImplementationOnce(() => Promise.resolve())
|
||||||
|
}, implementation || {})
|
||||||
|
|
||||||
|
Command.prototype.importCore = jest.fn().mockImplementationOnce(() => {
|
||||||
|
return { Nuxt }
|
||||||
|
})
|
||||||
|
return Nuxt
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mockBuilder = (implementation) => {
|
||||||
|
const Builder = function () {}
|
||||||
|
Object.assign(Builder.prototype, {
|
||||||
|
build: jest.fn().mockImplementationOnce(() => Promise.resolve()),
|
||||||
|
unwatch: jest.fn().mockImplementationOnce(() => Promise.resolve()),
|
||||||
|
watchServer: jest.fn().mockImplementationOnce(() => Promise.resolve())
|
||||||
|
}, implementation || {})
|
||||||
|
|
||||||
|
Command.prototype.importBuilder = jest.fn().mockImplementationOnce(() => {
|
||||||
|
return { Builder }
|
||||||
|
})
|
||||||
|
return Builder
|
||||||
|
}
|
@ -11088,6 +11088,15 @@ wrap-ansi@^3.0.1:
|
|||||||
string-width "^2.1.1"
|
string-width "^2.1.1"
|
||||||
strip-ansi "^4.0.0"
|
strip-ansi "^4.0.0"
|
||||||
|
|
||||||
|
wrap-ansi@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-4.0.0.tgz#b3570d7c70156159a2d42be5cc942e957f7b1131"
|
||||||
|
integrity sha512-uMTsj9rDb0/7kk1PbcbCcwvHUxp60fGDB/NNXpVa0Q+ic/e7y5+BwTxKfQ33VYgDppSwi/FBzpetYzo8s6tfbg==
|
||||||
|
dependencies:
|
||||||
|
ansi-styles "^3.2.0"
|
||||||
|
string-width "^2.1.1"
|
||||||
|
strip-ansi "^4.0.0"
|
||||||
|
|
||||||
wrappy@1:
|
wrappy@1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||||
|
Loading…
Reference in New Issue
Block a user