basic migration to jest

This commit is contained in:
Pooya Parsa 2018-03-18 23:01:32 +03:30
parent 6f718ec24b
commit ed22e78a75
30 changed files with 2080 additions and 2183 deletions

View File

@ -8,16 +8,16 @@ import { Nuxt, Builder } from 'nuxt'
let nuxt = null
// Init Nuxt.js and create a server listening on localhost:4000
test.before('Init Nuxt.js', async t => {
beforeAll(async () => {
const rootDir = resolve(__dirname, '..')
let config = {}
try { config = require(resolve(rootDir, 'nuxt.config.js')) } catch (e) {}
config.rootDir = rootDir // project folder
config.dev = false // production build
nuxt = new Nuxt(config)
await new Builder(nuxt).build()
new Builder(nuxt).build()
await nuxt.listen(4000, 'localhost')
})
}, 30000)
// Example of testing only generated html
test('Route / exits and render HTML', async t => {

View File

@ -43,7 +43,8 @@
"jest": {
"testEnvironment": "node",
"coverageDirectory": "./coverage/",
"collectCoverage": false
"collectCoverage": false,
"setupTestFrameworkScriptFile": "./test/helpers/setup"
},
"scripts": {
"test": "npm run lint && jest",

View File

@ -1,16 +1,16 @@
import { resolve } from 'path'
import test from 'ava'
import { Nuxt, Options } from '..'
import { version } from '../package.json'
test('Nuxt.version is same as package', t => {
t.is(Nuxt.version, version)
})
describe('basic config defaults', () => {
test('Nuxt.version is same as package', () => {
expect(Nuxt.version).toBe(version)
})
test('modulesDir uses /node_modules as default if not set', async t => {
const options = Options.from({})
const currentNodeModulesDir = resolve(__dirname, '..', 'node_modules')
t.true(options.modulesDir.includes(currentNodeModulesDir))
test('modulesDir uses /node_modules as default if not set', async () => {
const options = Options.from({})
const currentNodeModulesDir = resolve(__dirname, '..', 'node_modules')
expect(options.modulesDir.includes(currentNodeModulesDir)).toBe(true)
})
})

View File

@ -1,11 +1,8 @@
import { resolve } from 'path'
import test from 'ava'
import { Nuxt, Builder } from '..'
import * as browser from './helpers/browser'
import { interceptLog } from './helpers/console'
const port = 4003
const url = route => 'http://localhost:' + port + route
@ -15,241 +12,229 @@ let page = null
const waitFor = ms => new Promise(resolve => setTimeout(resolve, ms || 0))
// Init nuxt.js and create server listening on localhost:4003
test.serial('Init Nuxt.js', async t => {
const options = {
rootDir: resolve(__dirname, 'fixtures/basic'),
buildDir: '.nuxt-csr',
dev: true,
head: {
titleTemplate(titleChunk) {
return titleChunk ? `${titleChunk} - Nuxt.js` : 'Nuxt.js'
describe('basic csr', () => {
// Init nuxt.js and create server listening on localhost:4003
beforeAll(async () => {
const options = {
rootDir: resolve(__dirname, 'fixtures/basic'),
buildDir: '.nuxt-csr',
dev: true,
build: {
stats: false
}
},
build: {
stats: false
}
}
const logSpy = await interceptLog(async () => {
nuxt = new Nuxt(options)
await new Builder(nuxt).build()
new Builder(nuxt).build()
await nuxt.listen(port, 'localhost')
}, 30000)
test('Start browser', async () => {
expect.assertions(0) // suppress 'no assertions' warning
await browser.start({
// slowMo: 50,
// headless: false
})
})
t.true(logSpy.calledWithMatch('DONE'))
t.true(logSpy.calledWithMatch('OPEN'))
})
test('Open /', async () => {
page = await browser.page(url('/'))
await waitFor(1000)
test.serial('Start browser', async t => {
t.plan(0) // suppress 'no assertions' warning
await browser.start({
// slowMo: 50,
// headless: false
expect(await page.$text('h1')).toBe('Index page')
})
test('/stateless', async () => {
const { hook } = await page.nuxt.navigate('/stateless', false)
const loading = await page.nuxt.loadingData()
await waitFor(1000)
expect(loading.show).toBe(true)
await hook
expect(await page.$text('h1')).toBe('My component!')
})
test('/css', async () => {
await page.nuxt.navigate('/css')
await waitFor(1000)
expect(await page.$text('.red')).toBe('This is red')
expect(await page.$eval('.red', red => window.getComputedStyle(red).color)).toBe('rgb(255, 0, 0)')
})
test('/stateful', async () => {
await page.nuxt.navigate('/stateful')
await waitFor(1000)
expect(await page.$text('p')).toBe('The answer is 42')
})
test('/store', async () => {
await page.nuxt.navigate('/store')
await waitFor(1000)
expect(await page.$text('h1')).toBe('Vuex Nested Modules')
expect(await page.$text('p')).toBe('1')
})
test('/head', async () => {
const msg = new Promise(resolve =>
page.on('console', msg => resolve(msg.text()))
)
await page.nuxt.navigate('/head')
const metas = await page.$$attr('meta', 'content')
await waitFor(1000)
expect(await msg).toBe('Body script!')
expect(await page.title()).toBe('My title - Nuxt.js')
expect(await page.$text('h1')).toBe('I can haz meta tags')
expect(metas[0]).toBe('my meta')
})
test('/async-data', async () => {
await page.nuxt.navigate('/async-data')
await waitFor(1000)
expect(await page.$text('p')).toBe('Nuxt.js')
})
test('/await-async-data', async () => {
await page.nuxt.navigate('/await-async-data')
await waitFor(1000)
expect(await page.$text('p')).toBe('Await Nuxt.js')
})
test('/callback-async-data', async () => {
await page.nuxt.navigate('/callback-async-data')
await waitFor(1000)
expect(await page.$text('p')).toBe('Callback Nuxt.js')
})
test('/users/1', async () => {
await page.nuxt.navigate('/users/1')
await waitFor(1000)
expect(await page.$text('h1')).toBe('User: 1')
})
test('/validate should display a 404', async () => {
await page.nuxt.navigate('/validate')
await waitFor(1000)
const error = await page.nuxt.errorData()
expect(error.statusCode).toBe(404)
expect(error.message).toBe('This page could not be found')
})
test('/validate?valid=true', async () => {
await page.nuxt.navigate('/validate?valid=true')
await waitFor(1000)
expect(await page.$text('h1')).toBe('I am valid')
})
test('/redirect', async () => {
await page.nuxt.navigate('/redirect')
await waitFor(1000)
expect(await page.$text('h1')).toBe('Index page')
})
test('/error', async () => {
await page.nuxt.navigate('/error')
await waitFor(1000)
expect(await page.nuxt.errorData()).toEqual({ statusCode: 500 })
expect(await page.$text('.title')).toBe('Error mouahahah')
})
test('/error2', async () => {
await page.nuxt.navigate('/error2')
await waitFor(1000)
expect(await page.$text('.title')).toBe('Custom error')
expect(await page.nuxt.errorData()).toEqual({ message: 'Custom error' })
})
test('/redirect-middleware', async () => {
await page.nuxt.navigate('/redirect-middleware')
await waitFor(1000)
expect(await page.$text('h1')).toBe('Index page')
})
test('/redirect-external', async () => {
// New page for redirecting to external link.
const page = await browser.page(url('/'))
await page.nuxt.navigate('/redirect-external', false)
await waitFor(1000)
await page.waitForFunction(
() => window.location.href === 'https://nuxtjs.org/'
)
page.close()
})
test('/redirect-name', async () => {
await page.nuxt.navigate('/redirect-name')
await waitFor(1000)
expect(await page.$text('h1')).toBe('My component!')
})
test('/no-ssr', async () => {
await page.nuxt.navigate('/no-ssr')
await waitFor(1000)
expect(await page.$text('h1')).toBe('Displayed only on client-side')
})
test('/meta', async () => {
await page.nuxt.navigate('/meta')
await waitFor(1000)
const state = await page.nuxt.storeState()
expect(state.meta).toEqual([{ works: true }])
})
test('/fn-midd', async () => {
await page.nuxt.navigate('/fn-midd')
await waitFor(1000)
expect(await page.$text('.title')).toBe('You need to ask the permission')
expect(await page.nuxt.errorData()).toEqual({
message: 'You need to ask the permission',
statusCode: 403
})
})
test('/fn-midd?please=true', async () => {
await page.nuxt.navigate('/fn-midd?please=true')
await waitFor(1000)
const h1 = await page.$text('h1')
expect(h1.includes('Date:')).toBe(true)
})
test('/router-guard', async () => {
await page.nuxt.navigate('/router-guard')
await waitFor(1000)
const p = await page.$text('p')
expect(p).toBe('Nuxt.js')
})
test('Stop browser', async () => {
process.on('unhandledRejection', () => { })
await browser.stop()
})
// Close server and ask nuxt to stop listening to file changes
test('Closing server and nuxt.js', async () => {
await nuxt.close()
})
})
test.serial('Open /', async t => {
page = await browser.page(url('/'))
await waitFor(1000)
t.is(await page.$text('h1'), 'Index page')
})
test.serial('/stateless', async t => {
const { hook } = await page.nuxt.navigate('/stateless', false)
const loading = await page.nuxt.loadingData()
await waitFor(1000)
t.is(loading.show, true)
await hook
t.is(await page.$text('h1'), 'My component!')
})
test.serial('/css', async t => {
await page.nuxt.navigate('/css')
await waitFor(1000)
t.is(await page.$text('.red'), 'This is red')
t.is(
await page.$eval('.red', red => window.getComputedStyle(red).color),
'rgb(255, 0, 0)'
)
})
test.serial('/stateful', async t => {
await page.nuxt.navigate('/stateful')
await waitFor(1000)
t.is(await page.$text('p'), 'The answer is 42')
})
test.serial('/store', async t => {
await page.nuxt.navigate('/store')
await waitFor(1000)
t.is(await page.$text('h1'), 'Vuex Nested Modules')
t.is(await page.$text('p'), '1')
})
test.serial('/head', async t => {
const msg = new Promise(resolve =>
page.on('console', msg => resolve(msg.text()))
)
await page.nuxt.navigate('/head')
const metas = await page.$$attr('meta', 'content')
await waitFor(1000)
t.is(await msg, 'Body script!')
t.is(await page.title(), 'My title - Nuxt.js')
t.is(await page.$text('h1'), 'I can haz meta tags')
t.is(metas[0], 'my meta')
})
test.serial('/async-data', async t => {
await page.nuxt.navigate('/async-data')
await waitFor(1000)
t.is(await page.$text('p'), 'Nuxt.js')
})
test.serial('/await-async-data', async t => {
await page.nuxt.navigate('/await-async-data')
await waitFor(1000)
t.is(await page.$text('p'), 'Await Nuxt.js')
})
test.serial('/callback-async-data', async t => {
await page.nuxt.navigate('/callback-async-data')
await waitFor(1000)
t.is(await page.$text('p'), 'Callback Nuxt.js')
})
test.serial('/users/1', async t => {
await page.nuxt.navigate('/users/1')
await waitFor(1000)
t.is(await page.$text('h1'), 'User: 1')
})
test.serial('/validate should display a 404', async t => {
await page.nuxt.navigate('/validate')
await waitFor(1000)
const error = await page.nuxt.errorData()
t.is(error.statusCode, 404)
t.is(error.message, 'This page could not be found')
})
test.serial('/validate?valid=true', async t => {
await page.nuxt.navigate('/validate?valid=true')
await waitFor(1000)
t.is(await page.$text('h1'), 'I am valid')
})
test.serial('/redirect', async t => {
await page.nuxt.navigate('/redirect')
await waitFor(1000)
t.is(await page.$text('h1'), 'Index page')
})
test.serial('/error', async t => {
await page.nuxt.navigate('/error')
await waitFor(1000)
t.deepEqual(await page.nuxt.errorData(), { statusCode: 500 })
t.is(await page.$text('.title'), 'Error mouahahah')
})
test.serial('/error2', async t => {
await page.nuxt.navigate('/error2')
await waitFor(1000)
t.is(await page.$text('.title'), 'Custom error')
t.deepEqual(await page.nuxt.errorData(), { message: 'Custom error' })
})
test.serial('/redirect-middleware', async t => {
await page.nuxt.navigate('/redirect-middleware')
await waitFor(1000)
t.is(await page.$text('h1'), 'Index page')
})
test.serial('/redirect-external', async t => {
// New page for redirecting to external link.
const page = await browser.page(url('/'))
await page.nuxt.navigate('/redirect-external', false)
await waitFor(1000)
await page.waitForFunction(
() => window.location.href === 'https://nuxtjs.org/'
)
page.close()
t.pass()
})
test.serial('/redirect-name', async t => {
await page.nuxt.navigate('/redirect-name')
await waitFor(1000)
t.is(await page.$text('h1'), 'My component!')
})
test.serial('/no-ssr', async t => {
await page.nuxt.navigate('/no-ssr')
await waitFor(1000)
t.is(await page.$text('h1'), 'Displayed only on client-side')
})
test.serial('/meta', async t => {
await page.nuxt.navigate('/meta')
await waitFor(1000)
const state = await page.nuxt.storeState()
t.deepEqual(state.meta, [{ works: true }])
})
test.serial('/fn-midd', async t => {
await page.nuxt.navigate('/fn-midd')
await waitFor(1000)
t.is(await page.$text('.title'), 'You need to ask the permission')
t.deepEqual(await page.nuxt.errorData(), {
message: 'You need to ask the permission',
statusCode: 403
})
})
test.serial('/fn-midd?please=true', async t => {
await page.nuxt.navigate('/fn-midd?please=true')
await waitFor(1000)
const h1 = await page.$text('h1')
t.true(h1.includes('Date:'))
})
test.serial('/router-guard', async t => {
await page.nuxt.navigate('/router-guard')
await waitFor(1000)
const p = await page.$text('p')
t.is(p, 'Nuxt.js')
})
test.after.always('Stop browser', async () => {
process.on('unhandledRejection', () => {})
await browser.stop()
})
// Close server and ask nuxt to stop listening to file changes
test.after.always('Closing server and nuxt.js', async () => {
await nuxt.close()
})

View File

@ -1,6 +1,4 @@
import test from 'ava'
import { resolve } from 'path'
import { intercept, release } from './helpers/console'
import { Nuxt, Builder } from '..'
const port = 4001
@ -9,59 +7,56 @@ const rootDir = resolve(__dirname, 'fixtures/basic')
let nuxt = null
// Init nuxt.js and create server listening on localhost:4000
test.serial('Init Nuxt.js', async t => {
const options = {
rootDir,
buildDir: '.nuxt-dev',
dev: true,
build: {
stats: false,
profile: true,
extractCSS: {
allChunks: true
describe('basic dev', () => {
// Init nuxt.js and create server listening on localhost:4000
beforeAll(async () => {
const options = {
rootDir,
buildDir: '.nuxt-dev',
dev: true,
build: {
stats: false,
profile: true,
extractCSS: {
allChunks: true
}
}
}
}
const spies = await intercept({ log: true, stderr: true }, async () => {
nuxt = new Nuxt(options)
await new Builder(nuxt).build()
new Builder(nuxt).build()
await nuxt.listen(port, 'localhost')
}, 30000)
// TODO: enable test when style-loader.js:60 was resolved
// test.serial('/extractCSS', async t => {
// const window = await nuxt.renderAndGetWindow(url('/extractCSS'))
// const html = window.document.head.innerHTML
// t.true(html.includes('vendor.css'))
// t.true(!html.includes('30px'))
// t.is(window.getComputedStyle(window.document.body).getPropertyValue('font-size'), '30px')
// })
test('/stateless', async () => {
// const spies = await intercept()
const window = await nuxt.renderAndGetWindow(url('/stateless'))
const html = window.document.body.innerHTML
expect(html.includes('<h1>My component!</h1>')).toBe(true)
// expect(spies.info.calledWithMatch('You are running Vue in development mode.')).toBe(true)
// release()
})
t.true(spies.log.calledWithMatch('DONE'))
t.true(spies.log.calledWithMatch('OPEN'))
})
// TODO: enable test when style-loader.js:60 was resolved
// test.serial('/extractCSS', async t => {
// const window = await nuxt.renderAndGetWindow(url('/extractCSS'))
// const html = window.document.head.innerHTML
// t.true(html.includes('vendor.css'))
// t.true(!html.includes('30px'))
// t.is(window.getComputedStyle(window.document.body).getPropertyValue('font-size'), '30px')
// })
test.serial('/stateless', async t => {
const spies = await intercept()
const window = await nuxt.renderAndGetWindow(url('/stateless'))
const html = window.document.body.innerHTML
t.true(html.includes('<h1>My component!</h1>'))
t.true(spies.info.calledWithMatch('You are running Vue in development mode.'))
release()
})
// test('/_nuxt/test.hot-update.json should returns empty html', async t => {
// try {
// await rp(url('/_nuxt/test.hot-update.json'))
// } catch (err) {
// t.is(err.statusCode, 404)
// t.is(err.response.body, '')
// }
// })
// Close server and ask nuxt to stop listening to file changes
test.after.always('Closing server and nuxt.js', async t => {
await nuxt.close()
// test('/_nuxt/test.hot-update.json should returns empty html', async t => {
// try {
// await rp(url('/_nuxt/test.hot-update.json'))
// } catch (err) {
// t.is(err.statusCode, 404)
// t.is(err.response.body, '')
// }
// })
// Close server and ask nuxt to stop listening to file changes
test('Closing server and nuxt.js', async () => {
await nuxt.close()
})
})

View File

@ -1,34 +1,28 @@
import { resolve } from 'path'
import test from 'ava'
import { Nuxt, Builder, Generator } from '..'
import { intercept } from './helpers/console'
test('Fail with routes() which throw an error', async t => {
const options = {
rootDir: resolve(__dirname, 'fixtures/basic'),
buildDir: '.nuxt-fail',
dev: false,
build: {
stats: false
},
generate: {
async routes() {
throw new Error('Not today!')
describe('basic fail generate', () => {
test('Fail with routes() which throw an error', async () => {
const options = {
rootDir: resolve(__dirname, 'fixtures/basic'),
buildDir: '.nuxt-fail',
dev: false,
build: {
stats: false
},
generate: {
async routes() {
throw new Error('Not today!')
}
}
}
}
const spies = await intercept(async () => {
const nuxt = new Nuxt(options)
const builder = new Builder(nuxt)
const generator = new Generator(nuxt, builder)
return generator.generate().catch(e => {
t.true(e.message === 'Not today!')
await generator.generate().catch(e => {
expect(e.message === 'Not today!').toBe(true)
})
})
t.true(spies.log.calledWithMatch('DONE'))
t.true(spies.error.withArgs('Could not resolve routes').calledOnce)
}, 30000)
})

View File

@ -2,7 +2,6 @@ import { existsSync } from 'fs'
import http from 'http'
import { resolve } from 'path'
import test from 'ava'
import { remove } from 'fs-extra'
import serveStatic from 'serve-static'
import finalhandler from 'finalhandler'
@ -10,7 +9,6 @@ import rp from 'request-promise-native'
import { Nuxt, Builder, Generator } from '..'
import { interceptLog, release } from './helpers/console'
import { loadConfig } from './helpers/config'
const port = 4002
@ -21,170 +19,181 @@ let nuxt = null
let server = null
let generator = null
// Init nuxt.js and create server listening on localhost:4000
test.serial('Init Nuxt.js', async t => {
const config = loadConfig('basic', {
buildDir: '.nuxt-generate',
dev: false
})
describe('basic generate', () => {
// Init nuxt.js and create server listening on localhost:4000
beforeAll(async () => {
const config = loadConfig('basic', {
buildDir: '.nuxt-generate',
dev: false
})
config.build.stats = false
config.build.stats = false
const logSpy = await interceptLog(async () => {
nuxt = new Nuxt(config)
const builder = new Builder(nuxt)
generator = new Generator(nuxt, builder)
await generator.generate()
const serve = serveStatic(resolve(__dirname, 'fixtures/basic/dist'))
server = http.createServer((req, res) => {
serve(req, res, finalhandler(req, res))
})
server.listen(port)
}, 30000)
test('Check ready hook called', async () => {
expect(nuxt.__hook_called__).toBe(true)
})
t.true(logSpy.calledWithMatch('DONE'))
const serve = serveStatic(resolve(__dirname, 'fixtures/basic/dist'))
server = http.createServer((req, res) => {
serve(req, res, finalhandler(req, res))
test('/stateless', async () => {
const window = await nuxt.renderAndGetWindow(url('/stateless'))
const html = window.document.body.innerHTML
expect(html.includes('<h1>My component!</h1>')).toBe(true)
})
test('/css', async () => {
const window = await nuxt.renderAndGetWindow(url('/css'))
const headHtml = window.document.head.innerHTML
expect(headHtml.includes('.red{color:red}')).toBe(true)
const element = window.document.querySelector('.red')
expect(element).not.toBe(null)
expect(element.textContent).toBe('This is red')
expect(element.className).toBe('red')
// t.is(window.getComputedStyle(element), 'red')
})
test('/stateful', async () => {
const window = await nuxt.renderAndGetWindow(url('/stateful'))
const html = window.document.body.innerHTML
expect(html.includes('<div><p>The answer is 42</p></div>')).toBe(true)
})
test('/head', async () => {
// const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/head'))
const html = window.document.body.innerHTML
const metas = window.document.getElementsByTagName('meta')
expect(window.document.title).toBe('My title')
expect(metas[0].getAttribute('content')).toBe('my meta')
expect(html.includes('<div><h1>I can haz meta tags</h1></div>')).toBe(true)
// release()
// expect(logSpy.getCall(0).args[0]).toBe('Body script!')
})
test('/async-data', async () => {
const window = await nuxt.renderAndGetWindow(url('/async-data'))
const html = window.document.body.innerHTML
expect(html.includes('<p>Nuxt.js</p>')).toBe(true)
})
test('/users/1/index.html', async () => {
const html = await rp(url('/users/1/index.html'))
expect(html.includes('<h1>User: 1</h1>')).toBe(true)
expect(
existsSync(resolve(__dirname, 'fixtures/basic/dist', 'users/1/index.html'))
).toBe(true)
expect(existsSync(resolve(__dirname, 'fixtures/basic/dist', 'users/1.html'))).toBe(false)
})
test('/users/2', async () => {
const html = await rp(url('/users/2'))
expect(html.includes('<h1>User: 2</h1>')).toBe(true)
})
test('/users/3 (payload given)', async () => {
const html = await rp(url('/users/3'))
expect(html.includes('<h1>User: 3000</h1>')).toBe(true)
})
test('/users/4 -> Not found', async () => {
await expect(rp(url('/users/4'))).rejects.toMatchObject({
statusCode: 404,
response: {
body: expect.stringContaining('Cannot GET /users/4')
}
})
})
test('/validate should not be server-rendered', async () => {
const html = await rp(url('/validate'))
expect(html.includes('<div id="__nuxt"></div>')).toBe(true)
expect(html.includes('serverRendered:!1')).toBe(true)
})
test('/validate -> should display a 404', async () => {
const window = await nuxt.renderAndGetWindow(url('/validate'))
const html = window.document.body.innerHTML
expect(html.includes('This page could not be found')).toBe(true)
})
test('/validate?valid=true', async () => {
const window = await nuxt.renderAndGetWindow(url('/validate?valid=true'))
const html = window.document.body.innerHTML
expect(html.includes('I am valid</h1>')).toBe(true)
})
test('/redirect should not be server-rendered', async () => {
const html = await rp(url('/redirect'))
expect(html.includes('<div id="__nuxt"></div>')).toBe(true)
expect(html.includes('serverRendered:!1')).toBe(true)
})
test('/redirect -> check redirected source', async () => {
const window = await nuxt.renderAndGetWindow(url('/redirect'))
const html = window.document.body.innerHTML
expect(html.includes('<h1>Index page</h1>')).toBe(true)
})
test('/users/1 not found', async () => {
await remove(resolve(rootDir, 'dist/users'))
await expect(rp(url('/users/1'))).rejects.toMatchObject({
statusCode: 404,
response: {
body: expect.stringContaining('Cannot GET /users/1')
}
})
})
test('nuxt re-generating with no subfolders', async () => {
// const logSpy = await interceptLog()
nuxt.options.generate.subFolders = false
await generator.generate()
// release()
// expect(logSpy.calledWithMatch('DONE')).toBe(true)
})
test('/users/1.html', async () => {
const html = await rp(url('/users/1.html'))
expect(html.includes('<h1>User: 1</h1>')).toBe(true)
expect(existsSync(resolve(__dirname, 'fixtures/basic/dist', 'users/1.html'))).toBe(true)
expect(
existsSync(resolve(__dirname, 'fixtures/basic/dist', 'users/1/index.html'))
).toBe(false)
})
test('/-ignored', async () => {
await expect(rp(url('/-ignored'))).rejects.toMatchObject({
statusCode: 404,
response: {
body: expect.stringContaining('Cannot GET /-ignored')
}
})
})
test('/ignored.test', async () => {
await expect(rp(url('/ignored.test'))).rejects.toMatchObject({
statusCode: 404,
response: {
body: expect.stringContaining('Cannot GET /ignored.test')
}
})
})
// Close server and ask nuxt to stop listening to file changes
test('Closing server', async () => {
await server.close()
})
server.listen(port)
})
test.serial('Check ready hook called', async t => {
t.true(nuxt.__hook_called__)
})
test.serial('/stateless', async t => {
const window = await nuxt.renderAndGetWindow(url('/stateless'))
const html = window.document.body.innerHTML
t.true(html.includes('<h1>My component!</h1>'))
})
test.serial('/css', async t => {
const window = await nuxt.renderAndGetWindow(url('/css'))
const headHtml = window.document.head.innerHTML
t.true(headHtml.includes('.red{color:red}'))
const element = window.document.querySelector('.red')
t.not(element, null)
t.is(element.textContent, 'This is red')
t.is(element.className, 'red')
// t.is(window.getComputedStyle(element), 'red')
})
test.serial('/stateful', async t => {
const window = await nuxt.renderAndGetWindow(url('/stateful'))
const html = window.document.body.innerHTML
t.true(html.includes('<div><p>The answer is 42</p></div>'))
})
test.serial('/head', async t => {
const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/head'))
const html = window.document.body.innerHTML
const metas = window.document.getElementsByTagName('meta')
t.is(window.document.title, 'My title')
t.is(metas[0].getAttribute('content'), 'my meta')
t.true(html.includes('<div><h1>I can haz meta tags</h1></div>'))
release()
t.is(logSpy.getCall(0).args[0], 'Body script!')
})
test.serial('/async-data', async t => {
const window = await nuxt.renderAndGetWindow(url('/async-data'))
const html = window.document.body.innerHTML
t.true(html.includes('<p>Nuxt.js</p>'))
})
test.serial('/users/1/index.html', async t => {
const html = await rp(url('/users/1/index.html'))
t.true(html.includes('<h1>User: 1</h1>'))
t.true(
existsSync(resolve(__dirname, 'fixtures/basic/dist', 'users/1/index.html'))
)
t.false(existsSync(resolve(__dirname, 'fixtures/basic/dist', 'users/1.html')))
})
test.serial('/users/2', async t => {
const html = await rp(url('/users/2'))
t.true(html.includes('<h1>User: 2</h1>'))
})
test.serial('/users/3 (payload given)', async t => {
const html = await rp(url('/users/3'))
t.true(html.includes('<h1>User: 3000</h1>'))
})
test.serial('/users/4 -> Not found', async t => {
const error = await t.throws(rp(url('/users/4')))
t.true(error.statusCode === 404)
t.true(error.response.body.includes('Cannot GET /users/4'))
})
test.serial('/validate should not be server-rendered', async t => {
const html = await rp(url('/validate'))
t.true(html.includes('<div id="__nuxt"></div>'))
t.true(html.includes('serverRendered:!1'))
})
test.serial('/validate -> should display a 404', async t => {
const window = await nuxt.renderAndGetWindow(url('/validate'))
const html = window.document.body.innerHTML
t.true(html.includes('This page could not be found'))
})
test.serial('/validate?valid=true', async t => {
const window = await nuxt.renderAndGetWindow(url('/validate?valid=true'))
const html = window.document.body.innerHTML
t.true(html.includes('I am valid</h1>'))
})
test.serial('/redirect should not be server-rendered', async t => {
const html = await rp(url('/redirect'))
t.true(html.includes('<div id="__nuxt"></div>'))
t.true(html.includes('serverRendered:!1'))
})
test.serial('/redirect -> check redirected source', async t => {
const window = await nuxt.renderAndGetWindow(url('/redirect'))
const html = window.document.body.innerHTML
t.true(html.includes('<h1>Index page</h1>'))
})
test.serial('/users/1 not found', async t => {
await remove(resolve(rootDir, 'dist/users'))
const error = await t.throws(rp(url('/users/1')))
t.true(error.statusCode === 404)
t.true(error.response.body.includes('Cannot GET /users/1'))
})
test.serial('nuxt re-generating with no subfolders', async t => {
const logSpy = await interceptLog()
nuxt.options.generate.subFolders = false
await generator.generate()
release()
t.true(logSpy.calledWithMatch('DONE'))
})
test.serial('/users/1.html', async t => {
const html = await rp(url('/users/1.html'))
t.true(html.includes('<h1>User: 1</h1>'))
t.true(existsSync(resolve(__dirname, 'fixtures/basic/dist', 'users/1.html')))
t.false(
existsSync(resolve(__dirname, 'fixtures/basic/dist', 'users/1/index.html'))
)
})
test.serial('/-ignored', async t => {
const error = await t.throws(rp(url('/-ignored')))
t.true(error.statusCode === 404)
t.true(error.response.body.includes('Cannot GET /-ignored'))
})
test.serial('/ignored.test', async t => {
const error = await t.throws(rp(url('/ignored.test')))
t.true(error.statusCode === 404)
t.true(error.response.body.includes('Cannot GET /ignored.test'))
})
// Close server and ask nuxt to stop listening to file changes
test.after.always('Closing server', async t => {
await server.close()
})

View File

@ -1,125 +1,128 @@
import { resolve } from 'path'
import test from 'ava'
import rp from 'request-promise-native'
import { Nuxt, Builder } from '..'
import { interceptLog } from './helpers/console'
const port = 4005
const url = route => 'http://localhost:' + port + route
// Init nuxt.js and create server listening on localhost:4005
const startCSPTestServer = async (t, csp) => {
const startCSPTestServer = async (csp) => {
const options = {
rootDir: resolve(__dirname, 'fixtures/basic'),
buildDir: '.nuxt-ssr-csp',
dev: false,
head: {
titleTemplate(titleChunk) {
return titleChunk ? `${titleChunk} - Nuxt.js` : 'Nuxt.js'
}
},
build: { stats: false },
render: { csp }
}
let nuxt = null
const logSpy = await interceptLog(async () => {
nuxt = new Nuxt(options)
const builder = await new Builder(nuxt)
await builder.build()
await nuxt.listen(port, '0.0.0.0')
})
t.true(logSpy.calledWithMatch('DONE'))
t.true(logSpy.calledWithMatch('OPEN'))
nuxt = new Nuxt(options)
const builder = new Builder(nuxt)
await builder.build()
await nuxt.listen(port, '0.0.0.0')
return nuxt
}
test.serial('Not contain Content-Security-Policy header, when csp.enabled is not set', async t => {
const nuxt = await startCSPTestServer(t, {})
const { headers } = await rp(url('/stateless'), {
resolveWithFullResponse: true
})
describe('basic ssr csp', () => {
test(
'Not contain Content-Security-Policy header, when csp.enabled is not set',
async () => {
const nuxt = await startCSPTestServer({})
const { headers } = await rp(url('/stateless'), {
resolveWithFullResponse: true
})
t.is(headers['content-security-policy'], undefined)
expect(headers['content-security-policy']).toBe(undefined)
await nuxt.close()
})
test.serial('Contain Content-Security-Policy header, when csp.enabled is only set', async t => {
const cspOption = {
enabled: true
}
const nuxt = await startCSPTestServer(t, cspOption)
const { headers } = await rp(url('/stateless'), {
resolveWithFullResponse: true
})
t.regex(headers['content-security-policy'], /^script-src 'self' 'sha256-.*'$/)
await nuxt.close()
})
test.serial('Contain Content-Security-Policy header, when csp.allowedSources set', async t => {
const cspOption = {
enabled: true,
allowedSources: ['https://example.com', 'https://example.io']
}
const nuxt = await startCSPTestServer(t, cspOption)
const { headers } = await rp(url('/stateless'), {
resolveWithFullResponse: true
})
t.regex(headers['content-security-policy'], /^script-src 'self' 'sha256-.*'/)
t.true(headers['content-security-policy'].includes('https://example.com'))
t.true(headers['content-security-policy'].includes('https://example.io'))
await nuxt.close()
})
test.serial('Contain Content-Security-Policy header, when csp.policies set', async t => {
const cspOption = {
enabled: true,
policies: {
'default-src': [`'none'`],
'script-src': ['https://example.com', 'https://example.io']
await nuxt.close()
}
}
)
const nuxt = await startCSPTestServer(t, cspOption)
const { headers } = await rp(url('/stateless'), {
resolveWithFullResponse: true
})
test(
'Contain Content-Security-Policy header, when csp.enabled is only set',
async () => {
const cspOption = {
enabled: true
}
t.regex(headers['content-security-policy'], /default-src 'none'/)
t.regex(headers['content-security-policy'], /script-src 'self' 'sha256-.*'/)
t.true(headers['content-security-policy'].includes('https://example.com'))
t.true(headers['content-security-policy'].includes('https://example.io'))
const nuxt = await startCSPTestServer(cspOption)
const { headers } = await rp(url('/stateless'), {
resolveWithFullResponse: true
})
await nuxt.close()
})
expect(headers['content-security-policy']).toMatch(/^script-src 'self' 'sha256-.*'$/)
test.serial('Contain Content-Security-Policy header, when csp.policies.script-src is not set', async t => {
const cspOption = {
enabled: true,
policies: {
'default-src': [`'none'`]
await nuxt.close()
}
}
)
const nuxt = await startCSPTestServer(t, cspOption)
const { headers } = await rp(url('/stateless'), {
resolveWithFullResponse: true
})
test(
'Contain Content-Security-Policy header, when csp.allowedSources set',
async () => {
const cspOption = {
enabled: true,
allowedSources: ['https://example.com', 'https://example.io']
}
t.regex(headers['content-security-policy'], /default-src 'none'/)
t.regex(headers['content-security-policy'], /script-src 'self' 'sha256-.*'/)
const nuxt = await startCSPTestServer(cspOption)
const { headers } = await rp(url('/stateless'), {
resolveWithFullResponse: true
})
await nuxt.close()
expect(headers['content-security-policy']).toMatch(/^script-src 'self' 'sha256-.*'/)
expect(headers['content-security-policy'].includes('https://example.com')).toBe(true)
expect(headers['content-security-policy'].includes('https://example.io')).toBe(true)
await nuxt.close()
}
)
test(
'Contain Content-Security-Policy header, when csp.policies set',
async () => {
const cspOption = {
enabled: true,
policies: {
'default-src': [`'none'`],
'script-src': ['https://example.com', 'https://example.io']
}
}
const nuxt = await startCSPTestServer(cspOption)
const { headers } = await rp(url('/stateless'), {
resolveWithFullResponse: true
})
expect(headers['content-security-policy']).toMatch(/default-src 'none'/)
expect(headers['content-security-policy']).toMatch(/script-src 'self' 'sha256-.*'/)
expect(headers['content-security-policy'].includes('https://example.com')).toBe(true)
expect(headers['content-security-policy'].includes('https://example.io')).toBe(true)
await nuxt.close()
}
)
test(
'Contain Content-Security-Policy header, when csp.policies.script-src is not set',
async () => {
const cspOption = {
enabled: true,
policies: {
'default-src': [`'none'`]
}
}
const nuxt = await startCSPTestServer(cspOption)
const { headers } = await rp(url('/stateless'), {
resolveWithFullResponse: true
})
expect(headers['content-security-policy']).toMatch(/default-src 'none'/)
expect(headers['content-security-policy']).toMatch(/script-src 'self' 'sha256-.*'/)
await nuxt.close()
}
)
})

View File

@ -1,312 +1,285 @@
import { resolve } from 'path'
import test from 'ava'
import rp from 'request-promise-native'
import { Nuxt, Builder } from '..'
import { interceptLog, interceptError, release } from './helpers/console'
import { loadConfig } from './helpers/config'
const port = 4004
const url = route => 'http://localhost:' + port + route
let nuxt = null
// Init nuxt.js and create server listening on localhost:4004
test.serial('Init Nuxt.js', async t => {
const options = {
rootDir: resolve(__dirname, 'fixtures/basic'),
buildDir: '.nuxt-ssr',
dev: false,
head: {
titleTemplate(titleChunk) {
return titleChunk ? `${titleChunk} - Nuxt.js` : 'Nuxt.js'
describe('basic ssr', () => {
// Init nuxt.js and create server listening on localhost:4004
beforeAll(async () => {
const options = loadConfig('basic', {
buildDir: '.nuxt-ssr',
dev: false,
build: {
stats: false
}
},
build: {
stats: false
}
}
})
const logSpy = await interceptLog(async () => {
nuxt = new Nuxt(options)
const builder = await new Builder(nuxt)
const builder = new Builder(nuxt)
await builder.build()
await nuxt.listen(port, '0.0.0.0')
}, 30000)
test('/stateless', async () => {
const { html } = await nuxt.renderRoute('/stateless')
expect(html.includes('<h1>My component!</h1>')).toBe(true)
})
t.true(logSpy.calledWithMatch('DONE'))
t.true(logSpy.calledWithMatch('OPEN'))
})
/*
** Example of testing via dom checking
*/
test('/css', async () => {
const window = await nuxt.renderAndGetWindow(url('/css'))
test('/stateless', async t => {
const { html } = await nuxt.renderRoute('/stateless')
t.true(html.includes('<h1>My component!</h1>'))
})
const headHtml = window.document.head.innerHTML
expect(headHtml.includes('color:red')).toBe(true)
/*
** Example of testing via dom checking
*/
test('/css', async t => {
const window = await nuxt.renderAndGetWindow(url('/css'))
const headHtml = window.document.head.innerHTML
t.true(headHtml.includes('color:red'))
const element = window.document.querySelector('.red')
t.not(element, null)
t.is(element.textContent, 'This is red')
t.is(element.className, 'red')
// t.is(window.getComputedStyle(element).color, 'red')
})
test('/postcss', async t => {
const window = await nuxt.renderAndGetWindow(url('/css'))
const headHtml = window.document.head.innerHTML
t.true(headHtml.includes('background-color:blue'))
// const element = window.document.querySelector('div.red')
// t.is(window.getComputedStyle(element)['background-color'], 'blue')
})
test('/stateful', async t => {
const { html } = await nuxt.renderRoute('/stateful')
t.true(html.includes('<div><p>The answer is 42</p></div>'))
})
test('/store', async t => {
const { html } = await nuxt.renderRoute('/store')
t.true(html.includes('<h1>Vuex Nested Modules</h1>'))
t.true(html.includes('<p>1</p>'))
})
test.serial('/head', async t => {
const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/head'), {
virtualConsole: false
const element = window.document.querySelector('.red')
expect(element).not.toBe(null)
expect(element.textContent).toBe('This is red')
expect(element.className).toBe('red')
// t.is(window.getComputedStyle(element).color, 'red')
})
t.is(window.document.title, 'My title - Nuxt.js')
const html = window.document.body.innerHTML
t.true(html.includes('<div><h1>I can haz meta tags</h1></div>'))
t.true(
html.includes('<script data-n-head="true" src="/body.js" data-body="true">')
)
test('/postcss', async () => {
const window = await nuxt.renderAndGetWindow(url('/css'))
const metas = window.document.getElementsByTagName('meta')
t.is(metas[0].getAttribute('content'), 'my meta')
release()
const headHtml = window.document.head.innerHTML
expect(headHtml.includes('background-color:blue')).toBe(true)
t.true(logSpy.calledOnce)
t.is(logSpy.args[0][0], 'Body script!')
})
test('/async-data', async t => {
const { html } = await nuxt.renderRoute('/async-data')
t.true(html.includes('<p>Nuxt.js</p>'))
})
test('/await-async-data', async t => {
const { html } = await nuxt.renderRoute('/await-async-data')
t.true(html.includes('<p>Await Nuxt.js</p>'))
})
test('/callback-async-data', async t => {
const { html } = await nuxt.renderRoute('/callback-async-data')
t.true(html.includes('<p>Callback Nuxt.js</p>'))
})
test('/users/1', async t => {
const { html } = await nuxt.renderRoute('/users/1')
t.true(html.includes('<h1>User: 1</h1>'))
})
test('/validate should display a 404', async t => {
const { html } = await nuxt.renderRoute('/validate')
t.true(html.includes('This page could not be found'))
})
test('/validate?valid=true', async t => {
const { html } = await nuxt.renderRoute('/validate?valid=true')
t.true(html.includes('<h1>I am valid</h1>'))
})
test('/redirect', async t => {
const { html, redirected } = await nuxt.renderRoute('/redirect')
t.true(html.includes('<div id="__nuxt"></div>'))
t.true(redirected.path === '/')
t.true(redirected.status === 302)
})
test('/redirect -> check redirected source', async t => {
// there are no transition properties in jsdom, ignore the error log
await interceptError()
const window = await nuxt.renderAndGetWindow(url('/redirect'))
release()
const html = window.document.body.innerHTML
t.true(html.includes('<h1>Index page</h1>'))
})
test('/redirect -> external link', async t => {
let _headers, _status
const { html } = await nuxt.renderRoute('/redirect-external', {
res: {
writeHead(status, headers) {
_status = status
_headers = headers
},
end() {}
}
// const element = window.document.querySelector('div.red')
// t.is(window.getComputedStyle(element)['background-color'], 'blue')
})
t.is(_status, 302)
t.is(_headers.Location, 'https://nuxtjs.org')
t.true(html.includes('<div data-server-rendered="true"></div>'))
})
test('/special-state -> check window.__NUXT__.test = true', async t => {
const window = await nuxt.renderAndGetWindow(url('/special-state'))
t.is(window.document.title, 'Nuxt.js')
t.is(window.__NUXT__.test, true)
})
test('/stateful', async () => {
const { html } = await nuxt.renderRoute('/stateful')
expect(html.includes('<div><p>The answer is 42</p></div>')).toBe(true)
})
test('/error', async t => {
const err = await t.throws(nuxt.renderRoute('/error', { req: {}, res: {} }))
t.true(err.message.includes('Error mouahahah'))
})
test('/store', async () => {
const { html } = await nuxt.renderRoute('/store')
expect(html.includes('<h1>Vuex Nested Modules</h1>')).toBe(true)
expect(html.includes('<p>1</p>')).toBe(true)
})
test.serial('/error status code', async t => {
const errorSpy = await interceptError()
const err = await t.throws(rp(url('/error')))
t.true(err.statusCode === 500)
t.true(
err.response.body.includes(
'An error occurred in the application and your page could not be served'
)
)
release()
t.true(errorSpy.calledOnce)
t.true(errorSpy.args[0][0].message.includes('Error mouahahah'))
})
test('/head', async () => {
// const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/head'), {
virtualConsole: false
})
expect(window.document.title).toBe('My title - Nuxt.js')
test('/error2', async t => {
const { html, error } = await nuxt.renderRoute('/error2')
t.true(html.includes('Custom error'))
t.true(error.message.includes('Custom error'))
t.true(error.statusCode === undefined)
})
const html = window.document.body.innerHTML
expect(html.includes('<div><h1>I can haz meta tags</h1></div>')).toBe(true)
expect(
html.includes('<script data-n-head="true" src="/body.js" data-body="true">')
).toBe(true)
test('/error2 status code', async t => {
const error = await t.throws(rp(url('/error2')))
t.is(error.statusCode, 500)
t.true(error.response.body.includes('Custom error'))
})
const metas = window.document.getElementsByTagName('meta')
expect(metas[0].getAttribute('content')).toBe('my meta')
// release()
test.serial('/error-midd', async t => {
const errorSpy = await interceptError()
const err = await t.throws(rp(url('/error-midd')))
t.is(err.statusCode, 505)
t.true(err.response.body.includes('Middleware Error'))
release()
// Don't display error since redirect returns a noopApp
t.true(errorSpy.notCalled)
})
// expect(logSpy.calledOnce).toBe(true)
// expect(logSpy.args[0][0]).toBe('Body script!')
})
test.serial('/redirect-middleware', async t => {
const errorSpy = await interceptError()
await rp(url('/redirect-middleware')) // Should not console.error
release()
// Don't display error since redirect returns a noopApp
t.true(errorSpy.notCalled)
})
test('/async-data', async () => {
const { html } = await nuxt.renderRoute('/async-data')
expect(html.includes('<p>Nuxt.js</p>')).toBe(true)
})
test('/redirect-name', async t => {
const { html, redirected } = await nuxt.renderRoute('/redirect-name')
t.true(html.includes('<div id="__nuxt"></div>'))
t.true(redirected.path === '/stateless')
t.true(redirected.status === 302)
})
test('/await-async-data', async () => {
const { html } = await nuxt.renderRoute('/await-async-data')
expect(html.includes('<p>Await Nuxt.js</p>')).toBe(true)
})
test('/no-ssr', async t => {
const { html } = await nuxt.renderRoute('/no-ssr')
t.true(
html.includes(
test('/callback-async-data', async () => {
const { html } = await nuxt.renderRoute('/callback-async-data')
expect(html.includes('<p>Callback Nuxt.js</p>')).toBe(true)
})
test('/users/1', async () => {
const { html } = await nuxt.renderRoute('/users/1')
expect(html.includes('<h1>User: 1</h1>')).toBe(true)
})
test('/validate should display a 404', async () => {
const { html } = await nuxt.renderRoute('/validate')
expect(html.includes('This page could not be found')).toBe(true)
})
test('/validate?valid=true', async () => {
const { html } = await nuxt.renderRoute('/validate?valid=true')
expect(html.includes('<h1>I am valid</h1>')).toBe(true)
})
test('/redirect', async () => {
const { html, redirected } = await nuxt.renderRoute('/redirect')
expect(html.includes('<div id="__nuxt"></div>')).toBe(true)
expect(redirected.path === '/').toBe(true)
expect(redirected.status === 302).toBe(true)
})
test('/redirect -> check redirected source', async () => {
// there are no transition properties in jsdom, ignore the error log
// await interceptError()
const window = await nuxt.renderAndGetWindow(url('/redirect'))
// release()
const html = window.document.body.innerHTML
expect(html.includes('<h1>Index page</h1>')).toBe(true)
})
test('/redirect -> external link', async () => {
let _headers, _status
const { html } = await nuxt.renderRoute('/redirect-external', {
res: {
writeHead(status, headers) {
_status = status
_headers = headers
},
end() { }
}
})
expect(_status).toBe(302)
expect(_headers.Location).toBe('https://nuxtjs.org')
expect(html.includes('<div data-server-rendered="true"></div>')).toBe(true)
})
test('/special-state -> check window.__NUXT__.test = true', async () => {
const window = await nuxt.renderAndGetWindow(url('/special-state'))
expect(window.document.title).toBe('Nuxt.js')
expect(window.__NUXT__.test).toBe(true)
})
test('/error', async () => {
await expect(nuxt.renderRoute('/error', { req: {}, res: {} }))
.rejects.toThrow('Error mouahahah')
})
test('/error status code', async () => {
// const errorSpy = await interceptError()
await expect(rp(url('/error'))).rejects.toMatchObject({
statusCode: 500
})
// release()
// expect(errorSpy.calledOnce).toBe(true)
// expect(errorSpy.args[0][0].message.includes('Error mouahahah')).toBe(true)
})
test('/error2', async () => {
const { html, error } = await nuxt.renderRoute('/error2')
expect(html.includes('Custom error')).toBe(true)
expect(error.message.includes('Custom error')).toBe(true)
expect(error.statusCode === undefined).toBe(true)
})
test('/error2 status code', async () => {
await expect(rp(url('/error2'))).rejects.toMatchObject({
statusCode: 500,
message: expect.stringContaining('Custom error')
})
})
test('/error-midd', async () => {
// const errorSpy = await interceptError()
await expect(rp(url('/error-midd')))
.rejects.toMatchObject({ statusCode: 505 })
// release()
// Don't display error since redirect returns a noopApp
// expect(errorSpy.notCalled).toBe(true)
})
test('/redirect-middleware', async () => {
// const errorSpy = await interceptError()
await rp(url('/redirect-middleware')) // Should not console.error
// release()
// Don't display error since redirect returns a noopApp
// expect(errorSpy.notCalled).toBe(true)
})
test('/redirect-name', async () => {
const { html, redirected } = await nuxt.renderRoute('/redirect-name')
expect(html.includes('<div id="__nuxt"></div>')).toBe(true)
expect(redirected.path === '/stateless').toBe(true)
expect(redirected.status === 302).toBe(true)
})
test('/no-ssr', async () => {
const { html } = await nuxt.renderRoute('/no-ssr')
expect(html.includes(
'<div class="no-ssr-placeholder">&lt;p&gt;Loading...&lt;/p&gt;</div>'
)
)
})
test('/no-ssr (client-side)', async t => {
const window = await nuxt.renderAndGetWindow(url('/no-ssr'))
const html = window.document.body.innerHTML
t.true(html.includes('Displayed only on client-side</h1>'))
})
test('ETag Header', async t => {
const { headers: { etag } } = await rp(url('/stateless'), {
resolveWithFullResponse: true
)).toBe(true)
})
// Verify functionality
const error = await t.throws(
rp(url('/stateless'), { headers: { 'If-None-Match': etag } })
)
t.is(error.statusCode, 304)
})
test('/_nuxt/server-bundle.json should return 404', async t => {
const err = await t.throws(
rp(url('/_nuxt/server-bundle.json'), { resolveWithFullResponse: true })
)
t.is(err.statusCode, 404)
})
test('/no-ssr (client-side)', async () => {
const window = await nuxt.renderAndGetWindow(url('/no-ssr'))
const html = window.document.body.innerHTML
expect(html.includes('Displayed only on client-side</h1>')).toBe(true)
})
test('/_nuxt/ should return 404', async t => {
const err = await t.throws(
rp(url('/_nuxt/'), { resolveWithFullResponse: true })
)
t.is(err.statusCode, 404)
})
test('ETag Header', async () => {
const { headers: { etag } } = await rp(url('/stateless'), {
resolveWithFullResponse: true
})
// Verify functionality
await expect(rp(url('/stateless'), { headers: { 'If-None-Match': etag } }))
.rejects.toMatchObject({ statusCode: 304 })
})
test('/meta', async t => {
const { html } = await nuxt.renderRoute('/meta')
t.true(html.includes('"meta":[{"works":true}]'))
})
test('/_nuxt/server-bundle.json should return 404', async () => {
await expect(rp(url('/_nuxt/server-bundle.json')))
.rejects.toMatchObject({ statusCode: 404 })
})
test('/fn-midd', async t => {
const err = await t.throws(
rp(url('/fn-midd'), { resolveWithFullResponse: true })
)
t.is(err.statusCode, 403)
t.true(err.response.body.includes('You need to ask the permission'))
})
test('/_nuxt/ should return 404', async () => {
await expect(rp(url('/_nuxt/')))
.rejects.toMatchObject({ statusCode: 404 })
})
test('/fn-midd?please=true', async t => {
const { html } = await nuxt.renderRoute('/fn-midd?please=true')
t.true(html.includes('<h1>Date:'))
})
test('/meta', async () => {
const { html } = await nuxt.renderRoute('/meta')
expect(html.includes('"meta":[{"works":true}]')).toBe(true)
})
test('/router-guard', async t => {
const { html } = await nuxt.renderRoute('/router-guard')
t.true(html.includes('<p>Nuxt.js</p>'))
t.false(html.includes('Router Guard'))
})
test('/fn-midd', async () => {
await expect(rp(url('/fn-midd')))
.rejects.toMatchObject({ statusCode: 403 })
})
test('/jsx', async t => {
const { html } = await nuxt.renderRoute('/jsx')
t.true(html.includes('<h1>JSX Page</h1>'))
})
test('/fn-midd?please=true', async () => {
const { html } = await nuxt.renderRoute('/fn-midd?please=true')
expect(html.includes('<h1>Date:')).toBe(true)
})
test('/jsx-link', async t => {
const { html } = await nuxt.renderRoute('/jsx-link')
t.true(html.includes('<h1>JSX Link Page</h1>'))
})
test('/router-guard', async () => {
const { html } = await nuxt.renderRoute('/router-guard')
expect(html.includes('<p>Nuxt.js</p>')).toBe(true)
expect(html.includes('Router Guard')).toBe(false)
})
test('/js-link', async t => {
const { html } = await nuxt.renderRoute('/js-link')
t.true(html.includes('<h1>vue file is first-class</h1>'))
})
test('/jsx', async () => {
const { html } = await nuxt.renderRoute('/jsx')
expect(html.includes('<h1>JSX Page</h1>')).toBe(true)
})
// Close server and ask nuxt to stop listening to file changes
test.after.always('Closing server and nuxt.js', async t => {
await nuxt.close()
test('/jsx-link', async () => {
const { html } = await nuxt.renderRoute('/jsx-link')
expect(html.includes('<h1>JSX Link Page</h1>')).toBe(true)
})
test('/js-link', async () => {
const { html } = await nuxt.renderRoute('/js-link')
expect(html.includes('<h1>vue file is first-class</h1>')).toBe(true)
})
// Close server and ask nuxt to stop listening to file changes
test('Closing server and nuxt.js', async () => {
await nuxt.close()
})
})

View File

@ -1,11 +1,8 @@
import { resolve } from 'path'
import test from 'ava'
import { Nuxt, Builder, Utils } from '..'
import * as browser from './helpers/browser'
import { interceptLog } from './helpers/console'
const port = 4014
const url = route => 'http://localhost:' + port + route
@ -14,136 +11,133 @@ let nuxt = null
let page
const dates = {}
// Init nuxt.js and create server listening on localhost:4000
test.serial('Init Nuxt.js', async t => {
const options = {
rootDir: resolve(__dirname, 'fixtures/children'),
buildDir: '.nuxt-patch',
dev: false,
build: {
stats: false
describe('children patch', () => {
// Init nuxt.js and create server listening on localhost:4000
beforeAll(async () => {
const options = {
rootDir: resolve(__dirname, 'fixtures/children'),
buildDir: '.nuxt-patch',
dev: false,
build: {
stats: false
}
}
}
const logSpy = await interceptLog(async () => {
nuxt = new Nuxt(options)
await new Builder(nuxt).build()
new Builder(nuxt).build()
await nuxt.listen(port, 'localhost')
}, 30000)
test('Start browser', async () => {
expect.assertions(0) // suppress 'no assertions' warning
await browser.start({
// slowMo: 50,
// headless: false
})
})
t.true(logSpy.calledWithMatch('DONE'))
t.true(logSpy.calledWithMatch('OPEN'))
})
test('Loading /patch and keep ', async () => {
page = await browser.page(url('/patch'))
test.serial('Start browser', async t => {
t.plan(0) // suppress 'no assertions' warning
await browser.start({
// slowMo: 50,
// headless: false
const h1 = await page.$text('h1')
expect(h1.includes('patch:')).toBe(true)
const h2 = await page.$text('h2')
expect(h2).toBe('Index')
dates.patch = await page.$text('[data-date-patch]')
})
test('Navigate to /patch/1', async () => {
const { hook } = await page.nuxt.navigate('/patch/1', false)
const loading = await page.nuxt.loadingData()
expect(loading.show).toBe(true)
await hook
const h2 = await page.$text('h2')
expect(h2.includes('_id:')).toBe(true)
dates.id = await page.$text('[data-date-id]')
expect(dates.patch).toBe(await page.$text('[data-date-patch]'))
})
test('Navigate to /patch/2', async () => {
await page.nuxt.navigate('/patch/2')
const date = await page.$text('[data-date-id]')
expect(await page.$text('h3')).toBe('Index')
expect(dates.patch).toBe(await page.$text('[data-date-patch]'))
expect(+dates.id < +date).toBe(true)
dates.id = date
})
test('Navigate to /patch/2?test=true', async () => {
await page.nuxt.navigate('/patch/2?test=true')
expect(dates.patch).toBe(await page.$text('[data-date-patch]'))
expect(dates.id).toBe(await page.$text('[data-date-id]'))
})
test('Navigate to /patch/2#test', async () => {
await page.nuxt.navigate('/patch/2#test')
expect(dates.patch).toBe(await page.$text('[data-date-patch]'))
expect(dates.id).toBe(await page.$text('[data-date-id]'))
})
test('Navigate to /patch/2/child', async () => {
await page.nuxt.navigate('/patch/2/child')
dates.child = await page.$text('[data-date-child]')
dates.slug = await page.$text('[data-date-child-slug]')
expect(dates.patch).toBe(await page.$text('[data-date-patch]'))
expect(dates.id).toBe(await page.$text('[data-date-id]'))
expect(+dates.child > +dates.id).toBe(true)
expect(+dates.slug > +dates.child).toBe(true)
})
test('Navigate to /patch/2/child/1', async () => {
await page.nuxt.navigate('/patch/2/child/1')
const date = await page.$text('[data-date-child-slug]')
expect(dates.patch).toBe(await page.$text('[data-date-patch]'))
expect(dates.id).toBe(await page.$text('[data-date-id]'))
expect(dates.child).toBe(await page.$text('[data-date-child]'))
expect(+date > +dates.slug).toBe(true)
dates.slug = date
})
test('Navigate to /patch/2/child/1?foo=bar', async () => {
await page.nuxt.navigate('/patch/2/child/1?foo=bar')
expect(dates.patch).toBe(await page.$text('[data-date-patch]'))
expect(dates.id).toBe(await page.$text('[data-date-id]'))
expect(dates.child).toBe(await page.$text('[data-date-child]'))
expect(dates.slug).toBe(await page.$text('[data-date-child-slug]'))
})
test('Search a country', async () => {
const countries = await page.$$text('[data-test-search-result]')
expect(countries.length).toBe(5)
await page.type('[data-test-search-input]', 'gu')
await Utils.waitFor(250)
const newCountries = await page.$$text('[data-test-search-result]')
expect(newCountries.length).toBe(1)
expect(newCountries).toEqual(['Guinea'])
expect(await page.nuxt.routeData()).toEqual({
path: '/patch/2/child/1',
query: {
foo: 'bar',
q: 'gu'
}
})
})
// Close server and ask nuxt to stop listening to file changes
test('Closing server and nuxt.js', async () => {
await nuxt.close()
})
test('Stop browser', async () => {
await page.close()
await browser.stop()
})
})
test.serial('Loading /patch and keep ', async t => {
page = await browser.page(url('/patch'))
const h1 = await page.$text('h1')
t.true(h1.includes('patch:'))
const h2 = await page.$text('h2')
t.is(h2, 'Index')
dates.patch = await page.$text('[data-date-patch]')
})
test.serial('Navigate to /patch/1', async t => {
const { hook } = await page.nuxt.navigate('/patch/1', false)
const loading = await page.nuxt.loadingData()
t.is(loading.show, true)
await hook
const h2 = await page.$text('h2')
t.true(h2.includes('_id:'))
dates.id = await page.$text('[data-date-id]')
t.is(dates.patch, await page.$text('[data-date-patch]'))
})
test.serial('Navigate to /patch/2', async t => {
await page.nuxt.navigate('/patch/2')
const date = await page.$text('[data-date-id]')
t.is(await page.$text('h3'), 'Index')
t.is(dates.patch, await page.$text('[data-date-patch]'))
t.true(+dates.id < +date)
dates.id = date
})
test.serial('Navigate to /patch/2?test=true', async t => {
await page.nuxt.navigate('/patch/2?test=true')
t.is(dates.patch, await page.$text('[data-date-patch]'))
t.is(dates.id, await page.$text('[data-date-id]'))
})
test.serial('Navigate to /patch/2#test', async t => {
await page.nuxt.navigate('/patch/2#test')
t.is(dates.patch, await page.$text('[data-date-patch]'))
t.is(dates.id, await page.$text('[data-date-id]'))
})
test.serial('Navigate to /patch/2/child', async t => {
await page.nuxt.navigate('/patch/2/child')
dates.child = await page.$text('[data-date-child]')
dates.slug = await page.$text('[data-date-child-slug]')
t.is(dates.patch, await page.$text('[data-date-patch]'))
t.is(dates.id, await page.$text('[data-date-id]'))
t.true(+dates.child > +dates.id)
t.true(+dates.slug > +dates.child)
})
test.serial('Navigate to /patch/2/child/1', async t => {
await page.nuxt.navigate('/patch/2/child/1')
const date = await page.$text('[data-date-child-slug]')
t.is(dates.patch, await page.$text('[data-date-patch]'))
t.is(dates.id, await page.$text('[data-date-id]'))
t.is(dates.child, await page.$text('[data-date-child]'))
t.true(+date > +dates.slug)
dates.slug = date
})
test.serial('Navigate to /patch/2/child/1?foo=bar', async t => {
await page.nuxt.navigate('/patch/2/child/1?foo=bar')
t.is(dates.patch, await page.$text('[data-date-patch]'))
t.is(dates.id, await page.$text('[data-date-id]'))
t.is(dates.child, await page.$text('[data-date-child]'))
t.is(dates.slug, await page.$text('[data-date-child-slug]'))
})
test.serial('Search a country', async t => {
const countries = await page.$$text('[data-test-search-result]')
t.is(countries.length, 5)
await page.type('[data-test-search-input]', 'gu')
await Utils.waitFor(250)
const newCountries = await page.$$text('[data-test-search-result]')
t.is(newCountries.length, 1)
t.deepEqual(newCountries, ['Guinea'])
t.deepEqual(await page.nuxt.routeData(), {
path: '/patch/2/child/1',
query: {
foo: 'bar',
q: 'gu'
}
})
})
// Close server and ask nuxt to stop listening to file changes
test.after.always('Closing server and nuxt.js', async t => {
await nuxt.close()
})
test.after.always('Stop browser', async t => {
await page.close()
await browser.stop()
})

View File

@ -1,71 +1,64 @@
import { resolve } from 'path'
import test from 'ava'
import { Nuxt, Builder } from '..'
import { interceptLog } from './helpers/console'
const port = 4013
// const url = (route) => 'http://localhost:' + port + route
let nuxt = null
// Init nuxt.js and create server listening on localhost:4000
test.serial('Init Nuxt.js', async t => {
const options = {
rootDir: resolve(__dirname, 'fixtures/children'),
dev: false,
build: {
stats: false
describe('children', () => {
// Init nuxt.js and create server listening on localhost:4000
beforeAll(async () => {
const options = {
rootDir: resolve(__dirname, 'fixtures/children'),
dev: false,
build: {
stats: false
}
}
}
const logSpy = await interceptLog(async () => {
nuxt = new Nuxt(options)
await new Builder(nuxt).build()
new Builder(nuxt).build()
await nuxt.listen(port, 'localhost')
}, 30000)
test('/parent', async () => {
const { html } = await nuxt.renderRoute('/parent')
expect(html.includes('<h1>I am the parent</h1>')).toBe(true)
})
t.true(logSpy.calledWithMatch('DONE'))
t.true(logSpy.calledWithMatch('OPEN'))
})
test('/parent/child', async () => {
const { html } = await nuxt.renderRoute('/parent/child')
expect(html.includes('<h1>I am the parent</h1>')).toBe(true)
expect(html.includes('<h2>I am the child</h2>')).toBe(true)
})
test('/parent', async t => {
const { html } = await nuxt.renderRoute('/parent')
t.true(html.includes('<h1>I am the parent</h1>'))
})
test('/parent should call _id.vue', async () => {
const { html } = await nuxt.renderRoute('/parent')
expect(html.includes('<h1>I am the parent</h1>')).toBe(true)
expect(html.includes('<h2>Id=</h2>')).toBe(true)
})
test('/parent/child', async t => {
const { html } = await nuxt.renderRoute('/parent/child')
t.true(html.includes('<h1>I am the parent</h1>'))
t.true(html.includes('<h2>I am the child</h2>'))
})
test('/parent/1', async () => {
const { html } = await nuxt.renderRoute('/parent/1')
expect(html.includes('<h1>I am the parent</h1>')).toBe(true)
expect(html.includes('<h2>Id=1</h2>')).toBe(true)
})
test('/parent should call _id.vue', async t => {
const { html } = await nuxt.renderRoute('/parent')
t.true(html.includes('<h1>I am the parent</h1>'))
t.true(html.includes('<h2>Id=</h2>'))
})
test('/parent/validate-child should display 404', async () => {
const { html } = await nuxt.renderRoute('/parent/validate-child')
expect(html.includes('This page could not be found')).toBe(true)
})
test('/parent/1', async t => {
const { html } = await nuxt.renderRoute('/parent/1')
t.true(html.includes('<h1>I am the parent</h1>'))
t.true(html.includes('<h2>Id=1</h2>'))
})
test('/parent/validate-child?key=12345', async () => {
const { html } = await nuxt.renderRoute('/parent/validate-child?key=12345')
expect(html.includes('<h1>I am the parent</h1>')).toBe(true)
expect(html.includes('<h2>Child valid</h2>')).toBe(true)
})
test('/parent/validate-child should display 404', async t => {
const { html } = await nuxt.renderRoute('/parent/validate-child')
t.true(html.includes('This page could not be found'))
})
test('/parent/validate-child?key=12345', async t => {
const { html } = await nuxt.renderRoute('/parent/validate-child?key=12345')
t.true(html.includes('<h1>I am the parent</h1>'))
t.true(html.includes('<h2>Child valid</h2>'))
})
// Close server and ask nuxt to stop listening to file changes
test.after.always('Closing server and nuxt.js', async t => {
await nuxt.close()
// Close server and ask nuxt to stop listening to file changes
test('Closing server and nuxt.js', async () => {
await nuxt.close()
})
})

View File

@ -1,5 +1,4 @@
import { promisify } from 'util'
import test from 'ava'
import { resolve } from 'path'
import rp from 'request-promise-native'
import { exec, spawn } from 'child_process'
@ -13,84 +12,88 @@ const url = route => 'http://localhost:' + port + route
const nuxtBin = resolve(__dirname, '..', 'bin', 'nuxt')
test.serial('nuxt build', async t => {
const { stdout } = await execify(`node ${nuxtBin} build ${rootDir}`)
describe('cli', () => {
test('nuxt build', async () => {
const { stdout } = await execify(`node ${nuxtBin} build ${rootDir}`)
t.true(stdout.includes('Compiled successfully'))
})
test.serial('nuxt build -> error config', async t => {
const { stderr } = await t.throws(execify(`node ${nuxtBin} build ${rootDir} -c config.js`))
t.true(stderr.includes('Could not load config file'))
})
test.serial('nuxt start', async t => {
let stdout = ''
// let stderr = ''
let error
let exitCode
const env = process.env
env.PORT = port
const nuxtStart = spawn('node', [nuxtBin, 'start', rootDir], { env: env })
nuxtStart.stdout.on('data', data => {
stdout += data
expect(stdout.includes('Compiled successfully')).toBe(true)
})
nuxtStart.stderr.on('data', data => {
// stderr += data
test('nuxt build -> error config', async () => {
await expect(execify(`node ${nuxtBin} build ${rootDir} -c config.js`)).rejects.toMatchObject({
stderr: expect.stringContaining('Could not load config file')
})
})
nuxtStart.on('error', err => {
error = err
test('nuxt start', async () => {
let stdout = ''
// let stderr = ''
let error
let exitCode
const env = process.env
env.PORT = port
const nuxtStart = spawn('node', [nuxtBin, 'start', rootDir], { env: env })
nuxtStart.stdout.on('data', data => {
stdout += data
})
nuxtStart.stderr.on('data', data => {
// stderr += data
})
nuxtStart.on('error', err => {
error = err
})
nuxtStart.on('close', code => {
exitCode = code
})
// Give the process max 20s to start
let iterator = 0
while (!stdout.includes('OPEN') && iterator < 80) {
await Utils.waitFor(250)
iterator++
}
if (iterator === 80) {
test.log('WARN: server failed to start successfully in 20 seconds')
}
expect(error).toBe(undefined)
expect(stdout.includes('OPEN')).toBe(true)
const html = await rp(url('/users/1'))
expect(html.includes('<h1>User: 1</h1>')).toBe(true)
nuxtStart.kill()
// Wait max 10s for the process to be killed
iterator = 0
// eslint-disable-next-line no-unmodified-loop-condition
while (exitCode === undefined && iterator < 40) {
await Utils.waitFor(250)
iterator++
}
if (iterator >= 40) {
// eslint-disable-line no-console
test.log(
`WARN: we were unable to automatically kill the child process with pid: ${
nuxtStart.pid
}`
)
}
expect(exitCode).toBe(null)
})
nuxtStart.on('close', code => {
exitCode = code
test('nuxt generate', async () => {
const { stdout } = await execify(`node ${nuxtBin} generate ${rootDir}`)
expect(stdout.includes('vue-ssr-client-manifest.json')).toBe(true)
})
// Give the process max 20s to start
let iterator = 0
while (!stdout.includes('OPEN') && iterator < 80) {
await Utils.waitFor(250)
iterator++
}
if (iterator === 80) {
t.log('WARN: server failed to start successfully in 20 seconds')
}
t.is(error, undefined)
t.true(stdout.includes('OPEN'))
const html = await rp(url('/users/1'))
t.true(html.includes('<h1>User: 1</h1>'))
nuxtStart.kill()
// Wait max 10s for the process to be killed
iterator = 0
// eslint-disable-next-line no-unmodified-loop-condition
while (exitCode === undefined && iterator < 40) {
await Utils.waitFor(250)
iterator++
}
if (iterator >= 40) {
t.log(
`WARN: we were unable to automatically kill the child process with pid: ${
nuxtStart.pid
}`
)
}
t.is(exitCode, null)
})
test.serial('nuxt generate', async t => {
const { stdout } = await execify(`node ${nuxtBin} generate ${rootDir}`)
t.true(stdout.includes('vue-ssr-client-manifest.json'))
})

View File

@ -1,7 +1,5 @@
import test from 'ava'
import rp from 'request-promise-native'
import { Nuxt, Builder } from '..'
import { interceptLog } from './helpers/console'
import { loadConfig } from './helpers/config'
const port = 4007
@ -10,50 +8,47 @@ const url = route => 'http://localhost:' + port + route
let nuxt = null
let builder = null
// Init nuxt.js and create server listening on localhost:4000
test.before('Init Nuxt.js', async t => {
const config = loadConfig('/custom-dirs', { dev: false })
describe('custom-dirs', () => {
// Init nuxt.js and create server listening on localhost:4000
beforeAll(async () => {
const config = loadConfig('/custom-dirs', { dev: false })
const logSpy = await interceptLog(async () => {
nuxt = new Nuxt(config)
builder = new Builder(nuxt)
await builder.build()
await nuxt.listen(4007, 'localhost')
}, 30000)
test('custom assets directory', async () => {
const { html } = await nuxt.renderRoute('/')
expect(html.includes('.global-css-selector')).toBe(true)
})
t.true(logSpy.calledWithMatch('DONE'))
t.true(logSpy.calledWithMatch('OPEN'))
})
test('custom assets directory', async t => {
const { html } = await nuxt.renderRoute('/')
t.true(html.includes('.global-css-selector'))
})
test('custom layouts directory', async t => {
const { html } = await nuxt.renderRoute('/')
t.true(html.includes('<p>I have custom layouts directory</p>'))
})
test('custom middleware directory', async t => {
const window = await nuxt.renderAndGetWindow(url('/user-agent'))
const html = window.document.body.innerHTML
t.true(html.includes('<pre>Mozilla'))
})
test('custom pages directory', async t => {
const { html } = await nuxt.renderRoute('/')
t.true(html.includes('<h1>I have custom pages directory</h1>'))
})
test('custom static directory', async t => {
const { headers } = await rp(url('/test.txt'), {
resolveWithFullResponse: true
test('custom layouts directory', async () => {
const { html } = await nuxt.renderRoute('/')
expect(html.includes('<p>I have custom layouts directory</p>')).toBe(true)
})
t.is(headers['cache-control'], 'public, max-age=0')
})
// Close server and ask nuxt to stop listening to file changes
test.after.always('Closing server and nuxt.js', async t => {
await nuxt.close()
test('custom middleware directory', async () => {
const window = await nuxt.renderAndGetWindow(url('/user-agent'))
const html = window.document.body.innerHTML
expect(html.includes('<pre>Mozilla')).toBe(true)
})
test('custom pages directory', async () => {
const { html } = await nuxt.renderRoute('/')
expect(html.includes('<h1>I have custom pages directory</h1>')).toBe(true)
})
test('custom static directory', async () => {
const { headers } = await rp(url('/test.txt'), {
resolveWithFullResponse: true
})
expect(headers['cache-control']).toBe('public, max-age=0')
})
// Close server and ask nuxt to stop listening to file changes
test('Closing server and nuxt.js', async () => {
await nuxt.close()
})
})

View File

@ -1,7 +1,5 @@
import test from 'ava'
import rp from 'request-promise-native'
import { Nuxt, Builder } from '..'
import { interceptLog, interceptError, release } from './helpers/console'
import { loadConfig } from './helpers/config'
const port = 4009
@ -9,94 +7,93 @@ const url = route => 'http://localhost:' + port + route
let nuxt = null
// Init nuxt.js and create server listening on localhost:4000
test.before('Init Nuxt.js', async t => {
const config = loadConfig('debug')
describe('debug', () => {
// Init nuxt.js and create server listening on localhost:4000
beforeAll(async () => {
const config = loadConfig('debug')
const logSpy = await interceptLog(async () => {
nuxt = new Nuxt(config)
await new Builder(nuxt).build()
new Builder(nuxt).build()
await nuxt.listen(port, 'localhost')
}, 30000)
test('/test/__open-in-editor (open-in-editor)', async () => {
const { body } = await rp(
url('/test/__open-in-editor?file=pages/index.vue'),
{ resolveWithFullResponse: true }
)
expect(body).toBe('')
})
t.true(logSpy.calledWithMatch('DONE'))
t.true(logSpy.calledWithMatch('OPEN'))
})
test.serial('/test/__open-in-editor (open-in-editor)', async t => {
const { body } = await rp(
url('/test/__open-in-editor?file=pages/index.vue'),
{ resolveWithFullResponse: true }
test(
'/test/__open-in-editor should return error (open-in-editor)',
async () => {
await expect(rp(url('/test/__open-in-editor?file='))).rejects.toMatchObject({
statusCode: 500,
message: 'launch-editor-middleware: required query param "file" is missing.'
})
}
)
t.is(body, '')
})
test.serial(
'/test/__open-in-editor should return error (open-in-editor)',
async t => {
const { error, statusCode } = await t.throws(
rp(url('/test/__open-in-editor?file='), { resolveWithFullResponse: true })
)
t.is(statusCode, 500)
t.is(
error,
'launch-editor-middleware: required query param "file" is missing.'
)
}
)
test.serial('/test/error should return error stack trace (Youch)', async t => {
const errorSpy = await interceptError()
const { response, error } = await t.throws(
nuxt.renderAndGetWindow(url('/test/error'))
)
t.is(response.statusCode, 500)
t.is(response.statusMessage, 'NuxtServerError')
t.true(error.includes('test youch !'))
t.true(error.includes('<div class="error-frames">'))
release()
t.true(errorSpy.calledTwice)
t.true(errorSpy.getCall(0).args[0].includes('test youch !'))
t.true(errorSpy.getCall(1).args[0].message.includes('test youch !'))
})
test.serial('/test/error no source-map (Youch)', async t => {
const sourceMaps = nuxt.renderer.resources.serverBundle.maps
nuxt.renderer.resources.serverBundle.maps = {}
const errorSpy = await interceptError()
const { response, error } = await t.throws(
nuxt.renderAndGetWindow(url('/test/error'))
)
t.is(response.statusCode, 500)
t.is(response.statusMessage, 'NuxtServerError')
t.true(error.includes('test youch !'))
t.true(error.includes('<div class="error-frames">'))
release()
t.true(errorSpy.calledTwice)
t.true(errorSpy.getCall(0).args[0].includes('test youch !'))
t.true(errorSpy.getCall(1).args[0].message.includes('test youch !'))
nuxt.renderer.resources.serverBundle.maps = sourceMaps
})
test.serial('/test/error should return json format error (Youch)', async t => {
const opts = {
headers: {
accept: 'application/json'
},
resolveWithFullResponse: true
}
const errorSpy = await interceptError()
const { response: { headers } } = await t.throws(rp(url('/test/error'), opts))
t.is(headers['content-type'], 'text/json; charset=utf-8')
release()
t.true(errorSpy.calledTwice)
t.true(errorSpy.getCall(0).args[0].includes('test youch !'))
t.true(errorSpy.getCall(1).args[0].message.includes('test youch !'))
})
// Close server and ask nuxt to stop listening to file changes
test.after.always('Closing server and nuxt.js', async t => {
await nuxt.close()
test('/test/error should return error stack trace (Youch)', async () => {
// const errorSpy = await interceptError()
await expect(nuxt.renderAndGetWindow(url('/test/error'))).rejects.toMatchObject({
response: {
statusCode: 500,
statusMessage: 'NuxtServerError'
},
error: expect.stringContaining('test youch !')
})
// release()
// expect(errorSpy.calledTwice).toBe(true)
// expect(errorSpy.getCall(0).args[0].includes('test youch !')).toBe(true)
// expect(errorSpy.getCall(1).args[0].message.includes('test youch !')).toBe(true)
})
test('/test/error no source-map (Youch)', async () => {
const sourceMaps = nuxt.renderer.resources.serverBundle.maps
nuxt.renderer.resources.serverBundle.maps = {}
// const errorSpy = await interceptError()
await expect(nuxt.renderAndGetWindow(url('/test/error'))).rejects.toMatchObject({
statusCode: 500,
error: expect.stringContaining('<div class="error-frames">')
})
// release()
// expect(errorSpy.calledTwice).toBe(true)
// expect(errorSpy.getCall(0).args[0].includes('test youch !')).toBe(true)
// expect(errorSpy.getCall(1).args[0].message.includes('test youch !')).toBe(true)
nuxt.renderer.resources.serverBundle.maps = sourceMaps
})
test('/test/error should return json format error (Youch)', async () => {
const opts = {
headers: {
accept: 'application/json'
},
resolveWithFullResponse: true
}
// const errorSpy = await interceptError()
await expect(rp(url('/test/error'), opts)).rejects.toMatchObject({
response: {
headers: {
'content-type': 'text/json; charset=utf-8'
}
}
})
// release()
// expect(errorSpy.calledTwice).toBe(true)
// expect(errorSpy.getCall(0).args[0].includes('test youch !')).toBe(true)
// expect(errorSpy.getCall(1).args[0].message.includes('test youch !')).toBe(true)
})
// Close server and ask nuxt to stop listening to file changes
test('Closing server and nuxt.js', async () => {
await nuxt.close()
})
})

View File

@ -1,34 +1,31 @@
import test from 'ava'
import { Nuxt, Builder } from '..'
import { intercept } from './helpers/console'
import { loadConfig } from './helpers/config'
const port = 4010
let nuxt = null
let builder = null
let buildSpies = null
// let buildSpies = null
// Init nuxt.js and create server listening on localhost:4000
test.serial('Init Nuxt.js', async t => {
const config = loadConfig('deprecate', { dev: false })
describe('depricate', () => {
// Init nuxt.js and create server listening on localhost:4000
beforeAll(async () => {
const config = loadConfig('deprecate', { dev: false })
buildSpies = await intercept(async () => {
nuxt = new Nuxt(config)
builder = await new Builder(nuxt)
builder = new Builder(nuxt)
await builder.build()
await nuxt.listen(port, 'localhost')
}, 30000)
// test('Deprecated: module.addVendor()', async () => {
// expect(
// buildSpies.warn.calledWithMatch('module: addVendor is no longer necessary')
// ).toBe(true)
// })
// Close server and ask nuxt to stop listening to file changes
test('Closing server and nuxt.js', async () => {
await nuxt.close()
})
t.true(buildSpies.log.calledWithMatch('DONE'))
t.true(buildSpies.log.calledWithMatch('OPEN'))
})
test.serial('Deprecated: module.addVendor()', async t => {
t.true(buildSpies.warn.calledWithMatch('module: addVendor is no longer necessary'))
})
// Close server and ask nuxt to stop listening to file changes
test.after.always('Closing server and nuxt.js', async t => {
await nuxt.close()
})

View File

@ -2,121 +2,116 @@ import { resolve } from 'path'
import fs from 'fs'
import { promisify } from 'util'
import test from 'ava'
import { Nuxt, Builder } from '..'
import { interceptLog } from './helpers/console'
const readFile = promisify(fs.readFile)
test.serial('Init Nuxt.js', async t => {
const config = {
rootDir: resolve(__dirname, 'fixtures/dynamic-routes'),
dev: false,
build: {
stats: false
describe('dynamic routes', () => {
beforeAll(async () => {
const config = {
rootDir: resolve(__dirname, 'fixtures/dynamic-routes'),
dev: false,
build: {
stats: false
}
}
}
const logSpy = await interceptLog(async () => {
const nuxt = new Nuxt(config)
await new Builder(nuxt).build()
})
t.true(logSpy.calledWithMatch('DONE'))
})
new Builder(nuxt).build()
}, 30000)
test('Check .nuxt/router.js', t => {
return readFile(
resolve(__dirname, './fixtures/dynamic-routes/.nuxt/router.js'),
'utf-8'
).then(routerFile => {
routerFile = routerFile
.slice(routerFile.indexOf('routes: ['))
.replace('routes: [', '[')
.replace(/ _[0-9A-z]+,/g, ' "",')
routerFile = routerFile.substr(
routerFile.indexOf('['),
routerFile.lastIndexOf(']') + 1
)
let routes = eval('( ' + routerFile + ')') // eslint-disable-line no-eval
// pages/test/index.vue
t.is(routes[0].path, '/test')
t.is(routes[0].name, 'test')
// pages/posts.vue
t.is(routes[1].path, '/posts')
t.is(routes[1].name, 'posts')
t.is(routes[1].children.length, 1)
// pages/posts/_id.vue
t.is(routes[1].children[0].path, ':id?')
t.is(routes[1].children[0].name, 'posts-id')
// pages/parent.vue
t.is(routes[2].path, '/parent')
t.falsy(routes[2].name) // parent route has no name
// pages/parent/*.vue
t.is(routes[2].children.length, 3) // parent has 3 children
t.deepEqual(routes[2].children.map(r => r.path), ['', 'teub', 'child'])
t.deepEqual(routes[2].children.map(r => r.name), [
'parent',
'parent-teub',
'parent-child'
])
// pages/test/projects/index.vue
t.is(routes[3].path, '/test/projects')
t.is(routes[3].name, 'test-projects')
// pages/test/users.vue
t.is(routes[4].path, '/test/users')
t.falsy(routes[4].name) // parent route has no name
// pages/test/users/*.vue
t.is(routes[4].children.length, 5) // parent has 5 children
t.deepEqual(routes[4].children.map(r => r.path), [
'',
'projects',
'projects/:category',
':id',
':index/teub'
])
t.deepEqual(routes[4].children.map(r => r.name), [
'test-users',
'test-users-projects',
'test-users-projects-category',
'test-users-id',
'test-users-index-teub'
])
// pages/test/songs/toto.vue
t.is(routes[5].path, '/test/songs/toto')
t.is(routes[5].name, 'test-songs-toto')
// pages/test/projects/_category.vue
t.is(routes[6].path, '/test/projects/:category')
t.is(routes[6].name, 'test-projects-category')
// pages/test/songs/_id.vue
t.is(routes[7].path, '/test/songs/:id?')
t.is(routes[7].name, 'test-songs-id')
// pages/users/_id.vue
t.is(routes[8].path, '/users/:id?')
t.is(routes[8].name, 'users-id')
// pages/test/_.vue
t.is(routes[9].path, '/test/*')
t.is(routes[9].name, 'test-all')
test('Check .nuxt/router.js', () => {
return readFile(
resolve(__dirname, './fixtures/dynamic-routes/.nuxt/router.js'),
'utf-8'
).then(routerFile => {
routerFile = routerFile
.slice(routerFile.indexOf('routes: ['))
.replace('routes: [', '[')
.replace(/ _[0-9A-z]+,/g, ' "",')
routerFile = routerFile.substr(
routerFile.indexOf('['),
routerFile.lastIndexOf(']') + 1
)
let routes = eval('( ' + routerFile + ')') // eslint-disable-line no-eval
// pages/test/index.vue
expect(routes[0].path).toBe('/test')
expect(routes[0].name).toBe('test')
// pages/posts.vue
expect(routes[1].path).toBe('/posts')
expect(routes[1].name).toBe('posts')
expect(routes[1].children.length).toBe(1)
// pages/posts/_id.vue
expect(routes[1].children[0].path).toBe(':id?')
expect(routes[1].children[0].name).toBe('posts-id')
// pages/parent.vue
expect(routes[2].path).toBe('/parent')
expect(routes[2].name).toBeFalsy() // parent route has no name
// pages/parent/*.vue
expect(routes[2].children.length).toBe(3) // parent has 3 children
expect(routes[2].children.map(r => r.path)).toEqual(['', 'teub', 'child'])
expect(routes[2].children.map(r => r.name)).toEqual([
'parent',
'parent-teub',
'parent-child'
])
// pages/test/projects/index.vue
expect(routes[3].path).toBe('/test/projects')
expect(routes[3].name).toBe('test-projects')
// pages/test/users.vue
expect(routes[4].path).toBe('/test/users')
expect(routes[4].name).toBeFalsy() // parent route has no name
// pages/test/users/*.vue
expect(routes[4].children.length).toBe(5) // parent has 5 children
expect(routes[4].children.map(r => r.path)).toEqual([
'',
'projects',
'projects/:category',
':id',
':index/teub'
])
expect(routes[4].children.map(r => r.name)).toEqual([
'test-users',
'test-users-projects',
'test-users-projects-category',
'test-users-id',
'test-users-index-teub'
])
// pages/test/songs/toto.vue
expect(routes[5].path).toBe('/test/songs/toto')
expect(routes[5].name).toBe('test-songs-toto')
// pages/test/projects/_category.vue
expect(routes[6].path).toBe('/test/projects/:category')
expect(routes[6].name).toBe('test-projects-category')
// pages/test/songs/_id.vue
expect(routes[7].path).toBe('/test/songs/:id?')
expect(routes[7].name).toBe('test-songs-id')
// pages/users/_id.vue
expect(routes[8].path).toBe('/users/:id?')
expect(routes[8].name).toBe('users-id')
// pages/test/_.vue
expect(routes[9].path).toBe('/test/*')
expect(routes[9].name).toBe('test-all')
// pages/index.vue
t.is(routes[10].path, '/')
t.is(routes[10].name, 'index')
// pages/index.vue
expect(routes[10].path).toBe('/')
expect(routes[10].name).toBe('index')
// pages/_slug.vue
t.is(routes[11].path, '/:slug')
t.is(routes[11].name, 'slug')
// pages/_key/_id.vue
t.is(routes[12].path, '/:key/:id?')
t.is(routes[12].name, 'key-id')
// pages/_.vue
t.is(routes[13].path, '/*/p/*')
t.is(routes[13].name, 'all-p-all')
// pages/_/_.vue
t.is(routes[14].path, '/*/*')
t.is(routes[14].name, 'all-all')
// pages/_.vue
t.is(routes[15].path, '/*')
t.is(routes[15].name, 'all')
// pages/_slug.vue
expect(routes[11].path).toBe('/:slug')
expect(routes[11].name).toBe('slug')
// pages/_key/_id.vue
expect(routes[12].path).toBe('/:key/:id?')
expect(routes[12].name).toBe('key-id')
// pages/_.vue
expect(routes[13].path).toBe('/*/p/*')
expect(routes[13].name).toBe('all-p-all')
// pages/_/_.vue
expect(routes[14].path).toBe('/*/*')
expect(routes[14].name).toBe('all-all')
// pages/_.vue
expect(routes[15].path).toBe('/*')
expect(routes[15].name).toBe('all')
})
})
})

View File

@ -1,89 +1,80 @@
import test from 'ava'
import rp from 'request-promise-native'
// import rp from 'request-promise-native'
import { Nuxt, Builder } from '..'
import { interceptLog, interceptError, release } from './helpers/console'
import { loadConfig } from './helpers/config'
const port = 4005
const url = route => 'http://localhost:' + port + route
let nuxt = null
let logSpy
// let logSpy
// Init nuxt.js and create server listening on localhost:4000
test.serial('Init Nuxt.js', async t => {
const config = loadConfig('error', { dev: false })
describe('error', () => {
// Init nuxt.js and create server listening on localhost:4000
beforeAll(async () => {
const config = loadConfig('error', { dev: false })
logSpy = await interceptLog(async () => {
nuxt = new Nuxt(config)
await new Builder(nuxt).build()
new Builder(nuxt).build()
await nuxt.listen(port, 'localhost')
}, 30000)
test('/ should display an error', async () => {
await expect(nuxt.renderRoute('/')).rejects.toMatchObject({
message: expect.stringContaining('not_defined is not defined')
})
})
t.true(logSpy.calledWithMatch('DONE'))
t.true(logSpy.calledWithMatch('OPEN'))
})
test('/404 should display an error too', async () => {
let { error } = await nuxt.renderRoute('/404')
expect(error.message.includes('This page could not be found')).toBe(true)
})
test.serial('/ should display an error', async t => {
const error = await t.throws(nuxt.renderRoute('/'))
t.true(error.message.includes('not_defined is not defined'))
})
test('/ with renderAndGetWindow()', async () => {
// const errorSpy = await interceptError()
await expect(nuxt.renderAndGetWindow(url('/'))).rejects.toMatchObject({
statusCode: 500
})
test.serial('/404 should display an error too', async t => {
let { error } = await nuxt.renderRoute('/404')
t.true(error.message.includes('This page could not be found'))
})
// release()
// expect(errorSpy.calledOnce).toBe(true)
// expect(errorSpy
// .getCall(0)
// .args[0].message.includes(
// 'render function or template not defined in component: anonymous'
// )).toBe(true)
})
test.serial('/ with renderAndGetWindow()', async t => {
const errorSpy = await interceptError()
const err = await t.throws(nuxt.renderAndGetWindow(url('/')))
t.is(err.response.statusCode, 500)
t.is(err.response.statusMessage, 'NuxtServerError')
release()
t.true(errorSpy.calledOnce)
t.true(
errorSpy
.getCall(0)
.args[0].message.includes(
'render function or template not defined in component: anonymous'
)
)
})
// test('/ with text/json content', async () => {
// const opts = {
// headers: {
// accept: 'application/json'
// },
// resolveWithFullResponse: true
// }
// const errorSpy = await interceptError()
// const { response: { headers } } = await expect(rp(url('/'), opts)).toThrow()
// expect(headers['content-type']).toBe('text/json; charset=utf-8')
// release()
// expect(errorSpy.calledOnce).toBe(true)
// expect(errorSpy
// .getCall(0)
// .args[0].message.includes(
// 'render function or template not defined in component: anonymous'
// )).toBe(true)
// })
test.serial('/ with text/json content', async t => {
const opts = {
headers: {
accept: 'application/json'
},
resolveWithFullResponse: true
}
const errorSpy = await interceptError()
const { response: { headers } } = await t.throws(rp(url('/'), opts))
t.is(headers['content-type'], 'text/json; charset=utf-8')
release()
t.true(errorSpy.calledOnce)
t.true(
errorSpy
.getCall(0)
.args[0].message.includes(
'render function or template not defined in component: anonymous'
)
)
})
// test('Deprecated: dev in build.extend()', async () => {
// expect(logSpy.calledWith('[build:done]: hook error')).toBe(true)
// })
test.serial('Deprecated: dev in build.extend()', async t => {
t.true(logSpy.calledWith('[build:done]: hook error'))
})
test('Error: resolvePath()', async () => {
expect(() => nuxt.resolvePath()).toThrowError(TypeError)
test.serial('Error: resolvePath()', async t => {
let error = t.throws(() => nuxt.resolvePath())
t.true(error instanceof TypeError)
expect(() => nuxt.resolvePath('@/pages/about.vue')).toThrowError('Cannot resolve "@/pages/about.vue"')
})
error = t.throws(() => nuxt.resolvePath('@/pages/about.vue'))
t.true(error.message.includes('Cannot resolve "@/pages/about.vue"'))
})
// Close server and ask nuxt to stop listening to file changes
test.after.always('Closing server and nuxt.js', async t => {
await nuxt.close()
// Close server and ask nuxt to stop listening to file changes
test('Closing server and nuxt.js', async () => {
await nuxt.close()
})
})

View File

@ -1,11 +1,9 @@
import { resolve } from 'path'
import test from 'ava'
import express from 'express'
import rp from 'request-promise-native'
import { Nuxt, Builder } from '..'
import { interceptLog } from './helpers/console'
const port = 4000
const url = route => 'http://localhost:' + port + route
@ -13,35 +11,34 @@ const url = route => 'http://localhost:' + port + route
let nuxt
let app
// Init nuxt.js and create express server
test.serial('Init Nuxt.js', async t => {
const config = {
rootDir: resolve(__dirname, 'fixtures/basic'),
buildDir: '.nuxt-express',
dev: false,
build: {
stats: false
describe('express', () => {
// Init nuxt.js and create express server
beforeAll(async () => {
const config = {
rootDir: resolve(__dirname, 'fixtures/basic'),
buildDir: '.nuxt-express',
dev: false,
build: {
stats: false
}
}
}
const logSpy = await interceptLog(async () => {
nuxt = new Nuxt(config)
await new Builder(nuxt).build()
new Builder(nuxt).build()
// Create express app
app = express()
// Register nuxt
app.use(nuxt.render)
// Start listening on localhost:4000
app.listen(port)
}, 30000)
test('/stateless with express', async () => {
const html = await rp(url('/stateless'))
expect(html.includes('<h1>My component!</h1>')).toBe(true)
})
t.true(logSpy.calledWithMatch('DONE'))
// Create express app
app = express()
// Register nuxt
app.use(nuxt.render)
// Start listening on localhost:4000
app.listen(port)
})
test('/stateless with express', async t => {
const html = await rp(url('/stateless'))
t.true(html.includes('<h1>My component!</h1>'))
})

View File

@ -2,14 +2,12 @@ import http from 'http'
import { existsSync } from 'fs'
import { resolve } from 'path'
import test from 'ava'
import serveStatic from 'serve-static'
import finalhandler from 'finalhandler'
import rp from 'request-promise-native'
import { Nuxt, Builder, Generator, Options } from '..'
import { intercept, interceptLog } from './helpers/console'
import { loadConfig } from './helpers/config'
const port = 4015
@ -19,98 +17,97 @@ let nuxt = null
let server = null
let generator = null
// Init nuxt.js and create server listening on localhost:4015
test.serial('Init Nuxt.js', async t => {
let config = loadConfig('basic', {
buildDir: '.nuxt-spa-fallback',
dev: false
})
config.build.stats = false
describe('fallback generate', () => {
// Init nuxt.js and create server listening on localhost:4015
beforeAll(async () => {
let config = loadConfig('basic', {
buildDir: '.nuxt-spa-fallback',
dev: false
})
config.build.stats = false
const logSpy = await interceptLog(async () => {
nuxt = new Nuxt(config)
const builder = new Builder(nuxt)
generator = new Generator(nuxt, builder)
await generator.generate()
const serve = serveStatic(resolve(__dirname, 'fixtures/basic/dist'))
server = http.createServer((req, res) => {
serve(req, res, finalhandler(req, res))
})
server.listen(port)
}, 30000)
test('default creates /200.html as fallback', async () => {
const html = await rp(url('/200.html'))
expect(html.includes('<h1>Index page</h1>')).toBe(false)
expect(html.includes('data-server-rendered')).toBe(false)
expect(existsSync(resolve(__dirname, 'fixtures/basic/dist', '200.html'))).toBe(true)
expect(existsSync(resolve(__dirname, 'fixtures/basic/dist', '404.html'))).toBe(false)
})
t.true(logSpy.calledWithMatch('DONE'))
const serve = serveStatic(resolve(__dirname, 'fixtures/basic/dist'))
server = http.createServer((req, res) => {
serve(req, res, finalhandler(req, res))
})
server.listen(port)
})
test.serial('default creates /200.html as fallback', async t => {
const html = await rp(url('/200.html'))
t.false(html.includes('<h1>Index page</h1>'))
t.false(html.includes('data-server-rendered'))
t.true(existsSync(resolve(__dirname, 'fixtures/basic/dist', '200.html')))
t.false(existsSync(resolve(__dirname, 'fixtures/basic/dist', '404.html')))
})
test.serial('nuxt re-generating with generate.fallback = false', async t => {
const logSpy = await interceptLog(async () => {
test('nuxt re-generating with generate.fallback = false', async () => {
// const logSpy = await interceptLog(async () => {
nuxt.options.generate.fallback = false
await generator.generate()
// expect(logSpy.calledWithMatch('DONE')).toBe(true)
})
t.true(logSpy.calledWithMatch('DONE'))
})
test.serial('false creates no fallback', async t => {
const error = await t.throws(rp(url('/200.html')))
t.true(error.statusCode === 404)
t.true(error.response.body.includes('Cannot GET /200.html'))
t.false(existsSync(resolve(__dirname, 'fixtures/basic/dist', '200.html')))
t.false(existsSync(resolve(__dirname, 'fixtures/basic/dist', '404.html')))
})
test('false creates no fallback', async () => {
await expect(rp(url('/200.html'))).rejects.toMatchObject({
statusCode: 404,
response: {
body: expect.stringContaining('Cannot GET /200.html')
}
})
test.serial('generate.fallback = true is transformed to /404.html', async t => {
nuxt.options.generate.fallback = true
const options = Options.from(nuxt.options)
t.is(options.generate.fallback, '404.html')
})
test.serial('nuxt re-generating with generate.fallback = "spa-fallback.html"', async t => {
const logSpy = await interceptLog(async () => {
nuxt.options.generate.fallback = 'spa-fallback.html'
await generator.generate()
expect(existsSync(resolve(__dirname, 'fixtures/basic/dist', '200.html'))).toBe(false)
expect(existsSync(resolve(__dirname, 'fixtures/basic/dist', '404.html'))).toBe(false)
})
t.true(logSpy.calledWithMatch('DONE'))
})
test.serial('"spa-fallback.html" creates /spa-fallback.html as fallback', async t => {
const html = await rp(url('/spa-fallback.html'))
t.false(html.includes('<h1>Index page</h1>'))
t.false(html.includes('data-server-rendered'))
t.true(
existsSync(resolve(__dirname, 'fixtures/basic/dist', 'spa-fallback.html'))
test('generate.fallback = true is transformed to /404.html', async () => {
nuxt.options.generate.fallback = true
const options = Options.from(nuxt.options)
expect(options.generate.fallback).toBe('404.html')
})
test(
'nuxt re-generating with generate.fallback = "spa-fallback.html"',
async () => {
nuxt.options.generate.fallback = 'spa-fallback.html'
await generator.generate()
}
)
t.false(existsSync(resolve(__dirname, 'fixtures/basic/dist', '404.html')))
t.false(existsSync(resolve(__dirname, 'fixtures/basic/dist', '200.html')))
})
test.serial('nuxt re-generating with generate.fallback = "index.html"', async t => {
const {log: logSpy, warn: warnSpy} = await intercept({warn: true, log: true}, async () => {
test(
'"spa-fallback.html" creates /spa-fallback.html as fallback',
async () => {
const html = await rp(url('/spa-fallback.html'))
expect(html.includes('<h1>Index page</h1>')).toBe(false)
expect(html.includes('data-server-rendered')).toBe(false)
expect(existsSync(resolve(__dirname, 'fixtures/basic/dist', 'spa-fallback.html'))).toBe(true)
expect(existsSync(resolve(__dirname, 'fixtures/basic/dist', '404.html'))).toBe(false)
expect(existsSync(resolve(__dirname, 'fixtures/basic/dist', '200.html'))).toBe(false)
}
)
test('nuxt re-generating with generate.fallback = "index.html"', async () => {
nuxt.options.generate.fallback = 'index.html'
await generator.generate()
})
t.true(warnSpy.calledWithMatch('WARN')) // Must emit warnning
t.true(logSpy.calledWithMatch('DONE'))
})
test.serial('"index.html" creates /index.html as fallback', async t => {
const html = await rp(url('/index.html'))
t.true(html.includes('<h1>Index page</h1>'))
t.true(html.includes('data-server-rendered'))
t.true(existsSync(resolve(__dirname, 'fixtures/basic/dist', 'index.html')))
t.false(existsSync(resolve(__dirname, 'fixtures/basic/dist', '404.html')))
t.false(existsSync(resolve(__dirname, 'fixtures/basic/dist', '200.html')))
})
test('"index.html" creates /index.html as fallback', async () => {
const html = await rp(url('/index.html'))
expect(html.includes('<h1>Index page</h1>')).toBe(true)
expect(html.includes('data-server-rendered')).toBe(true)
expect(existsSync(resolve(__dirname, 'fixtures/basic/dist', 'index.html'))).toBe(true)
expect(existsSync(resolve(__dirname, 'fixtures/basic/dist', '404.html'))).toBe(false)
expect(existsSync(resolve(__dirname, 'fixtures/basic/dist', '200.html'))).toBe(false)
})
// Close server and ask nuxt to stop listening to file changes
test.after.always('Closing server', async t => {
await server.close()
// Close server and ask nuxt to stop listening to file changes
test('Closing server', async () => {
await server.close()
})
})

View File

@ -10,6 +10,11 @@ export default {
interval: 200,
subFolders: true
},
head: {
titleTemplate: (titleChunk) => {
return titleChunk ? `${titleChunk} - Nuxt.js` : 'Nuxt.js'
}
},
modulesDir: path.join(__dirname, '..', '..', '..', 'node_modules'),
hooks: {
ready(nuxt) {

View File

@ -1,76 +1,77 @@
import test from 'ava'
import { Nuxt, Generator } from '..'
test('initRoutes with routes (fn => array)', async t => {
const array = ['/1', '/2', '/3', '/4']
const config = {
generate: {
routes: array
}
}
const nuxt = new Nuxt(config)
const generator = new Generator(nuxt)
const routes = await generator.initRoutes()
t.is(routes.length, array.length)
routes.map((route, index) => {
t.is(route.route, array[index])
})
})
test('initRoutes with routes (fn())', async t => {
const array = ['/1', '/2', '/3', '/4']
const config = {
generate: {
routes() {
return array
describe('generator', () => {
test('initRoutes with routes (fn => array)', async () => {
const array = ['/1', '/2', '/3', '/4']
const config = {
generate: {
routes: array
}
}
}
const nuxt = new Nuxt(config)
const generator = new Generator(nuxt)
const routes = await generator.initRoutes()
const nuxt = new Nuxt(config)
const generator = new Generator(nuxt)
const routes = await generator.initRoutes()
t.is(routes.length, array.length)
routes.map((route, index) => {
t.is(route.route, array[index])
expect(routes.length).toBe(array.length)
routes.map((route, index) => {
expect(route.route).toBe(array[index])
})
})
})
test('initRoutes with routes (fn(args))', async t => {
const config = {
generate: {
routes(array) {
return array
test('initRoutes with routes (fn())', async () => {
const array = ['/1', '/2', '/3', '/4']
const config = {
generate: {
routes() {
return array
}
}
}
}
const nuxt = new Nuxt(config)
const generator = new Generator(nuxt)
const array = ['/1', '/2', '/3', '/4']
const routes = await generator.initRoutes(array)
const nuxt = new Nuxt(config)
const generator = new Generator(nuxt)
const routes = await generator.initRoutes()
t.is(routes.length, array.length)
routes.map((route, index) => {
t.is(route.route, array[index])
expect(routes.length).toBe(array.length)
routes.map((route, index) => {
expect(route.route).toBe(array[index])
})
})
})
test('initRoutes with routes (fn(cb, args))', async t => {
const config = {
generate: {
routes(cb, arg1, arg2, arg3, arg4) {
cb(null, [arg1, arg2, arg3, arg4])
test('initRoutes with routes (fn(args))', async () => {
const config = {
generate: {
routes(array) {
return array
}
}
}
}
const nuxt = new Nuxt(config)
const generator = new Generator(nuxt)
const array = ['/1', '/2', '/3', '/4']
const routes = await generator.initRoutes(...array)
const nuxt = new Nuxt(config)
const generator = new Generator(nuxt)
const array = ['/1', '/2', '/3', '/4']
const routes = await generator.initRoutes(array)
t.is(routes.length, array.length)
routes.map((route, index) => {
t.is(route.route, array[index])
expect(routes.length).toBe(array.length)
routes.map((route, index) => {
expect(route.route).toBe(array[index])
})
})
test('initRoutes with routes (fn(cb, args))', async () => {
const config = {
generate: {
routes(cb, arg1, arg2, arg3, arg4) {
cb(null, [arg1, arg2, arg3, arg4])
}
}
}
const nuxt = new Nuxt(config)
const generator = new Generator(nuxt)
const array = ['/1', '/2', '/3', '/4']
const routes = await generator.initRoutes(...array)
expect(routes.length).toBe(array.length)
routes.map((route, index) => {
expect(route.route).toBe(array[index])
})
})
})

4
test/helpers/setup.js Normal file
View File

@ -0,0 +1,4 @@
// eslint-disable
jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000
jasmine.stopSpecOnExpectationFailure = true

View File

@ -1,45 +0,0 @@
import test from 'ava'
import { resolve } from 'path'
import { Nuxt, Builder } from '..'
test('Nuxt.js Class', t => {
t.is(typeof Nuxt, 'function')
})
test('Nuxt.js Instance', async t => {
const nuxt = new Nuxt({
dev: true,
rootDir: resolve(__dirname, 'fixtures', 'empty')
})
t.is(typeof nuxt, 'object')
t.is(nuxt.options.dev, true)
t.is(typeof nuxt._ready.then, 'function')
await nuxt.ready()
t.is(nuxt.initialized, true)
})
test('Fail to build when no pages/ directory but is in the parent', t => {
const nuxt = new Nuxt({
dev: false,
rootDir: resolve(__dirname, 'fixtures', 'empty', 'pages')
})
return new Builder(nuxt).build().catch(err => {
let s = String(err)
t.true(s.includes('No `pages` directory found'))
t.true(
s.includes('Did you mean to run `nuxt` in the parent (`../`) directory?')
)
})
})
test('Fail to build when no pages/ directory', t => {
const nuxt = new Nuxt({
dev: false,
rootDir: resolve(__dirname)
})
return new Builder(nuxt).build().catch(err => {
let s = String(err)
t.true(s.includes("Couldn't find a `pages` directory"))
t.true(s.includes('Please create one under the project root'))
})
})

View File

@ -1,11 +1,9 @@
import { normalize } from 'path'
import test from 'ava'
import rp from 'request-promise-native'
import { Nuxt, Builder } from '..'
import { intercept } from './helpers/console'
import { loadConfig } from './helpers/config'
const port = 4006
@ -16,68 +14,57 @@ let builder = null
let buildSpies = null
// Init nuxt.js and create server listening on localhost:4000
test.serial('Init Nuxt.js', async t => {
beforeAll(async () => {
const config = loadConfig('module', { dev: false })
nuxt = new Nuxt(config)
builder = new Builder(nuxt)
buildSpies = await intercept({ log: true, error: true }, async () => {
await builder.build()
await nuxt.listen(port, 'localhost')
})
await builder.build()
await nuxt.listen(port, 'localhost')
}, 30000)
t.true(buildSpies.log.calledWithMatch('DONE'))
t.true(buildSpies.log.calledWithMatch('OPEN'))
})
test.serial('Plugin', async t => {
t.true(
normalize(nuxt.options.plugins[0].src).includes(
normalize('fixtures/module/.nuxt/basic.reverse.')
),
'plugin added to config'
)
test('Plugin', async () => {
expect(normalize(nuxt.options.plugins[0].src).includes(
normalize('fixtures/module/.nuxt/basic.reverse.')
)).toBe(true)
const { html } = await nuxt.renderRoute('/')
t.true(html.includes('<h1>TXUN</h1>'), 'plugin works')
expect(html.includes('<h1>TXUN</h1>')).toBe(true)
})
test.serial('Layout', async t => {
t.true(
nuxt.options.layouts.layout.includes('layout'),
'layout added to config'
)
test('Layout', async () => {
expect(nuxt.options.layouts.layout.includes('layout')).toBe(true)
const { html } = await nuxt.renderRoute('/layout')
t.true(html.includes('<h1>Module Layouts</h1>'), 'layout works')
expect(html.includes('<h1>Module Layouts</h1>')).toBe(true)
})
test.serial('Hooks', async t => {
t.is(nuxt.__module_hook, 1)
t.is(nuxt.__renderer_hook, 2)
t.is(nuxt.__builder_hook, 3)
test('Hooks', async () => {
expect(nuxt.__module_hook).toBe(1)
expect(nuxt.__renderer_hook).toBe(2)
expect(nuxt.__builder_hook).toBe(3)
})
test.serial('Hooks - Functional', async t => {
t.true(nuxt.__ready_called__)
t.true(builder.__build_done__)
test('Hooks - Functional', async () => {
expect(nuxt.__ready_called__).toBe(true)
expect(builder.__build_done__).toBe(true)
})
test.serial('Hooks - Error', async t => {
t.true(buildSpies.error.calledWithMatch(/build:extendRoutes/))
test('Hooks - Error', async () => {
expect(buildSpies.error.calledWithMatch(/build:extendRoutes/)).toBe(true)
})
test('Middleware', async t => {
test('Middleware', async () => {
let response = await rp(url('/api'))
t.is(response, 'It works!', '/api response is correct')
expect(response).toBe('It works!')
})
test('Hooks - Use external middleware before render', async t => {
test('Hooks - Use external middleware before render', async () => {
let response = await rp(url('/use-middleware'))
t.is(response, 'Use external middleware')
expect(response).toBe('Use external middleware')
})
// Close server and ask nuxt to stop listening to file changes
test.after.always('Closing server and nuxt.js', async t => {
test('Closing server and nuxt.js', async () => {
await nuxt.close()
})

44
test/nuxt.test.js Normal file
View File

@ -0,0 +1,44 @@
import { resolve } from 'path'
import { Nuxt, Builder } from '..'
describe('nuxt', () => {
test('Nuxt.js Class', () => {
expect(typeof Nuxt).toBe('function')
})
test('Nuxt.js Instance', async () => {
const nuxt = new Nuxt({
dev: true,
rootDir: resolve(__dirname, 'fixtures', 'empty')
})
expect(typeof nuxt).toBe('object')
expect(nuxt.options.dev).toBe(true)
expect(typeof nuxt._ready.then).toBe('function')
await nuxt.ready()
expect(nuxt.initialized).toBe(true)
})
test('Fail to build when no pages/ directory but is in the parent', () => {
const nuxt = new Nuxt({
dev: false,
rootDir: resolve(__dirname, 'fixtures', 'empty', 'pages')
})
return new Builder(nuxt).build().catch(err => {
let s = String(err)
expect(s.includes('No `pages` directory found')).toBe(true)
expect(s.includes('Did you mean to run `nuxt` in the parent (`../`) directory?')).toBe(true)
})
})
test('Fail to build when no pages/ directory', () => {
const nuxt = new Nuxt({
dev: false,
rootDir: resolve(__dirname)
})
return new Builder(nuxt).build().catch(err => {
let s = String(err)
expect(s.includes("Couldn't find a `pages` directory")).toBe(true)
expect(s.includes('Please create one under the project root')).toBe(true)
})
})
})

View File

@ -1,6 +1,4 @@
import test from 'ava'
import { Nuxt, Builder } from '..'
import { interceptLog, release } from './helpers/console'
import { loadConfig } from './helpers/config'
let nuxt = null
@ -8,77 +6,75 @@ let nuxt = null
const port = 4012
const url = route => 'http://localhost:' + port + route
const renderRoute = async _url => {
const window = await nuxt.renderAndGetWindow(url(_url))
const head = window.document.head.innerHTML
const html = window.document.body.innerHTML
return { window, head, html }
}
describe('spa', () => {
const renderRoute = async _url => {
const window = await nuxt.renderAndGetWindow(url(_url))
const head = window.document.head.innerHTML
const html = window.document.body.innerHTML
return { window, head, html }
}
// Init nuxt.js and create server listening on localhost:4000
test.serial('Init Nuxt.js', async t => {
const config = loadConfig('spa')
// Init nuxt.js and create server listening on localhost:4000
beforeAll(async () => {
const config = loadConfig('spa')
const logSpy = await interceptLog(async () => {
nuxt = new Nuxt(config)
await new Builder(nuxt).build()
new Builder(nuxt).build()
await nuxt.listen(port, 'localhost')
}, 30000)
test('/ (basic spa)', async () => {
// const logSpy = await interceptLog()
const { html } = await renderRoute('/')
expect(html.includes('Hello SPA!')).toBe(true)
// release()
// expect(logSpy.withArgs('created').notCalled).toBe(true)
// expect(logSpy.withArgs('mounted').calledOnce).toBe(true)
})
t.true(logSpy.calledWithMatch('DONE'))
t.true(logSpy.calledWithMatch('OPEN'))
})
test('/custom (custom layout)', async () => {
// const logSpy = await interceptLog()
const { html } = await renderRoute('/custom')
expect(html.includes('Custom layout')).toBe(true)
// release()
// expect(logSpy.withArgs('created').calledOnce).toBe(true)
// expect(logSpy.withArgs('mounted').calledOnce).toBe(true)
})
test.serial('/ (basic spa)', async t => {
const logSpy = await interceptLog()
const { html } = await renderRoute('/')
t.true(html.includes('Hello SPA!'))
release()
t.true(logSpy.withArgs('created').notCalled)
t.true(logSpy.withArgs('mounted').calledOnce)
})
test('/custom (not default layout)', async () => {
// const logSpy = await interceptLog()
const { head } = await renderRoute('/custom')
expect(head.includes('src="/_nuxt/layouts/default.')).toBe(false)
// release()
// expect(logSpy.withArgs('created').calledOnce).toBe(true)
// expect(logSpy.withArgs('mounted').calledOnce).toBe(true)
})
test.serial('/custom (custom layout)', async t => {
const logSpy = await interceptLog()
const { html } = await renderRoute('/custom')
t.true(html.includes('Custom layout'))
release()
t.true(logSpy.withArgs('created').calledOnce)
t.true(logSpy.withArgs('mounted').calledOnce)
})
test('/custom (call mounted and created once)', async () => {
// const logSpy = await interceptLog()
await renderRoute('/custom')
// release()
// expect(logSpy.withArgs('created').calledOnce).toBe(true)
// expect(logSpy.withArgs('mounted').calledOnce).toBe(true)
})
test.serial('/custom (not default layout)', async t => {
const logSpy = await interceptLog()
const { head } = await renderRoute('/custom')
t.false(head.includes('src="/_nuxt/layouts/default.'))
release()
t.true(logSpy.withArgs('created').calledOnce)
t.true(logSpy.withArgs('mounted').calledOnce)
})
test('/mounted', async () => {
const { html } = await renderRoute('/mounted')
test.serial('/custom (call mounted and created once)', async t => {
const logSpy = await interceptLog()
await renderRoute('/custom')
release()
t.true(logSpy.withArgs('created').calledOnce)
t.true(logSpy.withArgs('mounted').calledOnce)
})
expect(html.includes('<h1>Test: updated</h1>')).toBe(true)
})
test.serial('/mounted', async t => {
const { html } = await renderRoute('/mounted')
test('/_nuxt/ (access publicPath in spa mode)', async () => {
await expect(renderRoute('/_nuxt/')).rejects.toMatchObject({
response: {
statusCode: 404,
statusMessage: 'ResourceNotFound'
}
})
})
t.true(html.includes('<h1>Test: updated</h1>'))
})
test('/_nuxt/ (access publicPath in spa mode)', async t => {
const { response: { statusCode, statusMessage } } = await t.throws(
renderRoute('/_nuxt/')
)
t.is(statusCode, 404)
t.is(statusMessage, 'ResourceNotFound')
})
// Close server and ask nuxt to stop listening to file changes
test.after.always('Closing server and nuxt.js', async t => {
await nuxt.close()
// Close server and ask nuxt to stop listening to file changes
test('Closing server and nuxt.js', async () => {
await nuxt.close()
})
})

View File

@ -1,8 +1,6 @@
import test from 'ava'
import { Nuxt, Builder, Utils } from '..'
import { uniq } from 'lodash'
import rp from 'request-promise-native'
import { interceptLog } from './helpers/console'
import { loadConfig } from './helpers/config'
const port = 4008
@ -17,101 +15,98 @@ const url = route => 'http://localhost:' + port + route
// const isWindows = /^win/.test(process.platform)
// Init nuxt.js and create server listening on localhost:4000
test.serial('Init Nuxt.js', async t => {
const config = loadConfig('ssr')
describe('ssr', () => {
// Init nuxt.js and create server listening on localhost:4000
beforeAll(async () => {
const config = loadConfig('ssr')
const logSpy = await interceptLog(async () => {
nuxt = new Nuxt(config)
await new Builder(nuxt).build()
new Builder(nuxt).build()
await nuxt.listen(port, 'localhost')
})
}, 30000)
t.true(logSpy.calledWithMatch('DONE'))
t.true(logSpy.calledWithMatch('OPEN'))
})
// == Uniq Test ==
// The idea behind is pages using a shared nextId() which returns an incrementing id
// So all responses should strictly be different and length of unique responses should equal to responses
// We strictly compare <foorbar>{id}</foorbar> section
// Because other response parts such as window.__NUXT may be different resulting false positive passes.
const uniqueTest = async (t, url) => {
let results = []
// == Uniq Test ==
// The idea behind is pages using a shared nextId() which returns an incrementing id
// So all responses should strictly be different and length of unique responses should equal to responses
// We strictly compare <foorbar>{id}</foorbar> section
// Because other response parts such as window.__NUXT may be different resulting false positive passes.
const uniqueTest = async (t, url) => {
let results = []
await Utils.parallel(range(5), async () => {
let { html } = await nuxt.renderRoute(url)
let foobar = match(FOOBAR_REGEX, html)
results.push(parseInt(foobar))
})
await Utils.parallel(range(5), async () => {
let { html } = await nuxt.renderRoute(url)
let foobar = match(FOOBAR_REGEX, html)
results.push(parseInt(foobar))
})
let isUnique = uniq(results).length === results.length
let isUnique = uniq(results).length === results.length
if (!isUnique) {
/* eslint-disable no-console */
console.log(url + '\n' + results.join(', ') + '\n')
}
if (!isUnique) {
/* eslint-disable no-console */
console.log(url + '\n' + results.join(', ') + '\n')
expect(isUnique).toBe(true)
return results
}
t.true(isUnique)
return results
}
test.serial('unique responses with data()', async t => {
await uniqueTest(t, '/data')
})
test.serial('unique responses with component', async t => {
await uniqueTest(t, '/component')
})
test.serial('unique responses with async components', async t => {
await uniqueTest(t, '/asyncComponent')
})
test.serial('unique responses with asyncData()', async t => {
await uniqueTest(t, '/asyncData')
})
test.serial('unique responses with store initial state', async t => {
await uniqueTest(t, '/store')
})
test.serial('unique responses with nuxtServerInit', async t => {
await uniqueTest(t, '/store?onServerInit=1')
})
test.serial('unique responses with fetch', async t => {
await uniqueTest(t, '/fetch')
})
// == Stress Test ==
// The idea of this test is to ensure there is no memory or data leak during SSR requests
// Or pending promises/sockets and function calls.
// Related issue: https://github.com/nuxt/nuxt.js/issues/1354
const stressTest = async (t, _url, concurrency = 2, steps = 4) => {
let statusCodes = {}
await Utils.sequence(range(steps), async () => {
await Utils.parallel(range(concurrency), async () => {
let response = await rp(url(_url), { resolveWithFullResponse: true })
// Status Code
let code = response.statusCode
if (!statusCodes[code]) {
statusCodes[code] = 0
}
statusCodes[code]++
})
test('unique responses with data()', async () => {
await uniqueTest('/data')
})
t.is(statusCodes[200], concurrency * steps)
}
test('unique responses with component', async () => {
await uniqueTest('/component')
})
test.serial('stress test with asyncData', async t => {
await stressTest(t, '/asyncData')
})
test('unique responses with async components', async () => {
await uniqueTest('/asyncComponent')
})
// Close server and ask nuxt to stop listening to file changes
test.after.always('Closing server and nuxt.js', async t => {
await nuxt.close()
test('unique responses with asyncData()', async () => {
await uniqueTest('/asyncData')
})
test('unique responses with store initial state', async () => {
await uniqueTest('/store')
})
test('unique responses with nuxtServerInit', async () => {
await uniqueTest('/store?onServerInit=1')
})
test('unique responses with fetch', async () => {
await uniqueTest('/fetch')
})
// == Stress Test ==
// The idea of this test is to ensure there is no memory or data leak during SSR requests
// Or pending promises/sockets and function calls.
// Related issue: https://github.com/nuxt/nuxt.js/issues/1354
const stressTest = async (t, _url, concurrency = 2, steps = 4) => {
let statusCodes = {}
await Utils.sequence(range(steps), async () => {
await Utils.parallel(range(concurrency), async () => {
let response = await rp(url(_url), { resolveWithFullResponse: true })
// Status Code
let code = response.statusCode
if (!statusCodes[code]) {
statusCodes[code] = 0
}
statusCodes[code]++
})
})
expect(statusCodes[200]).toBe(concurrency * steps)
}
test('stress test with asyncData', async () => {
await stressTest('/asyncData')
})
// Close server and ask nuxt to stop listening to file changes
test('Closing server and nuxt.js', async () => {
await nuxt.close()
})
})

View File

@ -1,207 +1,205 @@
import test from 'ava'
import ansiHTML from 'ansi-html'
import { Utils } from '..'
test('encodeHtml', t => {
const html = '<h1>Hello</h1>'
t.is(Utils.encodeHtml(html), '&lt;h1&gt;Hello&lt;/h1&gt;')
})
test('getContext', t => {
let ctx = Utils.getContext({ a: 1 }, { b: 2 })
t.is(Utils.getContext.length, 2)
t.is(typeof ctx.req, 'object')
t.is(typeof ctx.res, 'object')
t.is(ctx.req.a, 1)
t.is(ctx.res.b, 2)
})
test('setAnsiColors', t => {
Utils.setAnsiColors(ansiHTML)
t.pass()
})
test('waitFor', async t => {
let s = Date.now()
await Utils.waitFor(100)
t.true(Date.now() - s >= 100)
await Utils.waitFor()
})
test('timeout (promise)', async t => {
const result = await Utils.timeout(Promise.resolve('time not run out'), 100)
t.is(result, 'time not run out')
})
test('timeout (async function)', async t => {
const result = await Utils.timeout(async () => {
await Utils.waitFor(10)
return 'time not run out'
}, 100)
t.is(result, 'time not run out')
})
test('timeout (timeout in 100ms)', async t => {
const timeout = Utils.timeout(Utils.waitFor(200), 100, 'timeout test 100ms')
const { message } = await t.throws(timeout)
t.is(message, 'timeout test 100ms')
})
test('timeout (async timeout in 100ms)', async t => {
const timeout = Utils.timeout(async () => {
await Utils.waitFor(500)
}, 100, 'timeout test 100ms')
const { message } = await t.throws(timeout)
t.is(message, 'timeout test 100ms')
})
test('urlJoin', t => {
t.is(Utils.urlJoin('test', '/about'), 'test/about')
})
test('promisifyRoute (array)', t => {
const array = [1]
const promise = Utils.promisifyRoute(array)
t.is(typeof promise, 'object')
return promise.then(res => {
t.is(res, array)
describe('utils', () => {
test('encodeHtml', () => {
const html = '<h1>Hello</h1>'
expect(Utils.encodeHtml(html)).toBe('&lt;h1&gt;Hello&lt;/h1&gt;')
})
})
test('promisifyRoute (fn => array)', t => {
const array = [1, 2]
const fn = function () {
return array
}
const promise = Utils.promisifyRoute(fn)
t.is(typeof promise, 'object')
return promise.then(res => {
t.is(res, array)
test('getContext', () => {
let ctx = Utils.getContext({ a: 1 }, { b: 2 })
expect(Utils.getContext.length).toBe(2)
expect(typeof ctx.req).toBe('object')
expect(typeof ctx.res).toBe('object')
expect(ctx.req.a).toBe(1)
expect(ctx.res.b).toBe(2)
})
})
test('promisifyRoute (fn => promise)', t => {
const array = [1, 2, 3]
const fn = function () {
return new Promise(resolve => {
resolve(array)
test('setAnsiColors', () => {
Utils.setAnsiColors(ansiHTML)
})
test('waitFor', async () => {
let s = Date.now()
await Utils.waitFor(100)
expect(Date.now() - s >= 100).toBe(true)
await Utils.waitFor()
})
test('timeout (promise)', async () => {
const result = await Utils.timeout(Promise.resolve('time not run out'), 100)
expect(result).toBe('time not run out')
})
test('timeout (async function)', async () => {
const result = await Utils.timeout(async () => {
await Utils.waitFor(10)
return 'time not run out'
}, 100)
expect(result).toBe('time not run out')
})
test('timeout (timeout in 100ms)', async () => {
const timeout = Utils.timeout(Utils.waitFor(200), 100, 'timeout test 100ms')
await expect(timeout).rejects.toThrow('timeout test 100ms')
})
test('timeout (async timeout in 100ms)', async () => {
const timeout = Utils.timeout(async () => {
await Utils.waitFor(500)
}, 100, 'timeout test 100ms')
await expect(timeout).rejects.toThrow('timeout test 100ms')
})
test('urlJoin', () => {
expect(Utils.urlJoin('test', '/about')).toBe('test/about')
})
test('promisifyRoute (array)', () => {
const array = [1]
const promise = Utils.promisifyRoute(array)
expect(typeof promise).toBe('object')
return promise.then(res => {
expect(res).toBe(array)
})
}
const promise = Utils.promisifyRoute(fn)
t.is(typeof promise, 'object')
return promise.then(res => {
t.is(res, array)
})
})
test('promisifyRoute ((fn(args) => promise))', t => {
const fn = function (array) {
return new Promise(resolve => {
resolve(array)
test('promisifyRoute (fn => array)', () => {
const array = [1, 2]
const fn = function () {
return array
}
const promise = Utils.promisifyRoute(fn)
expect(typeof promise).toBe('object')
return promise.then(res => {
expect(res).toBe(array)
})
}
const array = [1, 2, 3]
const promise = Utils.promisifyRoute(fn, array)
t.is(typeof promise, 'object')
return promise.then(res => {
t.is(res, array)
})
test('promisifyRoute (fn => promise)', () => {
const array = [1, 2, 3]
const fn = function () {
return new Promise(resolve => {
resolve(array)
})
}
const promise = Utils.promisifyRoute(fn)
expect(typeof promise).toBe('object')
return promise.then(res => {
expect(res).toBe(array)
})
})
test('promisifyRoute ((fn(args) => promise))', () => {
const fn = function (array) {
return new Promise(resolve => {
resolve(array)
})
}
const array = [1, 2, 3]
const promise = Utils.promisifyRoute(fn, array)
expect(typeof promise).toBe('object')
return promise.then(res => {
expect(res).toBe(array)
})
})
test('promisifyRoute (fn(cb) with error)', () => {
const fn = function (cb) {
cb(new Error('Error here'))
}
const promise = Utils.promisifyRoute(fn)
expect(typeof promise).toBe('object')
return promise.catch(e => {
expect(e.message).toBe('Error here')
})
})
test('promisifyRoute (fn(cb, args) with error)', () => {
const fn = function (cb, array) {
cb(new Error('Error here: ' + array.join()))
}
const array = [1, 2, 3, 4]
const promise = Utils.promisifyRoute(fn, array)
expect(typeof promise).toBe('object')
return promise.catch(e => {
expect(e.message).toBe('Error here: ' + array.join())
})
})
test('promisifyRoute (fn(cb) with result)', () => {
const array = [1, 2, 3, 4]
const fn = function (cb) {
cb(null, array)
}
const promise = Utils.promisifyRoute(fn)
expect(typeof promise).toBe('object')
return promise.then(res => {
expect(res).toBe(array)
})
})
test('promisifyRoute (fn(cb, args) with result)', () => {
const fn = function (cb, array, object) {
cb(null, { array, object })
}
const array = [1, 2, 3, 4]
const object = { a: 1 }
const promise = Utils.promisifyRoute(fn, array, object)
expect(typeof promise).toBe('object')
return promise.then(res => {
expect(res.array).toBe(array)
expect(res.object).toBe(object)
})
})
test('chainFn (mutate, mutate)', () => {
// Pass more than one argument to test that they're actually taken into account
const firstFn = function (obj, count) {
obj.foo = count + 1
}
const secondFn = function (obj, count) {
obj.bar = count + 2
}
const chainedFn = Utils.chainFn(firstFn, secondFn)
expect(chainedFn({}, 10)).toEqual({ foo: 11, bar: 12 })
})
test('chainFn (mutate, return)', () => {
const firstFn = function (obj, count) {
obj.foo = count + 1
}
const secondFn = function (obj, count) {
return Object.assign({}, obj, { bar: count + 2 })
}
const chainedFn = Utils.chainFn(firstFn, secondFn)
expect(chainedFn({}, 10)).toEqual({ foo: 11, bar: 12 })
})
test('chainFn (return, mutate)', () => {
const firstFn = function (obj, count) {
return Object.assign({}, obj, { foo: count + 1 })
}
const secondFn = function (obj, count) {
obj.bar = count + 2
}
const chainedFn = Utils.chainFn(firstFn, secondFn)
expect(chainedFn({}, 10)).toEqual({ foo: 11, bar: 12 })
})
test('chainFn (return, return)', () => {
const firstFn = function (obj, count) {
return Object.assign({}, obj, { foo: count + 1 })
}
const secondFn = function (obj, count) {
return Object.assign({}, obj, { bar: count + 2 })
}
const chainedFn = Utils.chainFn(firstFn, secondFn)
expect(chainedFn({}, 10)).toEqual({ foo: 11, bar: 12 })
})
})
test('promisifyRoute (fn(cb) with error)', t => {
const fn = function (cb) {
cb(new Error('Error here'))
}
const promise = Utils.promisifyRoute(fn)
t.is(typeof promise, 'object')
return promise.catch(e => {
t.is(e.message, 'Error here')
})
})
test('promisifyRoute (fn(cb, args) with error)', t => {
const fn = function (cb, array) {
cb(new Error('Error here: ' + array.join()))
}
const array = [1, 2, 3, 4]
const promise = Utils.promisifyRoute(fn, array)
t.is(typeof promise, 'object')
return promise.catch(e => {
t.is(e.message, 'Error here: ' + array.join())
})
})
test('promisifyRoute (fn(cb) with result)', t => {
const array = [1, 2, 3, 4]
const fn = function (cb) {
cb(null, array)
}
const promise = Utils.promisifyRoute(fn)
t.is(typeof promise, 'object')
return promise.then(res => {
t.is(res, array)
})
})
test('promisifyRoute (fn(cb, args) with result)', t => {
const fn = function (cb, array, object) {
cb(null, { array, object })
}
const array = [1, 2, 3, 4]
const object = { a: 1 }
const promise = Utils.promisifyRoute(fn, array, object)
t.is(typeof promise, 'object')
return promise.then(res => {
t.is(res.array, array)
t.is(res.object, object)
})
})
test('chainFn (mutate, mutate)', t => {
// Pass more than one argument to test that they're actually taken into account
const firstFn = function (obj, count) {
obj.foo = count + 1
}
const secondFn = function (obj, count) {
obj.bar = count + 2
}
const chainedFn = Utils.chainFn(firstFn, secondFn)
const expectedResult = { foo: 11, bar: 12 }
t.deepEqual(chainedFn({}, 10), expectedResult)
})
test('chainFn (mutate, return)', t => {
const firstFn = function (obj, count) {
obj.foo = count + 1
}
const secondFn = function (obj, count) {
return Object.assign({}, obj, { bar: count + 2 })
}
const chainedFn = Utils.chainFn(firstFn, secondFn)
const expectedResult = { foo: 11, bar: 12 }
t.deepEqual(chainedFn({}, 10), expectedResult)
})
test('chainFn (return, mutate)', t => {
const firstFn = function (obj, count) {
return Object.assign({}, obj, { foo: count + 1 })
}
const secondFn = function (obj, count) {
obj.bar = count + 2
}
const chainedFn = Utils.chainFn(firstFn, secondFn)
const expectedResult = { foo: 11, bar: 12 }
t.deepEqual(chainedFn({}, 10), expectedResult)
})
test('chainFn (return, return)', t => {
const firstFn = function (obj, count) {
return Object.assign({}, obj, { foo: count + 1 })
}
const secondFn = function (obj, count) {
return Object.assign({}, obj, { bar: count + 2 })
}
const chainedFn = Utils.chainFn(firstFn, secondFn)
const expectedResult = { foo: 11, bar: 12 }
t.deepEqual(chainedFn({}, 10), expectedResult)
})

View File

@ -1,12 +1,10 @@
import { resolve } from 'path'
import test from 'ava'
import rp from 'request-promise-native'
import { Nuxt, Builder } from '..'
import styleLoader from '../lib/builder/webpack/style-loader'
import { interceptLog, release } from './helpers/console'
import { loadConfig } from './helpers/config'
const port = 4007
@ -15,210 +13,205 @@ const url = route => 'http://localhost:' + port + route
let nuxt = null
let builder = null
// Init nuxt.js and create server listening on localhost:4000
test.before('Init Nuxt.js', async t => {
const config = loadConfig('with-config', {
dev: false
})
describe('with-config', () => {
// Init nuxt.js and create server listening on localhost:4000
beforeAll(async () => {
const config = loadConfig('with-config', {
dev: false
})
const logSpy = await interceptLog(async () => {
nuxt = new Nuxt(config)
builder = new Builder(nuxt)
await builder.build()
await nuxt.listen(port, 'localhost')
}, 30000)
test('/', async () => {
// const logSpy = await interceptLog()
const { html } = await nuxt.renderRoute('/')
expect(html.includes('<h1>I have custom configurations</h1>')).toBe(true)
// release()
// expect(logSpy.calledOnce).toBe(true)
// expect(logSpy.args[0][0]).toBe('Test plugin!')
})
t.true(logSpy.calledWithMatch('DONE'))
t.true(logSpy.calledWithMatch('OPEN'))
})
test('/ (global styles inlined)', async () => {
const { html } = await nuxt.renderRoute('/')
expect(html.includes('.global-css-selector')).toBe(true)
})
test.serial('/', async t => {
const logSpy = await interceptLog()
const { html } = await nuxt.renderRoute('/')
t.true(html.includes('<h1>I have custom configurations</h1>'))
release()
t.true(logSpy.calledOnce)
t.is(logSpy.args[0][0], 'Test plugin!')
})
test('/ (global styles inlined)', async t => {
const { html } = await nuxt.renderRoute('/')
t.true(html.includes('.global-css-selector'))
})
test.skip('/ (preload fonts)', async t => {
const { html } = await nuxt.renderRoute('/')
t.true(
html.includes(
test.skip('/ (preload fonts)', async () => {
const { html } = await nuxt.renderRoute('/')
expect(html.includes(
'<link rel="preload" href="/test/orion/fonts/roboto.7cf5d7c.woff2" as="font" type="font/woff2" crossorigin'
)
)
})
test('/ (custom app.html)', async t => {
const { html } = await nuxt.renderRoute('/')
t.true(html.includes('<p>Made by Nuxt.js team</p>'))
})
test('/ (custom build.publicPath)', async t => {
const { html } = await nuxt.renderRoute('/')
t.true(html.includes('<script src="/test/orion/'))
})
test('/ (custom postcss.config.js)', async t => {
const { html } = await nuxt.renderRoute('/')
t.true(html.includes('::-webkit-input-placeholder'))
})
test.serial('/test/ (router base)', async t => {
const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/test/'))
const html = window.document.body.innerHTML
t.is(window.__NUXT__.layout, 'default')
t.true(html.includes('<h1>Default layout</h1>'))
t.true(html.includes('<h1>I have custom configurations</h1>'))
release()
t.true(logSpy.calledOnce)
t.is(logSpy.args[0][0], 'Test plugin!')
})
test.serial('/test/about (custom layout)', async t => {
const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/test/about'))
t.true(logSpy.calledOnce)
t.is(logSpy.args[0][0], 'Test plugin!')
release()
const html = window.document.body.innerHTML
t.is(window.__NUXT__.layout, 'custom')
t.true(html.includes('<h1>Custom layout</h1>'))
t.true(html.includes('<h1>About page</h1>'))
})
test.serial('/test/desktop (custom layout in desktop folder)', async t => {
const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/test/desktop'))
t.true(logSpy.calledOnce)
t.is(logSpy.args[0][0], 'Test plugin!')
release()
const html = window.document.body.innerHTML
t.is(window.__NUXT__.layout, 'desktop/default')
t.true(html.includes('<h1>Default desktop layout</h1>'))
t.true(html.includes('<h1>Desktop page</h1>'))
})
test.serial('/test/mobile (custom layout in mobile folder)', async t => {
const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/test/mobile'))
t.true(logSpy.calledOnce)
t.is(logSpy.args[0][0], 'Test plugin!')
release()
const html = window.document.body.innerHTML
t.is(window.__NUXT__.layout, 'mobile/default')
t.true(html.includes('<h1>Default mobile layout</h1>'))
t.true(html.includes('<h1>Mobile page</h1>'))
})
test.serial('/test/env', async t => {
const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/test/env'))
t.true(logSpy.calledOnce)
t.is(logSpy.args[0][0], 'Test plugin!')
release()
const html = window.document.body.innerHTML
t.true(html.includes('<h1>Custom env layout</h1>'))
t.true(html.includes('"bool": true'))
t.true(html.includes('"num": 23'))
t.true(html.includes('"string": "Nuxt.js"'))
t.true(html.includes('"bool": false'))
t.true(html.includes('"string": "ok"'))
t.true(html.includes('"num2": 8.23'))
t.true(html.includes('"obj": {'))
})
test.serial('/test/error', async t => {
const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/test/error'))
t.true(logSpy.calledOnce)
t.is(logSpy.args[0][0], 'Test plugin!')
release()
const html = window.document.body.innerHTML
t.true(html.includes('Error page'))
})
test.serial('/test/user-agent', async t => {
const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/test/user-agent'))
t.true(logSpy.calledOnce)
t.is(logSpy.args[0][0], 'Test plugin!')
release()
const html = window.document.body.innerHTML
t.true(html.includes('<pre>Mozilla'))
})
test.serial('/test/about-bis (added with extendRoutes)', async t => {
const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/test/about-bis'))
t.true(logSpy.calledOnce)
t.is(logSpy.args[0][0], 'Test plugin!')
release()
const html = window.document.body.innerHTML
t.true(html.includes('<h1>Custom layout</h1>'))
t.true(html.includes('<h1>About page</h1>'))
})
test.serial('/test/redirect/about-bis (redirect with extendRoutes)', async t => {
const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/test/redirect/about-bis'))
t.true(logSpy.calledOnce)
t.is(logSpy.args[0][0], 'Test plugin!')
release()
const windowHref = window.location.href
t.true(windowHref.includes('/test/about-bis'))
const html = window.document.body.innerHTML
t.true(html.includes('<h1>Custom layout</h1>'))
t.true(html.includes('<h1>About page</h1>'))
})
test('Check stats.json generated by build.analyze', t => {
const stats = require(resolve(
__dirname,
'fixtures/with-config/.nuxt/dist/stats.json'
))
t.is(stats.assets.length > 0, true)
})
test('Check /test/test.txt with custom serve-static options', async t => {
const { headers } = await rp(url('/test/test.txt'), {
resolveWithFullResponse: true
)).toBe(true)
})
t.is(headers['cache-control'], 'public, max-age=31536000')
})
test('Check /test.txt should return 404', async t => {
const err = await t.throws(rp(url('/test.txt')))
t.is(err.response.statusCode, 404)
})
test('/ (custom app.html)', async () => {
const { html } = await nuxt.renderRoute('/')
expect(html.includes('<p>Made by Nuxt.js team</p>')).toBe(true)
})
test('Check build.styleResources for style-resources-loader', async t => {
const loaders = styleLoader.call(builder, 'scss')
const loader = loaders.find(l => l.loader === 'style-resources-loader')
t.is(typeof loader, 'object')
t.deepEqual(loader.options, {
patterns: ['~/assets/pre-process.scss']
test('/ (custom build.publicPath)', async () => {
const { html } = await nuxt.renderRoute('/')
expect(html.includes('<script src="/test/orion/')).toBe(true)
})
test('/ (custom postcss.config.js)', async () => {
const { html } = await nuxt.renderRoute('/')
expect(html.includes('::-webkit-input-placeholder')).toBe(true)
})
test('/test/ (router base)', async () => {
// const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/test/'))
const html = window.document.body.innerHTML
expect(window.__NUXT__.layout).toBe('default')
expect(html.includes('<h1>Default layout</h1>')).toBe(true)
expect(html.includes('<h1>I have custom configurations</h1>')).toBe(true)
// release()
// expect(logSpy.calledOnce).toBe(true)
// expect(logSpy.args[0][0]).toBe('Test plugin!')
})
test('/test/about (custom layout)', async () => {
// const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/test/about'))
// expect(logSpy.calledOnce).toBe(true)
// expect(logSpy.args[0][0]).toBe('Test plugin!')
// release()
const html = window.document.body.innerHTML
expect(window.__NUXT__.layout).toBe('custom')
expect(html.includes('<h1>Custom layout</h1>')).toBe(true)
expect(html.includes('<h1>About page</h1>')).toBe(true)
})
test('/test/desktop (custom layout in desktop folder)', async () => {
// const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/test/desktop'))
// expect(logSpy.calledOnce).toBe(true)
// expect(logSpy.args[0][0]).toBe('Test plugin!')
// release()
const html = window.document.body.innerHTML
expect(window.__NUXT__.layout).toBe('desktop/default')
expect(html.includes('<h1>Default desktop layout</h1>')).toBe(true)
expect(html.includes('<h1>Desktop page</h1>')).toBe(true)
})
test('/test/mobile (custom layout in mobile folder)', async () => {
// const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/test/mobile'))
// expect(logSpy.calledOnce).toBe(true)
// expect(logSpy.args[0][0]).toBe('Test plugin!')
// release()
const html = window.document.body.innerHTML
expect(window.__NUXT__.layout).toBe('mobile/default')
expect(html.includes('<h1>Default mobile layout</h1>')).toBe(true)
expect(html.includes('<h1>Mobile page</h1>')).toBe(true)
})
test('/test/env', async () => {
// const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/test/env'))
// expect(logSpy.calledOnce).toBe(true)
// expect(logSpy.args[0][0]).toBe('Test plugin!')
// release()
const html = window.document.body.innerHTML
expect(html.includes('<h1>Custom env layout</h1>')).toBe(true)
expect(html.includes('"bool": true')).toBe(true)
expect(html.includes('"num": 23')).toBe(true)
expect(html.includes('"string": "Nuxt.js"')).toBe(true)
expect(html.includes('"bool": false')).toBe(true)
expect(html.includes('"string": "ok"')).toBe(true)
expect(html.includes('"num2": 8.23')).toBe(true)
expect(html.includes('"obj": {')).toBe(true)
})
test('/test/error', async () => {
// const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/test/error'))
// expect(logSpy.calledOnce).toBe(true)
// expect(logSpy.args[0][0]).toBe('Test plugin!')
// release()
const html = window.document.body.innerHTML
expect(html.includes('Error page')).toBe(true)
})
test('/test/user-agent', async () => {
// const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/test/user-agent'))
// expect(logSpy.calledOnce).toBe(true)
// expect(logSpy.args[0][0]).toBe('Test plugin!')
// release()
const html = window.document.body.innerHTML
expect(html.includes('<pre>Mozilla')).toBe(true)
})
test('/test/about-bis (added with extendRoutes)', async () => {
// const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/test/about-bis'))
// expect(logSpy.calledOnce).toBe(true)
// expect(logSpy.args[0][0]).toBe('Test plugin!')
// release()
const html = window.document.body.innerHTML
expect(html.includes('<h1>Custom layout</h1>')).toBe(true)
expect(html.includes('<h1>About page</h1>')).toBe(true)
})
test('/test/redirect/about-bis (redirect with extendRoutes)', async () => {
// const logSpy = await interceptLog()
const window = await nuxt.renderAndGetWindow(url('/test/redirect/about-bis'))
// expect(logSpy.calledOnce).toBe(true)
// expect(logSpy.args[0][0]).toBe('Test plugin!')
// release()
const windowHref = window.location.href
expect(windowHref.includes('/test/about-bis')).toBe(true)
const html = window.document.body.innerHTML
expect(html.includes('<h1>Custom layout</h1>')).toBe(true)
expect(html.includes('<h1>About page</h1>')).toBe(true)
})
test('Check stats.json generated by build.analyze', () => {
const stats = require(resolve(
__dirname,
'fixtures/with-config/.nuxt/dist/stats.json'
))
expect(stats.assets.length > 0).toBe(true)
})
test('Check /test/test.txt with custom serve-static options', async () => {
const { headers } = await rp(url('/test/test.txt'), {
resolveWithFullResponse: true
})
expect(headers['cache-control']).toBe('public, max-age=31536000')
})
test('Check /test.txt should return 404', async () => {
await expect(rp(url('/test.txt')))
.rejects.toMatchObject({ statusCode: 404 })
})
test('Check build.styleResources for style-resources-loader', async () => {
const loaders = styleLoader.call(builder, 'scss')
const loader = loaders.find(l => l.loader === 'style-resources-loader')
expect(typeof loader).toBe('object')
expect(loader.options).toEqual({
patterns: ['~/assets/pre-process.scss']
})
})
// Close server and ask nuxt to stop listening to file changes
test('Closing server and nuxt.js', async () => {
await nuxt.close()
})
})
// Close server and ask nuxt to stop listening to file changes
test.after.always('Closing server and nuxt.js', async t => {
await nuxt.close()
})