Nuxt/packages/builder/test/builder.watch.test.js

331 lines
10 KiB
JavaScript
Raw Normal View History

import chokidar from 'chokidar'
import upath from 'upath'
import debounce from 'lodash/debounce'
import { r, isString } from '@nuxt/utils'
import Builder from '../src/builder'
import { createNuxt } from './__utils__'
jest.mock('chokidar', () => ({
watch: jest.fn().mockReturnThis(),
on: jest.fn().mockReturnThis(),
close: jest.fn().mockReturnThis()
}))
jest.mock('upath', () => ({ normalizeSafe: jest.fn(src => src) }))
jest.mock('lodash/debounce', () => jest.fn(fn => fn))
jest.mock('@nuxt/utils')
jest.mock('../src/ignore')
describe('builder: builder watch', () => {
beforeEach(() => {
jest.clearAllMocks()
})
test('should watch client files', () => {
const nuxt = createNuxt()
nuxt.options.srcDir = '/var/nuxt/src'
nuxt.options.dir = {
layouts: '/var/nuxt/src/layouts',
pages: '/var/nuxt/src/pages',
store: '/var/nuxt/src/store',
middleware: '/var/nuxt/src/middleware'
}
nuxt.options.build.watch = []
nuxt.options.watchers = {
chokidar: { test: true }
}
const builder = new Builder(nuxt, {})
r.mockImplementation((dir, src) => src)
builder.watchClient()
const patterns = [
'/var/nuxt/src/layouts',
'/var/nuxt/src/store',
'/var/nuxt/src/middleware',
'/var/nuxt/src/layouts/*.{vue,js,ts,tsx}',
'/var/nuxt/src/layouts/**/*.{vue,js,ts,tsx}'
]
expect(r).toBeCalledTimes(5)
expect(r).nthCalledWith(1, '/var/nuxt/src', '/var/nuxt/src/layouts')
expect(r).nthCalledWith(2, '/var/nuxt/src', '/var/nuxt/src/store')
expect(r).nthCalledWith(3, '/var/nuxt/src', '/var/nuxt/src/middleware')
expect(r).nthCalledWith(4, '/var/nuxt/src', '/var/nuxt/src/layouts/*.{vue,js,ts,tsx}')
expect(r).nthCalledWith(5, '/var/nuxt/src', '/var/nuxt/src/layouts/**/*.{vue,js,ts,tsx}')
expect(upath.normalizeSafe).toBeCalledTimes(5)
expect(upath.normalizeSafe).nthCalledWith(1, '/var/nuxt/src/layouts', 0, patterns)
expect(upath.normalizeSafe).nthCalledWith(2, '/var/nuxt/src/store', 1, patterns)
expect(upath.normalizeSafe).nthCalledWith(3, '/var/nuxt/src/middleware', 2, patterns)
expect(upath.normalizeSafe).nthCalledWith(4, '/var/nuxt/src/layouts/*.{vue,js,ts,tsx}', 3, patterns)
expect(upath.normalizeSafe).nthCalledWith(5, '/var/nuxt/src/layouts/**/*.{vue,js,ts,tsx}', 4, patterns)
expect(chokidar.watch).toBeCalledTimes(1)
expect(chokidar.watch).toBeCalledWith(patterns, { test: true })
expect(chokidar.on).toBeCalledTimes(2)
expect(chokidar.on).nthCalledWith(1, 'add', expect.any(Function))
expect(chokidar.on).nthCalledWith(2, 'unlink', expect.any(Function))
})
test('should watch pages files', () => {
const nuxt = createNuxt()
nuxt.options.srcDir = '/var/nuxt/src'
nuxt.options.dir = {
layouts: '/var/nuxt/src/layouts',
pages: '/var/nuxt/src/pages',
store: '/var/nuxt/src/store',
middleware: '/var/nuxt/src/middleware'
}
nuxt.options.build.watch = []
nuxt.options.watchers = {
chokidar: { test: true }
}
const builder = new Builder(nuxt, {})
builder._nuxtPages = true
r.mockImplementation((dir, src) => src)
builder.watchClient()
expect(r).toBeCalledTimes(8)
expect(r).nthCalledWith(6, '/var/nuxt/src', '/var/nuxt/src/pages')
expect(r).nthCalledWith(7, '/var/nuxt/src', '/var/nuxt/src/pages/*.{vue,js,ts,tsx}')
expect(r).nthCalledWith(8, '/var/nuxt/src', '/var/nuxt/src/pages/**/*.{vue,js,ts,tsx}')
})
test('should watch custom in watchClient', () => {
const nuxt = createNuxt()
nuxt.options.srcDir = '/var/nuxt/src'
nuxt.options.dir = {
layouts: '/var/nuxt/src/layouts',
pages: '/var/nuxt/src/pages',
store: '/var/nuxt/src/store',
middleware: '/var/nuxt/src/middleware'
}
nuxt.options.build.watch = []
nuxt.options.watchers = {
chokidar: { test: true }
}
const builder = new Builder(nuxt, {})
builder.watchCustom = jest.fn()
r.mockImplementation((dir, src) => src)
builder.watchClient()
expect(debounce).toBeCalledTimes(1)
expect(debounce).toBeCalledWith(expect.any(Function), 200)
const refreshFiles = chokidar.on.mock.calls[0][1]
builder.generateRoutesAndFiles = jest.fn()
refreshFiles()
expect(builder.generateRoutesAndFiles).toBeCalled()
expect(builder.watchCustom).toBeCalledTimes(1)
expect(builder.watchCustom).toBeCalledWith(refreshFiles)
})
test('should watch custom patterns', () => {
const nuxt = createNuxt()
nuxt.options.watchers = {
chokidar: { test: true }
}
nuxt.options.build.watch = [
'/var/nuxt/src/custom'
]
nuxt.options.build.styleResources = [
'/var/nuxt/src/style'
]
const builder = new Builder(nuxt, {})
const refreshFiles = jest.fn()
builder.watchCustom(refreshFiles)
expect(chokidar.watch).toBeCalledTimes(1)
expect(chokidar.watch).toBeCalledWith(
['/var/nuxt/src/custom', '/var/nuxt/src/style'],
{ test: true }
)
expect(chokidar.on).toBeCalledTimes(1)
expect(chokidar.on).toBeCalledWith('change', refreshFiles)
})
test('should call refreshFiles before watching custom patterns', () => {
const nuxt = createNuxt()
nuxt.options.watchers = {
chokidar: { test: true }
}
nuxt.options.build.watch = [
'/var/nuxt/src/custom'
]
const builder = new Builder(nuxt, {})
const refreshFiles = jest.fn()
builder.watchCustom(refreshFiles, true)
expect(refreshFiles).toBeCalledTimes(1)
})
test('should rewatch custom patterns when event is included in rewatchOnRawEvents', () => {
const nuxt = createNuxt()
nuxt.options.watchers = {
chokidar: { test: true },
rewatchOnRawEvents: ['rename']
}
nuxt.options.build.watch = [
'/var/nuxt/src/custom'
]
const builder = new Builder(nuxt, {})
const refreshFiles = jest.fn()
builder.watchCustom(refreshFiles)
expect(chokidar.on).toBeCalledTimes(2)
expect(chokidar.on).nthCalledWith(2, 'raw', expect.any(Function))
const rewatchHandler = chokidar.on.mock.calls[1][1]
builder.watchCustom = jest.fn()
rewatchHandler('rename')
rewatchHandler('change')
expect(chokidar.close).toBeCalledTimes(1)
expect(builder.watchers.custom).toBeNull()
expect(builder.watchCustom).toBeCalledTimes(1)
expect(builder.watchCustom).toBeCalledWith(refreshFiles, true)
})
test('should watch files for restarting server', () => {
const nuxt = createNuxt()
nuxt.options.watchers = {
chokidar: { test: true }
}
nuxt.options.watch = [
'/var/nuxt/src/watch/test'
]
nuxt.options.serverMiddleware = [
'/var/nuxt/src/middleware/test',
{ obj: 'test' }
]
const builder = new Builder(nuxt, {})
builder.ignore.ignoreFile = '/var/nuxt/src/.nuxtignore'
isString.mockImplementationOnce(src => typeof src === 'string')
builder.watchRestart()
expect(chokidar.watch).toBeCalledTimes(1)
expect(chokidar.watch).toBeCalledWith(
[
'resolveAlias(/var/nuxt/src/middleware/test)',
'resolveAlias(/var/nuxt/src/watch/test)',
'/var/nuxt/src/.nuxtignore'
],
{ test: true }
)
expect(chokidar.on).toBeCalledTimes(1)
expect(chokidar.on).toBeCalledWith('all', expect.any(Function))
})
test('should trigger restarting when files changed', () => {
const nuxt = createNuxt()
nuxt.options.watchers = {
chokidar: { test: true }
}
nuxt.options.watch = [
'/var/nuxt/src/watch/test'
]
nuxt.options.serverMiddleware = []
const builder = new Builder(nuxt, {})
builder.watchRestart()
const restartHandler = chokidar.on.mock.calls[0][1]
const watchingFile = '/var/nuxt/src/watch/test/index.js'
restartHandler('add', watchingFile)
restartHandler('change', watchingFile)
restartHandler('unlink', watchingFile)
expect(nuxt.callHook).toBeCalledTimes(6)
expect(nuxt.callHook).nthCalledWith(1, 'watch:fileChanged', builder, watchingFile)
expect(nuxt.callHook).nthCalledWith(2, 'watch:restart', { event: 'add', path: watchingFile })
expect(nuxt.callHook).nthCalledWith(3, 'watch:fileChanged', builder, watchingFile)
expect(nuxt.callHook).nthCalledWith(4, 'watch:restart', { event: 'change', path: watchingFile })
expect(nuxt.callHook).nthCalledWith(5, 'watch:fileChanged', builder, watchingFile)
expect(nuxt.callHook).nthCalledWith(6, 'watch:restart', { event: 'unlink', path: watchingFile })
})
test('should ignore other events in watchRestart', () => {
const nuxt = createNuxt()
nuxt.options.watchers = {
chokidar: { test: true }
}
nuxt.options.watch = [
'/var/nuxt/src/watch/test'
]
nuxt.options.serverMiddleware = []
const builder = new Builder(nuxt, {})
builder.watchRestart()
const restartHandler = chokidar.on.mock.calls[0][1]
const watchingFile = '/var/nuxt/src/watch/test/index.js'
restartHandler('rename', watchingFile)
expect(nuxt.callHook).not.toBeCalled()
})
test('should unwatch every watcher', () => {
const nuxt = createNuxt()
const builder = new Builder(nuxt, {})
builder.watchers = {
files: { close: jest.fn() },
custom: { close: jest.fn() },
restart: { close: jest.fn() }
}
builder.unwatch()
expect(builder.watchers.files.close).toBeCalledTimes(1)
expect(builder.watchers.custom.close).toBeCalledTimes(1)
expect(builder.watchers.restart.close).toBeCalledTimes(1)
})
test('should close watch and bundle builder', async () => {
const nuxt = createNuxt()
const bundleBuilderClose = jest.fn()
const builder = new Builder(nuxt, { close: bundleBuilderClose })
builder.unwatch = jest.fn()
expect(builder.__closed).toBeUndefined()
await builder.close()
expect(builder.__closed).toEqual(true)
expect(builder.unwatch).toBeCalledTimes(1)
expect(bundleBuilderClose).toBeCalledTimes(1)
})
test('should close bundleBuilder only if close api exists', async () => {
const nuxt = createNuxt()
const builder = new Builder(nuxt, { })
builder.unwatch = jest.fn()
expect(builder.__closed).toBeUndefined()
await builder.close()
expect(builder.__closed).toEqual(true)
expect(builder.unwatch).toBeCalledTimes(1)
})
test('should prevent duplicate close', async () => {
const nuxt = createNuxt()
const bundleBuilderClose = jest.fn()
const builder = new Builder(nuxt, { close: bundleBuilderClose })
builder.unwatch = jest.fn()
builder.__closed = true
await builder.close()
expect(builder.unwatch).not.toBeCalled()
expect(bundleBuilderClose).not.toBeCalled()
})
})