feat: add tests to check for changed files (#3893)

* feat: add tests to check for changed files

Make sure that if we are building or generating only files in buildDir and generate.dir are changed. If files in another location would also be changed due to a new config option, those locations should be guarded in lib/common/options so you cant set them lower then rootDir or srcDir.

* fix running tests inBand

use simpler path comparisons

* add debug logs for ci

use process.hrtime for waitFor test

* add debug logs for ci

use process.hrtime for waitFor test

* use writeFileSync should probably help

* use forEach instead of map when not returning a value

update waitFor test to compare values with jest

* fix appeveyor

* use lower limit than delay in waitFor test

revert isAppveyor export
This commit is contained in:
Pim 2018-09-18 16:26:41 +02:00 committed by Sébastien Chopin
parent 2dd2f2aea9
commit 88c9bae57b
8 changed files with 97 additions and 15 deletions

View File

@ -154,6 +154,7 @@
"get-port": "^4.0.0", "get-port": "^4.0.0",
"jest": "^23.6.0", "jest": "^23.6.0",
"jsdom": "^12.0.0", "jsdom": "^12.0.0",
"klaw-sync": "^5.0.0",
"pug": "^2.0.3", "pug": "^2.0.3",
"pug-plain-loader": "^1.0.0", "pug-plain-loader": "^1.0.0",
"puppeteer": "^1.8.0", "puppeteer": "^1.8.0",

View File

@ -1,10 +1,10 @@
import { existsSync } from 'fs' import { existsSync, writeFileSync } from 'fs'
import http from 'http' import http from 'http'
import { resolve } from 'path' import { resolve } from 'path'
import { remove } from 'fs-extra' import { remove } from 'fs-extra'
import serveStatic from 'serve-static' import serveStatic from 'serve-static'
import finalhandler from 'finalhandler' import finalhandler from 'finalhandler'
import { Builder, Generator, getPort, loadFixture, Nuxt, rp } from '../utils' import { Builder, Generator, getPort, loadFixture, Nuxt, rp, listPaths, equalOrStartsWith } from '../utils'
let port let port
const url = route => 'http://localhost:' + port + route const url = route => 'http://localhost:' + port + route
@ -13,14 +13,24 @@ const distDir = resolve(rootDir, '.nuxt-generate')
let server = null let server = null
let generator = null let generator = null
let pathsBefore
let changedFileName
describe('basic generate', () => { describe('basic generate', () => {
beforeAll(async () => { beforeAll(async () => {
const config = await loadFixture('basic', { generate: { dir: '.nuxt-generate' } }) const config = await loadFixture('basic', { generate: { dir: '.nuxt-generate' } })
const nuxt = new Nuxt(config) const nuxt = new Nuxt(config)
pathsBefore = listPaths(nuxt.options.rootDir)
// Make sure our check for changed files is really working
changedFileName = resolve(nuxt.options.generate.dir, '..', '.nuxt-generate-changed')
nuxt.hook('generate:done', () => {
writeFileSync(changedFileName, '')
})
const builder = new Builder(nuxt) const builder = new Builder(nuxt)
builder.build = jest.fn() builder.build = jest.fn()
generator = new Generator(nuxt, builder) generator = new Generator(nuxt, builder)
await generator.generate() await generator.generate()
@ -43,6 +53,24 @@ describe('basic generate', () => {
expect(generator.nuxt.__hook_ready_called__).toBe(true) expect(generator.nuxt.__hook_ready_called__).toBe(true)
}) })
test('Check changed files', () => {
// When generating Nuxt we only expect files to change
// within nuxt.options.generate.dir, but also allow other
// .nuxt dirs for when tests are runInBand
const allowChangesDir = resolve(generator.nuxt.options.generate.dir, '..', '.nuxt')
let changedFileFound = false
const paths = listPaths(generator.nuxt.options.rootDir, pathsBefore)
paths.forEach((item) => {
if (item.path === changedFileName) {
changedFileFound = true
} else {
expect(equalOrStartsWith(allowChangesDir, item.path)).toBe(true)
}
})
expect(changedFileFound).toBe(true)
})
test('Format errors', () => { test('Format errors', () => {
const error = generator._formatErrors([ const error = generator._formatErrors([
{ type: 'handled', route: '/h1', error: 'page not found' }, { type: 'handled', route: '/h1', error: 'page not found' },

View File

@ -13,7 +13,7 @@ describe('generator', () => {
const routes = await generator.initRoutes() const routes = await generator.initRoutes()
expect(routes.length).toBe(array.length) expect(routes.length).toBe(array.length)
routes.map((route, index) => { routes.forEach((route, index) => {
expect(route.route).toBe(array[index]) expect(route.route).toBe(array[index])
}) })
}) })
@ -32,7 +32,7 @@ describe('generator', () => {
const routes = await generator.initRoutes() const routes = await generator.initRoutes()
expect(routes.length).toBe(array.length) expect(routes.length).toBe(array.length)
routes.map((route, index) => { routes.forEach((route, index) => {
expect(route.route).toBe(array[index]) expect(route.route).toBe(array[index])
}) })
}) })
@ -51,7 +51,7 @@ describe('generator', () => {
const routes = await generator.initRoutes(array) const routes = await generator.initRoutes(array)
expect(routes.length).toBe(array.length) expect(routes.length).toBe(array.length)
routes.map((route, index) => { routes.forEach((route, index) => {
expect(route.route).toBe(array[index]) expect(route.route).toBe(array[index])
}) })
}) })
@ -70,7 +70,7 @@ describe('generator', () => {
const routes = await generator.initRoutes(...array) const routes = await generator.initRoutes(...array)
expect(routes.length).toBe(array.length) expect(routes.length).toBe(array.length)
routes.map((route, index) => { routes.forEach((route, index) => {
expect(route.route).toBe(array[index]) expect(route.route).toBe(array[index])
}) })
}) })

View File

@ -16,10 +16,15 @@ describe('utils', () => {
expect(ctx.res.b).toBe(2) expect(ctx.res.b).toBe(2)
}) })
test.skip.appveyor('waitFor', async () => { test('waitFor', async () => {
const s = Date.now() const delay = 100
await Utils.waitFor(100) const s = process.hrtime()
expect(Date.now() - s >= 100).toBe(true) await Utils.waitFor(delay)
const t = process.hrtime(s)
// Node.js makes no guarantees about the exact timing of when callbacks will fire
// HTML5 specifies a minimum delay of 4ms for timeouts
// although arbitrary, use this value to determine our lower limit
expect((t[0] * 1e9 + t[1]) / 1e6).not.toBeLessThan(delay - 4)
await Utils.waitFor() await Utils.waitFor()
}) })

View File

@ -1,9 +1,18 @@
import { loadFixture, Nuxt, Builder } from './index' import { loadFixture, Nuxt, Builder, listPaths, equalOrStartsWith } from './index'
export const buildFixture = function (fixture, callback, hooks = []) { export const buildFixture = function (fixture, callback, hooks = []) {
const pathsBefore = {}
let nuxt
test(`Build ${fixture}`, async () => { test(`Build ${fixture}`, async () => {
const config = await loadFixture(fixture) const config = await loadFixture(fixture)
const nuxt = new Nuxt(config) nuxt = new Nuxt(config)
pathsBefore.root = listPaths(nuxt.options.rootDir)
if (nuxt.options.rootDir !== nuxt.options.srcDir) {
pathsBefore.src = listPaths(nuxt.options.srcDir)
}
const buildDone = jest.fn() const buildDone = jest.fn()
hooks.forEach(([hook, fn]) => nuxt.hook(hook, fn)) hooks.forEach(([hook, fn]) => nuxt.hook(hook, fn))
nuxt.hook('build:done', buildDone) nuxt.hook('build:done', buildDone)
@ -15,4 +24,17 @@ export const buildFixture = function (fixture, callback, hooks = []) {
callback(builder) callback(builder)
} }
}, 120000) }, 120000)
test('Check changed files', () => {
expect.hasAssertions()
// When building Nuxt we only expect files to changed
// within the nuxt.options.buildDir
Object.keys(pathsBefore).forEach((key) => {
const paths = listPaths(nuxt.options[`${key}Dir`], pathsBefore[key])
paths.forEach((item) => {
expect(equalOrStartsWith(nuxt.options.buildDir, item.path)).toBe(true)
})
})
})
} }

View File

@ -1,8 +1,9 @@
import path from 'path' import path from 'path'
import fs from 'fs' import fs from 'fs'
import klawSync from 'klaw-sync'
import _getPort from 'get-port' import _getPort from 'get-port'
import { defaultsDeep } from 'lodash' import { defaultsDeep, find } from 'lodash'
import _rp from 'request-promise-native' import _rp from 'request-promise-native'
import pkg from '../../package.json' import pkg from '../../package.json'
import _Nuxt from '../../lib/index.js' import _Nuxt from '../../lib/index.js'
@ -51,3 +52,23 @@ export const waitUntil = async function waitUntil(condition, duration = 20, inte
} }
return false return false
} }
export const listPaths = function listPaths(dir, pathsBefore = [], options = {}) {
if (Array.isArray(pathsBefore) && pathsBefore.length) {
// only return files that didn't exist before building
// and files that have been changed
options.filter = (item) => {
const foundItem = find(pathsBefore, (itemBefore) => {
return item.path === itemBefore.path
})
return typeof foundItem === 'undefined' ||
item.stats.mtimeMs !== foundItem.stats.mtimeMs
}
}
return klawSync(dir, options)
}
export const equalOrStartsWith = function equalOrStartsWith(string1, string2) {
return string1 === string2 || string2.startsWith(string1)
}

View File

@ -1,4 +1,3 @@
const isAppveyor = !!process.env.APPVEYOR const isAppveyor = !!process.env.APPVEYOR
describe.skip.appveyor = isAppveyor ? describe.skip : describe describe.skip.appveyor = isAppveyor ? describe.skip : describe
test.skip.appveyor = isAppveyor ? test.skip : test test.skip.appveyor = isAppveyor ? test.skip : test

View File

@ -4611,6 +4611,12 @@ kind-of@^6.0.0, kind-of@^6.0.2:
version "6.0.2" version "6.0.2"
resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
klaw-sync@^5.0.0:
version "5.0.0"
resolved "https://registry.npmjs.org/klaw-sync/-/klaw-sync-5.0.0.tgz#b8db1249f96a82751c311ee8a626a319db119904"
dependencies:
graceful-fs "^4.1.11"
kleur@^2.0.1: kleur@^2.0.1:
version "2.0.2" version "2.0.2"
resolved "https://registry.npmjs.org/kleur/-/kleur-2.0.2.tgz#b704f4944d95e255d038f0cb05fb8a602c55a300" resolved "https://registry.npmjs.org/kleur/-/kleur-2.0.2.tgz#b704f4944d95e255d038f0cb05fb8a602c55a300"