Skip to content

Commit

Permalink
test: unit tests for generator (#4857)
Browse files Browse the repository at this point in the history
  • Loading branch information
clarkdo committed Jan 29, 2019
1 parent 59be77a commit e22a282
Show file tree
Hide file tree
Showing 6 changed files with 719 additions and 5 deletions.
8 changes: 3 additions & 5 deletions packages/generator/src/generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export default class Generator {
const fallbackPath = path.join(this.distPath, fallback)

// Prevent conflicts
if (fsExtra.existsSync(fallbackPath)) {
if (await fsExtra.exists(fallbackPath)) {
consola.warn(`SPA fallback was configured, but the configured path (${fallbackPath}) already exists.`)
return
}
Expand All @@ -164,8 +164,7 @@ export default class Generator {
await this.nuxt.callHook('generate:distRemoved', this)

// Copy static and built files
/* istanbul ignore if */
if (fsExtra.existsSync(this.staticRoutes)) {
if (await fsExtra.exists(this.staticRoutes)) {
await fsExtra.copy(this.staticRoutes, this.distPath)
}
await fsExtra.copy(this.srcBuiltPath, this.distNuxtPath)
Expand Down Expand Up @@ -210,7 +209,6 @@ export default class Generator {
pageErrors.push({ type: 'handled', route, error: res.error })
}
} catch (err) {
/* istanbul ignore next */
pageErrors.push({ type: 'unhandled', route, error: err })
Array.prototype.push.apply(errors, pageErrors)

Expand All @@ -236,7 +234,7 @@ export default class Generator {
if (minificationOptions) {
try {
html = htmlMinifier.minify(html, minificationOptions)
} catch (err) /* istanbul ignore next */ {
} catch (err) {
const minifyErr = new Error(
`HTML minification failed. Make sure the route generates valid HTML. Failed HTML:\n ${html}`
)
Expand Down
14 changes: 14 additions & 0 deletions packages/generator/test/__utils__/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export const createNuxt = () => ({
ready: jest.fn(),
callHook: jest.fn(),
server: {
renderRoute: jest.fn(() => ({ html: 'rendered html' }))
},
options: {
srcDir: '/var/nuxt/src',
buildDir: '/var/nuxt/build',
generate: { dir: '/var/nuxt/generate' },
build: { publicPath: '__public' },
dir: { static: '/var/nuxt/static' }
}
})
220 changes: 220 additions & 0 deletions packages/generator/test/generator.gen.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
import path from 'path'
import chalk from 'chalk'
import consola from 'consola'
import fsExtra from 'fs-extra'
import { waitFor } from '@nuxt/utils'

import Generator from '../src/generator'
import { createNuxt } from './__utils__'

jest.mock('path')
jest.mock('chalk', () => ({
red: jest.fn(str => `red:${str}`),
yellow: jest.fn(str => `yellow:${str}`),
grey: jest.fn(str => `grey:${str}`)
}))
jest.mock('fs-extra')
jest.mock('@nuxt/utils')

describe('generator: generate routes', () => {
const sep = path.sep

beforeAll(() => {
path.sep = '[sep]'
path.join.mockImplementation((...args) => `join(${args.join(', ')})`)
})

afterAll(() => {
path.sep = sep
})

beforeEach(() => {
jest.clearAllMocks()
})

test('should generate with build and init by default', async () => {
const nuxt = createNuxt()
const builder = jest.fn()
const generator = new Generator(nuxt, builder)

const routes = ['routes']
const errors = ['errors']
generator.initiate = jest.fn()
generator.initRoutes = jest.fn(() => routes)
generator.generateRoutes = jest.fn(() => errors)
generator.afterGenerate = jest.fn()

await generator.generate()

expect(consola.debug).toBeCalledTimes(2)
expect(consola.debug).nthCalledWith(1, 'Initializing generator...')
expect(consola.debug).nthCalledWith(2, 'Preparing routes for generate...')
expect(generator.initiate).toBeCalledTimes(1)
expect(generator.initiate).toBeCalledWith({ build: true, init: true })
expect(generator.initRoutes).toBeCalledTimes(1)
expect(consola.info).toBeCalledTimes(1)
expect(consola.info).toBeCalledWith('Generating pages')
expect(generator.generateRoutes).toBeCalledTimes(1)
expect(generator.generateRoutes).toBeCalledWith(routes)
expect(generator.afterGenerate).toBeCalledTimes(1)
expect(nuxt.callHook).toBeCalledTimes(1)
expect(nuxt.callHook).toBeCalledWith('generate:done', generator, errors)
})

test('should generate without build and init when disabled', async () => {
const nuxt = createNuxt()
const builder = jest.fn()
const generator = new Generator(nuxt, builder)

const routes = ['routes']
const errors = ['errors']
generator.initiate = jest.fn()
generator.initRoutes = jest.fn(() => routes)
generator.generateRoutes = jest.fn(() => errors)
generator.afterGenerate = jest.fn()

await generator.generate({ build: false, init: false })

expect(generator.initiate).toBeCalledTimes(1)
expect(generator.initiate).toBeCalledWith({ build: false, init: false })
})

test('should generate routes', async () => {
const nuxt = createNuxt()
nuxt.options.generate = {
...nuxt.options.generate,
concurrency: 2,
interval: 100
}
const routes = [
{ route: '/index', payload: { param: 'test-index' } },
{ route: '/about', payload: { param: 'test-about' } },
{ route: '/foo', payload: { param: 'test-foo' } },
{ route: '/bar', payload: { param: 'test-bar' } },
{ route: '/baz', payload: { param: 'test-baz' } }
]
const generator = new Generator(nuxt)

generator.generateRoute = jest.fn()
jest.spyOn(routes, 'splice')

const errors = await generator.generateRoutes(routes)

expect(routes.splice).toBeCalledTimes(3)
expect(routes.splice).toBeCalledWith(0, 2)
expect(waitFor).toBeCalledTimes(5)
expect(waitFor).nthCalledWith(1, 0)
expect(waitFor).nthCalledWith(2, 100)
expect(waitFor).nthCalledWith(3, 0)
expect(waitFor).nthCalledWith(4, 100)
expect(waitFor).nthCalledWith(5, 0)
expect(generator.generateRoute).toBeCalledTimes(5)
expect(generator.generateRoute).nthCalledWith(1, { route: '/index', payload: { param: 'test-index' }, errors })
expect(generator.generateRoute).nthCalledWith(2, { route: '/about', payload: { param: 'test-about' }, errors })
expect(generator.generateRoute).nthCalledWith(3, { route: '/foo', payload: { param: 'test-foo' }, errors })
expect(generator.generateRoute).nthCalledWith(4, { route: '/bar', payload: { param: 'test-bar' }, errors })
expect(generator.generateRoute).nthCalledWith(5, { route: '/baz', payload: { param: 'test-baz' }, errors })

generator._formatErrors = jest.fn()
errors.toString()

expect(generator._formatErrors).toBeCalledTimes(1)
expect(generator._formatErrors).toBeCalledWith(errors)

routes.splice.mockRestore()
})

test('should format errors', () => {
const nuxt = createNuxt()
const generator = new Generator(nuxt)

const errors = generator._formatErrors([
{ type: 'handled', route: '/foo', error: 'foo failed' },
{ type: 'unhandled', route: '/bar', error: { stack: 'bar failed' } }
])

expect(chalk.yellow).toBeCalledTimes(1)
expect(chalk.yellow).toBeCalledWith(' /foo\n\n')
expect(chalk.red).toBeCalledTimes(1)
expect(chalk.red).toBeCalledWith(' /bar\n\n')
expect(chalk.grey).toBeCalledTimes(2)
expect(chalk.grey).nthCalledWith(1, '"foo failed"\n')
expect(chalk.grey).nthCalledWith(2, 'bar failed')
expect(errors).toEqual(`yellow: /foo
grey:"foo failed"
red: /bar
grey:bar failed`)
})

test('should write fallback html after generate', async () => {
const nuxt = createNuxt()
nuxt.options.generate.fallback = 'fallback.html'
const generator = new Generator(nuxt)
path.join.mockClear()
fsExtra.exists.mockReturnValueOnce(false)

await generator.afterGenerate()

expect(path.join).toBeCalledTimes(1)
expect(path.join).toBeCalledWith(generator.distPath, 'fallback.html')
expect(fsExtra.exists).toBeCalledTimes(1)
expect(fsExtra.exists).toBeCalledWith(`join(${generator.distPath}, fallback.html)`)
expect(nuxt.server.renderRoute).toBeCalledTimes(1)
expect(nuxt.server.renderRoute).toBeCalledWith('/', { spa: true })
expect(fsExtra.writeFile).toBeCalledTimes(1)
expect(fsExtra.writeFile).toBeCalledWith(`join(${generator.distPath}, fallback.html)`, 'rendered html', 'utf8')
})

test('should disable writing fallback if fallback is empty or not string', async () => {
const nuxt = createNuxt()
const generator = new Generator(nuxt)
path.join.mockClear()

nuxt.options.generate.fallback = ''
await generator.afterGenerate()

nuxt.options.generate.fallback = jest.fn()
await generator.afterGenerate()

expect(path.join).not.toBeCalled()
expect(fsExtra.exists).not.toBeCalled()
expect(nuxt.server.renderRoute).not.toBeCalled()
expect(fsExtra.writeFile).not.toBeCalled()
})

test('should disable writing fallback if fallback path is not existed', async () => {
const nuxt = createNuxt()
nuxt.options.generate.fallback = 'fallback.html'
const generator = new Generator(nuxt)
path.join.mockClear()
fsExtra.exists.mockReturnValueOnce(true)

await generator.afterGenerate()

expect(path.join).toBeCalledTimes(1)
expect(path.join).toBeCalledWith(generator.distPath, 'fallback.html')
expect(fsExtra.exists).toBeCalledTimes(1)
expect(fsExtra.exists).toBeCalledWith(`join(${generator.distPath}, fallback.html)`)
expect(nuxt.server.renderRoute).not.toBeCalled()
expect(fsExtra.writeFile).not.toBeCalled()
})

test('should disable writing fallback if fallback is empty or not string', async () => {
const nuxt = createNuxt()
const generator = new Generator(nuxt)
path.join.mockClear()

nuxt.options.generate.fallback = ''
await generator.afterGenerate()

nuxt.options.generate.fallback = jest.fn()
await generator.afterGenerate()

expect(path.join).not.toBeCalled()
expect(fsExtra.exists).not.toBeCalled()
expect(fsExtra.writeFile).not.toBeCalled()
})
})

0 comments on commit e22a282

Please sign in to comment.