mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-23 14:15:13 +00:00
test: unit tests for @nuxt/util (#4880)
This commit is contained in:
parent
5101dc6aae
commit
96bab9f09c
@ -4,7 +4,7 @@ export const encodeHtml = function encodeHtml(str) {
|
|||||||
|
|
||||||
export const isString = obj => typeof obj === 'string' || obj instanceof String
|
export const isString = obj => typeof obj === 'string' || obj instanceof String
|
||||||
|
|
||||||
export const isNonEmptyString = obj => obj && isString(obj)
|
export const isNonEmptyString = obj => Boolean(obj && isString(obj))
|
||||||
|
|
||||||
export const isPureObject = function isPureObject(o) {
|
export const isPureObject = function isPureObject(o) {
|
||||||
return !Array.isArray(o) && typeof o === 'object'
|
return !Array.isArray(o) && typeof o === 'object'
|
||||||
|
@ -11,7 +11,6 @@ export const startsWithRootAlias = startsWithAlias(['@@', '~~'])
|
|||||||
export const isWindows = /^win/.test(process.platform)
|
export const isWindows = /^win/.test(process.platform)
|
||||||
|
|
||||||
export const wp = function wp(p = '') {
|
export const wp = function wp(p = '') {
|
||||||
/* istanbul ignore if */
|
|
||||||
if (isWindows) {
|
if (isWindows) {
|
||||||
return p.replace(/\\/g, '\\\\')
|
return p.replace(/\\/g, '\\\\')
|
||||||
}
|
}
|
||||||
@ -19,7 +18,6 @@ export const wp = function wp(p = '') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const wChunk = function wChunk(p = '') {
|
export const wChunk = function wChunk(p = '') {
|
||||||
/* istanbul ignore if */
|
|
||||||
if (isWindows) {
|
if (isWindows) {
|
||||||
return p.replace(/\//g, '_')
|
return p.replace(/\//g, '_')
|
||||||
}
|
}
|
||||||
@ -62,7 +60,7 @@ export const relativeTo = function relativeTo() {
|
|||||||
// Make correct relative path
|
// Make correct relative path
|
||||||
let rp = path.relative(dir, _path)
|
let rp = path.relative(dir, _path)
|
||||||
if (rp[0] !== '.') {
|
if (rp[0] !== '.') {
|
||||||
rp = './' + rp
|
rp = '.' + path.sep + rp
|
||||||
}
|
}
|
||||||
|
|
||||||
return wp(rp)
|
return wp(rp)
|
||||||
|
@ -9,7 +9,6 @@ export const flatRoutes = function flatRoutes(router, _path = '', routes = []) {
|
|||||||
if ([':', '*'].some(c => r.path.includes(c))) {
|
if ([':', '*'].some(c => r.path.includes(c))) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
/* istanbul ignore if */
|
|
||||||
if (r.children) {
|
if (r.children) {
|
||||||
if (_path === '' && r.path === '/') {
|
if (_path === '' && r.path === '/') {
|
||||||
routes.push('/')
|
routes.push('/')
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import serialize from 'serialize-javascript'
|
import serialize from 'serialize-javascript'
|
||||||
|
|
||||||
export function serializeFunction(func) {
|
export function serializeFunction(func) {
|
||||||
|
@ -10,7 +10,6 @@ export const parallel = function parallel(tasks, fn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const chainFn = function chainFn(base, fn) {
|
export const chainFn = function chainFn(base, fn) {
|
||||||
/* istanbul ignore if */
|
|
||||||
if (typeof fn !== 'function') {
|
if (typeof fn !== 'function') {
|
||||||
return base
|
return base
|
||||||
}
|
}
|
||||||
|
121
packages/utils/test/__snapshots__/route.test.js.snap
Normal file
121
packages/utils/test/__snapshots__/route.test.js.snap
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`util: route util: route create createRoutes should allow snake case routes in posix system 1`] = `
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"chunkName": "pages/parent/index",
|
||||||
|
"component": "/some/nuxt/app/pages/parent/index.vue",
|
||||||
|
"name": "parent",
|
||||||
|
"path": "/parent",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"chunkName": "pages/snake_case_route",
|
||||||
|
"component": "/some/nuxt/app/pages/snake_case_route.vue",
|
||||||
|
"name": "snake_case_route",
|
||||||
|
"path": "/snake_case_route",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"chunkName": "pages/parent/child/index",
|
||||||
|
"component": "/some/nuxt/app/pages/parent/child/index.vue",
|
||||||
|
"name": "parent-child",
|
||||||
|
"path": "/parent/child",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"chunkName": "pages/parent/child/test",
|
||||||
|
"component": "/some/nuxt/app/pages/parent/child/test.vue",
|
||||||
|
"name": "parent-child-test",
|
||||||
|
"path": "/parent/child/test",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"children": Array [
|
||||||
|
Object {
|
||||||
|
"chunkName": "pages/another_route/_id",
|
||||||
|
"component": "/some/nuxt/app/pages/another_route/_id.vue",
|
||||||
|
"name": "another_route-id",
|
||||||
|
"path": "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"chunkName": "pages/another_route/_id",
|
||||||
|
"component": "/some/nuxt/app/pages/another_route/_id.vue",
|
||||||
|
"path": "/another_route/:id?",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"chunkName": "pages/subpage/_param",
|
||||||
|
"component": "/some/nuxt/app/pages/subpage/_param.vue",
|
||||||
|
"name": "subpage-param",
|
||||||
|
"path": "/subpage/:param?",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"chunkName": "pages/index",
|
||||||
|
"component": "/some/nuxt/app/pages/index.vue",
|
||||||
|
"name": "index",
|
||||||
|
"path": "/",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"chunkName": "pages/_param",
|
||||||
|
"component": "/some/nuxt/app/pages/_param.vue",
|
||||||
|
"name": "param",
|
||||||
|
"path": "/:param",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`util: route util: route create createRoutes should allow snake case routes in windows system 1`] = `
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"chunkName": "pages/parent/index",
|
||||||
|
"component": "\\\\\\\\\\\\\\\\some\\\\\\\\nuxt\\\\\\\\app\\\\\\\\pages\\\\\\\\parent\\\\\\\\index.vue",
|
||||||
|
"name": "parent",
|
||||||
|
"path": "/parent",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"chunkName": "pages/snake_case_route",
|
||||||
|
"component": "\\\\\\\\\\\\\\\\some\\\\\\\\nuxt\\\\\\\\app\\\\\\\\pages\\\\\\\\snake_case_route.vue",
|
||||||
|
"name": "snake_case_route",
|
||||||
|
"path": "/snake_case_route",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"chunkName": "pages/parent/child/index",
|
||||||
|
"component": "\\\\\\\\\\\\\\\\some\\\\\\\\nuxt\\\\\\\\app\\\\\\\\pages\\\\\\\\parent\\\\\\\\child\\\\\\\\index.vue",
|
||||||
|
"name": "parent-child",
|
||||||
|
"path": "/parent/child",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"chunkName": "pages/parent/child/test",
|
||||||
|
"component": "\\\\\\\\\\\\\\\\some\\\\\\\\nuxt\\\\\\\\app\\\\\\\\pages\\\\\\\\parent\\\\\\\\child\\\\\\\\test.vue",
|
||||||
|
"name": "parent-child-test",
|
||||||
|
"path": "/parent/child/test",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"children": Array [
|
||||||
|
Object {
|
||||||
|
"chunkName": "pages/another_route/_id",
|
||||||
|
"component": "\\\\\\\\\\\\\\\\some\\\\\\\\nuxt\\\\\\\\app\\\\\\\\pages\\\\\\\\another_route\\\\\\\\_id.vue",
|
||||||
|
"name": "another_route-id",
|
||||||
|
"path": "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"chunkName": "pages/another_route/_id",
|
||||||
|
"component": "\\\\\\\\\\\\\\\\some\\\\\\\\nuxt\\\\\\\\app\\\\\\\\pages\\\\\\\\another_route\\\\\\\\_id.vue",
|
||||||
|
"path": "/another_route/:id?",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"chunkName": "pages/subpage/_param",
|
||||||
|
"component": "\\\\\\\\\\\\\\\\some\\\\\\\\nuxt\\\\\\\\app\\\\\\\\pages\\\\\\\\subpage\\\\\\\\_param.vue",
|
||||||
|
"name": "subpage-param",
|
||||||
|
"path": "/subpage/:param?",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"chunkName": "pages/index",
|
||||||
|
"component": "\\\\\\\\\\\\\\\\some\\\\\\\\nuxt\\\\\\\\app\\\\\\\\pages\\\\\\\\index.vue",
|
||||||
|
"name": "index",
|
||||||
|
"path": "/",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"chunkName": "pages/_param",
|
||||||
|
"component": "\\\\\\\\\\\\\\\\some\\\\\\\\nuxt\\\\\\\\app\\\\\\\\pages\\\\\\\\_param.vue",
|
||||||
|
"name": "param",
|
||||||
|
"path": "/:param",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`;
|
24
packages/utils/test/context.test.js
Normal file
24
packages/utils/test/context.test.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { getContext, determineGlobals } from '../src/context'
|
||||||
|
|
||||||
|
describe('util: context', () => {
|
||||||
|
test('should get context with req and res', () => {
|
||||||
|
const ctx = getContext({ a: 1 }, { b: 2 })
|
||||||
|
|
||||||
|
expect(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('should get correct globals', () => {
|
||||||
|
const globals = {
|
||||||
|
foo: name => `${name}: foo`,
|
||||||
|
bar: name => `${name}: bar`,
|
||||||
|
baz: 'baz'
|
||||||
|
}
|
||||||
|
const result = determineGlobals('global', globals)
|
||||||
|
|
||||||
|
expect(result).toEqual({ bar: 'global: bar', foo: 'global: foo', baz: 'baz' })
|
||||||
|
})
|
||||||
|
})
|
22
packages/utils/test/index.test.js
Normal file
22
packages/utils/test/index.test.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import * as Util from '../src'
|
||||||
|
import * as context from '../src/context'
|
||||||
|
import * as lang from '../src/lang'
|
||||||
|
import * as resolve from '../src/resolve'
|
||||||
|
import * as route from '../src/route'
|
||||||
|
import * as serialize from '../src/serialize'
|
||||||
|
import * as task from '../src/task'
|
||||||
|
import * as timer from '../src/timer'
|
||||||
|
|
||||||
|
describe('util: entry', () => {
|
||||||
|
test('should export all methods from utils folder', () => {
|
||||||
|
expect(Util).toEqual({
|
||||||
|
...context,
|
||||||
|
...lang,
|
||||||
|
...resolve,
|
||||||
|
...route,
|
||||||
|
...serialize,
|
||||||
|
...task,
|
||||||
|
...timer
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
55
packages/utils/test/lang.test.js
Normal file
55
packages/utils/test/lang.test.js
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import {
|
||||||
|
encodeHtml, isString, isNonEmptyString,
|
||||||
|
isPureObject, isUrl, urlJoin, wrapArray, stripWhitespace
|
||||||
|
} from '../src/lang'
|
||||||
|
|
||||||
|
describe('util: lang', () => {
|
||||||
|
test('should check if given argument is string', () => {
|
||||||
|
expect(isString('str')).toEqual(true)
|
||||||
|
expect(isString(String(100))).toEqual(true)
|
||||||
|
expect(isString(100)).toEqual(false)
|
||||||
|
expect(isString([])).toEqual(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should check if given argument is empty string', () => {
|
||||||
|
expect(isNonEmptyString('str')).toEqual(true)
|
||||||
|
expect(isNonEmptyString([])).toEqual(false)
|
||||||
|
expect(isNonEmptyString('')).toEqual(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should check if given argument is pure object', () => {
|
||||||
|
expect(isPureObject({})).toEqual(true)
|
||||||
|
expect(isPureObject([])).toEqual(false)
|
||||||
|
expect(isPureObject(Number('1'))).toEqual(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should check if given argument is url', () => {
|
||||||
|
expect(isUrl('http://localhost')).toEqual(true)
|
||||||
|
expect(isUrl('https://localhost')).toEqual(true)
|
||||||
|
expect(isUrl('//localhost')).toEqual(true)
|
||||||
|
expect(isUrl('localhost')).toEqual(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should wrap given argument with array', () => {
|
||||||
|
expect(wrapArray([ 'array' ])).toEqual([ 'array' ])
|
||||||
|
expect(wrapArray('str')).toEqual([ 'str' ])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should strip white spaces in given argument', () => {
|
||||||
|
expect(stripWhitespace('foo')).toEqual('foo')
|
||||||
|
expect(stripWhitespace('foo\t\r\f\n')).toEqual('foo\n')
|
||||||
|
expect(stripWhitespace('foo{\n\n\n')).toEqual('foo{\n')
|
||||||
|
expect(stripWhitespace('\n\n\n\f\r\f}')).toEqual('\n\f\r\f}')
|
||||||
|
expect(stripWhitespace('foo\n\n\nbar')).toEqual('foo\n\nbar')
|
||||||
|
expect(stripWhitespace('foo\n\n\n')).toEqual('foo\n')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should encode html', () => {
|
||||||
|
const html = '<h1>Hello</h1>'
|
||||||
|
expect(encodeHtml(html)).toEqual('<h1>Hello</h1>')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should join url', () => {
|
||||||
|
expect(urlJoin('test', '/about')).toEqual('test/about')
|
||||||
|
})
|
||||||
|
})
|
85
packages/utils/test/resolve.posix.test.js
Normal file
85
packages/utils/test/resolve.posix.test.js
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import consola from 'consola'
|
||||||
|
|
||||||
|
import {
|
||||||
|
startsWithAlias, startsWithSrcAlias, wp, wChunk,
|
||||||
|
relativeTo, defineAlias, isIndexFileAndFolder, getMainModule
|
||||||
|
} from '../src/resolve'
|
||||||
|
|
||||||
|
describe.posix('util: resolve', () => {
|
||||||
|
test('should check if path starts with alias', () => {
|
||||||
|
expect(startsWithAlias(['/var'])('/var/nuxt/src')).toEqual(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should check if path starts with root alias', () => {
|
||||||
|
expect(startsWithSrcAlias('@/assets')).toEqual(true)
|
||||||
|
expect(startsWithSrcAlias('~/pages')).toEqual(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should check if path starts with src alias', () => {
|
||||||
|
expect(startsWithSrcAlias('@@/src/assets')).toEqual(true)
|
||||||
|
expect(startsWithSrcAlias('~~/src/pages')).toEqual(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should return same path in linux', () => {
|
||||||
|
expect(wp('/var/nuxt\\ src/')).toEqual('/var/nuxt\\ src/')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should return same path in linux', () => {
|
||||||
|
expect(wChunk('nuxt/layout/test')).toEqual('nuxt/layout/test')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should define alias', () => {
|
||||||
|
const nuxt = {}
|
||||||
|
const server = {
|
||||||
|
name: 'nuxt',
|
||||||
|
bound: () => 'bound fn',
|
||||||
|
test: () => 'test defineAlias'
|
||||||
|
}
|
||||||
|
|
||||||
|
defineAlias(nuxt, server, ['name', 'bound'])
|
||||||
|
defineAlias(nuxt, server, ['test'], { bind: false, warn: true })
|
||||||
|
|
||||||
|
expect(nuxt.name).toEqual(server.name)
|
||||||
|
expect(nuxt.bound).not.toBe(server.bound)
|
||||||
|
expect(nuxt.bound()).toEqual('bound fn')
|
||||||
|
expect(nuxt.test).toBe(server.test)
|
||||||
|
expect(nuxt.test()).toEqual('test defineAlias')
|
||||||
|
expect(consola.warn).toBeCalledTimes(1)
|
||||||
|
expect(consola.warn).toBeCalledWith({
|
||||||
|
message: `'test' is deprecated'`,
|
||||||
|
additional: expect.any(String)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should check if given argument is index file or folder', () => {
|
||||||
|
expect(isIndexFileAndFolder(['/var/nuxt/plugins/test'])).toEqual(false)
|
||||||
|
expect(isIndexFileAndFolder(['/var/nuxt/plugins/test/index.js'])).toEqual(false)
|
||||||
|
expect(isIndexFileAndFolder(['/var/nuxt/plugins/test', '/var/nuxt/plugins/test/index.js'])).toEqual(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should return main module', () => {
|
||||||
|
expect(getMainModule()).toHaveProperty('children', 'exports', 'filename', 'path')
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('relativeTo', () => {
|
||||||
|
const path1 = '@/foo'
|
||||||
|
const path2 = '@/bar'
|
||||||
|
|
||||||
|
test('should resolve alias path', () => {
|
||||||
|
expect(relativeTo(path1, path2)).toBe('@/bar')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should keep webpack inline loaders prepended', () => {
|
||||||
|
expect(relativeTo(path1, `loader1!loader2!${path2}`))
|
||||||
|
.toEqual('loader1!loader2!@/bar')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should check path which is not started with alias', () => {
|
||||||
|
expect(relativeTo('/var/nuxt/foo/bar', '/var/nuxt/foo/baz')).toBe('../baz')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should check path which is not started with alias ', () => {
|
||||||
|
expect(relativeTo('/var/nuxt/foo', '/var/nuxt/foo/bar')).toBe('./bar')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
90
packages/utils/test/resolve.win.test.js
Normal file
90
packages/utils/test/resolve.win.test.js
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import consola from 'consola'
|
||||||
|
|
||||||
|
import {
|
||||||
|
wp, wChunk, r, relativeTo,
|
||||||
|
startsWithAlias, startsWithSrcAlias,
|
||||||
|
defineAlias, isIndexFileAndFolder, getMainModule
|
||||||
|
} from '../src/resolve'
|
||||||
|
|
||||||
|
describe.win('util: resolve windows', () => {
|
||||||
|
test('should format windows separator', () => {
|
||||||
|
expect(wp('c:\\nuxt\\src')).toEqual('c:\\\\nuxt\\\\src')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should format windows path', () => {
|
||||||
|
expect(wChunk('nuxt/layout/test')).toEqual('nuxt_layout_test')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should resolve alias path', () => {
|
||||||
|
expect(r('@\\layout\\test')).toEqual('@\\\\layout\\\\test')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should check if path starts with alias', () => {
|
||||||
|
expect(startsWithAlias(['#'])('#layout/test')).toEqual(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should check if path starts with root alias', () => {
|
||||||
|
expect(startsWithSrcAlias('@/assets')).toEqual(true)
|
||||||
|
expect(startsWithSrcAlias('~/pages')).toEqual(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should check if path starts with src alias', () => {
|
||||||
|
expect(startsWithSrcAlias('@@/src/assets')).toEqual(true)
|
||||||
|
expect(startsWithSrcAlias('~~/src/pages')).toEqual(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should define alias', () => {
|
||||||
|
const nuxt = {}
|
||||||
|
const server = {
|
||||||
|
name: 'nuxt',
|
||||||
|
bound: () => 'bound fn',
|
||||||
|
test: () => 'test defineAlias'
|
||||||
|
}
|
||||||
|
|
||||||
|
defineAlias(nuxt, server, ['name', 'bound'])
|
||||||
|
defineAlias(nuxt, server, ['test'], { bind: false, warn: true })
|
||||||
|
|
||||||
|
expect(nuxt.name).toEqual(server.name)
|
||||||
|
expect(nuxt.bound).not.toBe(server.bound)
|
||||||
|
expect(nuxt.bound()).toEqual('bound fn')
|
||||||
|
expect(nuxt.test).toBe(server.test)
|
||||||
|
expect(nuxt.test()).toEqual('test defineAlias')
|
||||||
|
expect(consola.warn).toBeCalledTimes(1)
|
||||||
|
expect(consola.warn).toBeCalledWith({
|
||||||
|
message: `'test' is deprecated'`,
|
||||||
|
additional: expect.any(String)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should check if given argument is index file or folder', () => {
|
||||||
|
expect(isIndexFileAndFolder(['/var/nuxt/plugins/test'])).toEqual(false)
|
||||||
|
expect(isIndexFileAndFolder(['/var/nuxt/plugins/test/index.js'])).toEqual(false)
|
||||||
|
expect(isIndexFileAndFolder(['/var/nuxt/plugins/test', '/var/nuxt/plugins/test/index.js'])).toEqual(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should return main module', () => {
|
||||||
|
expect(getMainModule()).toHaveProperty('children', 'exports', 'filename', 'path')
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('relativeTo', () => {
|
||||||
|
const path1 = '@\\foo'
|
||||||
|
const path2 = '@\\bar'
|
||||||
|
|
||||||
|
test('should resolve alias path', () => {
|
||||||
|
expect(relativeTo(path1, path2)).toBe('@\\\\bar')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should keep webpack inline loaders prepended', () => {
|
||||||
|
expect(relativeTo(path1, `loader1!loader2!${path2}`))
|
||||||
|
.toBe('loader1!loader2!@\\\\bar')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should check path which is not started with alias', () => {
|
||||||
|
expect(relativeTo('c:\\foo\\bar', 'c:\\foo\\baz')).toBe('..\\\\baz')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should check path which is not started with alias ', () => {
|
||||||
|
expect(relativeTo('c:\\foo', 'c:\\foo\\baz')).toBe('.\\\\baz')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
198
packages/utils/test/route.test.js
Normal file
198
packages/utils/test/route.test.js
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
import { flatRoutes, createRoutes, guardDir, promisifyRoute } from '../src/route'
|
||||||
|
|
||||||
|
describe('util: route', () => {
|
||||||
|
test('should flat route with path', () => {
|
||||||
|
const routes = flatRoutes([
|
||||||
|
{ name: 'login', path: '/login' },
|
||||||
|
{ name: 'about', path: '/about' },
|
||||||
|
{ name: 'posts',
|
||||||
|
path: '',
|
||||||
|
children: [
|
||||||
|
{ name: 'posts-list', path: '' },
|
||||||
|
{ name: 'posts-create', path: 'post' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
])
|
||||||
|
expect(routes).toEqual([ '/login', '/about', '', '/post' ])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should ignore route with * and :', () => {
|
||||||
|
const routes = flatRoutes([
|
||||||
|
{ name: 'login', path: '/login' },
|
||||||
|
{ name: 'foo', path: '/foo/:id' },
|
||||||
|
{ name: 'bar', path: '/bar/*' }
|
||||||
|
])
|
||||||
|
expect(routes).toEqual([ '/login' ])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should resolve route with /', () => {
|
||||||
|
const routes = flatRoutes([
|
||||||
|
{ name: 'foo',
|
||||||
|
path: '/',
|
||||||
|
children: [
|
||||||
|
{ name: 'foo-bar', path: 'foo/bar' },
|
||||||
|
{ name: 'foo-baz', path: 'foo/baz' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
])
|
||||||
|
expect(routes).toEqual([ '/', '/foo/bar', '/foo/baz' ])
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('util: route guard', () => {
|
||||||
|
test('should guard parent dir', () => {
|
||||||
|
expect(() => {
|
||||||
|
guardDir({ dir1: '/root/parent', dir2: '/root' }, 'dir1', 'dir2')
|
||||||
|
}).toThrow()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should guard same dir', () => {
|
||||||
|
expect(() => {
|
||||||
|
guardDir({ dir1: '/root/parent', dir2: '/root/parent' }, 'dir1', 'dir2')
|
||||||
|
}).toThrow()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should not guard same level dir', () => {
|
||||||
|
expect(() => {
|
||||||
|
guardDir({ dir1: '/root/parent-next', dir2: '/root/parent' }, 'dir1', 'dir2')
|
||||||
|
}).not.toThrow()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should not guard same level dir - 2', () => {
|
||||||
|
expect(() => {
|
||||||
|
guardDir({ dir1: '/root/parent', dir2: '/root/parent-next' }, 'dir1', 'dir2')
|
||||||
|
}).not.toThrow()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should not guard child dir', () => {
|
||||||
|
expect(() => {
|
||||||
|
guardDir({ dir1: '/root/parent', dir2: '/root/parent/child' }, 'dir1', 'dir2')
|
||||||
|
}).not.toThrow()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('util: route promisifyRoute', () => {
|
||||||
|
test('should promisify array routes', () => {
|
||||||
|
const array = [1]
|
||||||
|
const promise = promisifyRoute(array)
|
||||||
|
expect(typeof promise).toBe('object')
|
||||||
|
return promise.then((res) => {
|
||||||
|
expect(res).toBe(array)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should promisify functional routes', () => {
|
||||||
|
const array = [1, 2]
|
||||||
|
const fn = function () {
|
||||||
|
return array
|
||||||
|
}
|
||||||
|
const promise = promisifyRoute(fn)
|
||||||
|
expect(typeof promise).toBe('object')
|
||||||
|
return promise.then((res) => {
|
||||||
|
expect(res).toBe(array)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should promisify promisable functional routes', () => {
|
||||||
|
const array = [1, 2, 3]
|
||||||
|
const fn = function () {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
resolve(array)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const promise = promisifyRoute(fn)
|
||||||
|
expect(typeof promise).toBe('object')
|
||||||
|
return promise.then((res) => {
|
||||||
|
expect(res).toBe(array)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should promisify promisable functional routes with arguments', () => {
|
||||||
|
const fn = function (array) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
resolve(array)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const array = [1, 2, 3]
|
||||||
|
const promise = promisifyRoute(fn, array)
|
||||||
|
expect(typeof promise).toBe('object')
|
||||||
|
return promise.then((res) => {
|
||||||
|
expect(res).toBe(array)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should promisify functional routes with error', () => {
|
||||||
|
const fn = function (cb) {
|
||||||
|
cb(new Error('Error here'))
|
||||||
|
}
|
||||||
|
const promise = promisifyRoute(fn)
|
||||||
|
expect(typeof promise).toBe('object')
|
||||||
|
return promise.catch((e) => {
|
||||||
|
expect(e.message).toBe('Error here')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should promisify functional routes with arguments and error', () => {
|
||||||
|
const fn = function (cb, array) {
|
||||||
|
cb(new Error('Error here: ' + array.join()))
|
||||||
|
}
|
||||||
|
const array = [1, 2, 3, 4]
|
||||||
|
const promise = promisifyRoute(fn, array)
|
||||||
|
expect(typeof promise).toBe('object')
|
||||||
|
return promise.catch((e) => {
|
||||||
|
expect(e.message).toBe('Error here: ' + array.join())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should promisify functional routes with result', () => {
|
||||||
|
const array = [1, 2, 3, 4]
|
||||||
|
const fn = function (cb) {
|
||||||
|
cb(null, array)
|
||||||
|
}
|
||||||
|
const promise = promisifyRoute(fn)
|
||||||
|
expect(typeof promise).toBe('object')
|
||||||
|
return promise.then((res) => {
|
||||||
|
expect(res).toBe(array)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should promisify functional routes with arguments and result', () => {
|
||||||
|
const fn = function (cb, array, object) {
|
||||||
|
cb(null, { array, object })
|
||||||
|
}
|
||||||
|
const array = [1, 2, 3, 4]
|
||||||
|
const object = { a: 1 }
|
||||||
|
const promise = promisifyRoute(fn, array, object)
|
||||||
|
expect(typeof promise).toBe('object')
|
||||||
|
return promise.then((res) => {
|
||||||
|
expect(res.array).toBe(array)
|
||||||
|
expect(res.object).toBe(object)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('util: route create', () => {
|
||||||
|
const files = [
|
||||||
|
'pages/index.vue',
|
||||||
|
'pages/_param.vue',
|
||||||
|
'pages/subpage/_param.vue',
|
||||||
|
'pages/snake_case_route.vue',
|
||||||
|
'pages/another_route/_id.vue',
|
||||||
|
'pages/another_route/_id.vue',
|
||||||
|
'pages/parent/index.vue',
|
||||||
|
'pages/parent/child/index.vue',
|
||||||
|
'pages/parent/child/test.vue'
|
||||||
|
]
|
||||||
|
const srcDir = '/some/nuxt/app'
|
||||||
|
const pagesDir = 'pages'
|
||||||
|
|
||||||
|
test.posix('createRoutes should allow snake case routes in posix system', () => {
|
||||||
|
const routesResult = createRoutes(files, srcDir, pagesDir)
|
||||||
|
expect(routesResult).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
|
||||||
|
test.win('createRoutes should allow snake case routes in windows system', () => {
|
||||||
|
const routesResult = createRoutes(files, srcDir, pagesDir)
|
||||||
|
expect(routesResult).toMatchSnapshot()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
61
packages/utils/test/serialize.test.js
Normal file
61
packages/utils/test/serialize.test.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import { serializeFunction } from '../src/serialize'
|
||||||
|
|
||||||
|
describe('util: serialize', () => {
|
||||||
|
test('should serialize normal function', () => {
|
||||||
|
const obj = {
|
||||||
|
fn: function () {}
|
||||||
|
}
|
||||||
|
expect(serializeFunction(obj.fn)).toEqual('function () {}')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should serialize shorthand function', () => {
|
||||||
|
const obj = {
|
||||||
|
fn() {}
|
||||||
|
}
|
||||||
|
expect(serializeFunction(obj.fn)).toEqual('function() {}')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should serialize arrow function', () => {
|
||||||
|
const obj = {
|
||||||
|
fn: () => {}
|
||||||
|
}
|
||||||
|
expect(serializeFunction(obj.fn)).toEqual('() => {}')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should not replace custom scripts', () => {
|
||||||
|
const obj = {
|
||||||
|
fn() {
|
||||||
|
return 'function xyz(){};a=false?true:xyz();'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(serializeFunction(obj.fn)).toEqual(`function () {
|
||||||
|
return 'function xyz(){};a=false?true:xyz();';
|
||||||
|
}`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should serialize internal function', () => {
|
||||||
|
const obj = {
|
||||||
|
fn(arg) {
|
||||||
|
if (arg) {
|
||||||
|
return {
|
||||||
|
title() {
|
||||||
|
return 'test'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(serializeFunction(obj.fn)).toEqual(`function(arg) {
|
||||||
|
if (arg) {
|
||||||
|
return {
|
||||||
|
title: function () {
|
||||||
|
return 'test';
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
})
|
||||||
|
})
|
106
packages/utils/test/task.test.js
Normal file
106
packages/utils/test/task.test.js
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
import consola from 'consola'
|
||||||
|
import { sequence, parallel, chainFn } from '../src/task'
|
||||||
|
|
||||||
|
describe('util: task', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should call fn in sequence', async () => {
|
||||||
|
const fn = jest.fn(consola.log)
|
||||||
|
await sequence([1, 2, 3, 4], fn)
|
||||||
|
|
||||||
|
expect(fn).toBeCalledTimes(4)
|
||||||
|
expect(consola.log).toBeCalledTimes(4)
|
||||||
|
expect(consola.log).nthCalledWith(1, 1)
|
||||||
|
expect(consola.log).nthCalledWith(2, 2)
|
||||||
|
expect(consola.log).nthCalledWith(3, 3)
|
||||||
|
expect(consola.log).nthCalledWith(4, 4)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should call fn in parallel', async () => {
|
||||||
|
jest.spyOn(Promise, 'all')
|
||||||
|
jest.spyOn(Promise, 'resolve')
|
||||||
|
|
||||||
|
await parallel([1, 2, 3, 4], (num, index) => [num, index])
|
||||||
|
|
||||||
|
expect(Promise.all).toBeCalledTimes(1)
|
||||||
|
expect(Promise.resolve).toBeCalledTimes(4)
|
||||||
|
expect(Promise.resolve).nthCalledWith(1, [1, 0])
|
||||||
|
expect(Promise.resolve).nthCalledWith(2, [2, 1])
|
||||||
|
expect(Promise.resolve).nthCalledWith(3, [3, 2])
|
||||||
|
expect(Promise.resolve).nthCalledWith(4, [4, 3])
|
||||||
|
|
||||||
|
Promise.all.mockRestore()
|
||||||
|
Promise.resolve.mockRestore()
|
||||||
|
})
|
||||||
|
|
||||||
|
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 = 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 = 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 = 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 = chainFn(firstFn, secondFn)
|
||||||
|
expect(chainedFn({}, 10)).toEqual({ foo: 11, bar: 12 })
|
||||||
|
})
|
||||||
|
|
||||||
|
test('chainFn (return, non-function)', () => {
|
||||||
|
const firstFn = function (obj, count) {
|
||||||
|
return Object.assign({}, obj, { foo: count + 1 })
|
||||||
|
}
|
||||||
|
const secondFn = ''
|
||||||
|
|
||||||
|
const chainedFn = chainFn(firstFn, secondFn)
|
||||||
|
expect(chainedFn).toBe(firstFn)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('chainFn (non-function, return)', () => {
|
||||||
|
const firstFn = ''
|
||||||
|
const secondFn = function (obj, count) {
|
||||||
|
return Object.assign({}, obj, { bar: count + 2 })
|
||||||
|
}
|
||||||
|
|
||||||
|
const chainedFn = chainFn(firstFn, secondFn)
|
||||||
|
expect(chainedFn({}, 10)).toEqual({ bar: 12 })
|
||||||
|
})
|
||||||
|
})
|
165
packages/utils/test/timer.test.js
Normal file
165
packages/utils/test/timer.test.js
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
import { timeout, waitFor, Timer } from '../src/timer'
|
||||||
|
|
||||||
|
describe('util: timer', () => {
|
||||||
|
test('timeout (promise)', async () => {
|
||||||
|
const result = await timeout(Promise.resolve('time not run out'), 100)
|
||||||
|
expect(result).toEqual('time not run out')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('timeout (async function)', async () => {
|
||||||
|
const result = await timeout(async () => {
|
||||||
|
await waitFor(10)
|
||||||
|
return 'time not run out'
|
||||||
|
}, 100)
|
||||||
|
expect(result).toEqual('time not run out')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('timeout (timeout in 100ms)', async () => {
|
||||||
|
const call = timeout(waitFor(200), 100, 'timeout test 100ms')
|
||||||
|
await expect(call).rejects.toThrow('timeout test 100ms')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('timeout (async timeout in 100ms)', async () => {
|
||||||
|
const call = timeout(async () => {
|
||||||
|
await waitFor(500)
|
||||||
|
}, 100, 'timeout test 100ms')
|
||||||
|
await expect(call).rejects.toThrow('timeout test 100ms')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('waitFor', async () => {
|
||||||
|
const delay = 100
|
||||||
|
const s = process.hrtime()
|
||||||
|
await 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 waitFor()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('util: timer Timer', () => {
|
||||||
|
beforeAll(() => {
|
||||||
|
// jest.spyOn()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should construct Timer', () => {
|
||||||
|
const timer = new Timer()
|
||||||
|
expect(timer._times).toBeInstanceOf(Map)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should create new time record', () => {
|
||||||
|
const timer = new Timer()
|
||||||
|
timer.hrtime = jest.fn(() => 'hrtime')
|
||||||
|
|
||||||
|
const time = timer.start('test', 'test Timer')
|
||||||
|
|
||||||
|
expect(timer.hrtime).toBeCalledTimes(1)
|
||||||
|
expect(time).toEqual({ description: 'test Timer', name: 'test', start: 'hrtime' })
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should stop and remove time record', () => {
|
||||||
|
const timer = new Timer()
|
||||||
|
timer.hrtime = jest.fn(() => 'hrtime')
|
||||||
|
timer.start('test', 'test Timer')
|
||||||
|
|
||||||
|
const time = timer.end('test')
|
||||||
|
|
||||||
|
expect(timer._times.size).toEqual(0)
|
||||||
|
expect(timer.hrtime).toBeCalledTimes(2)
|
||||||
|
expect(timer.hrtime).nthCalledWith(2, 'hrtime')
|
||||||
|
expect(time).toEqual({ description: 'test Timer', name: 'test', duration: 'hrtime', start: 'hrtime' })
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should be quiet if end with nonexistent time', () => {
|
||||||
|
const timer = new Timer()
|
||||||
|
|
||||||
|
const time = timer.end('test')
|
||||||
|
|
||||||
|
expect(time).toBeUndefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should use bigint hrtime if supports', () => {
|
||||||
|
const timer = new Timer()
|
||||||
|
const hrtime = process.hrtime
|
||||||
|
process.hrtime = {
|
||||||
|
bigint: jest.fn(() => 'bingint hrtime')
|
||||||
|
}
|
||||||
|
|
||||||
|
const time = timer.hrtime()
|
||||||
|
|
||||||
|
expect(time).toEqual('bingint hrtime')
|
||||||
|
expect(process.hrtime.bigint).toBeCalledTimes(1)
|
||||||
|
|
||||||
|
process.hrtime = hrtime
|
||||||
|
})
|
||||||
|
|
||||||
|
if (BigInt) {
|
||||||
|
test('should calculate duration with bigint hrtime', () => {
|
||||||
|
const timer = new Timer()
|
||||||
|
const hrtime = process.hrtime
|
||||||
|
process.hrtime = {
|
||||||
|
bigint: jest.fn()
|
||||||
|
.mockReturnValueOnce(BigInt(100000000))
|
||||||
|
.mockReturnValueOnce(BigInt(213000000))
|
||||||
|
}
|
||||||
|
|
||||||
|
let time = timer.hrtime()
|
||||||
|
time = timer.hrtime(time)
|
||||||
|
|
||||||
|
expect(time).toEqual(BigInt(113))
|
||||||
|
expect(process.hrtime.bigint).toBeCalledTimes(2)
|
||||||
|
|
||||||
|
process.hrtime = hrtime
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
test('should use hrtime if bigint it not supported', () => {
|
||||||
|
const timer = new Timer()
|
||||||
|
const hrtime = process.hrtime
|
||||||
|
process.hrtime = jest.fn(() => 'hrtime')
|
||||||
|
process.hrtime.bigint = undefined
|
||||||
|
|
||||||
|
const time = timer.hrtime()
|
||||||
|
|
||||||
|
expect(time).toEqual('hrtime')
|
||||||
|
expect(process.hrtime).toBeCalledTimes(1)
|
||||||
|
|
||||||
|
process.hrtime = hrtime
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should calculate duration with hrtime', () => {
|
||||||
|
const timer = new Timer()
|
||||||
|
const hrtime = process.hrtime
|
||||||
|
process.hrtime = jest.fn()
|
||||||
|
.mockReturnValueOnce([1, 500000])
|
||||||
|
.mockReturnValueOnce([2, 600000])
|
||||||
|
process.hrtime.bigint = undefined
|
||||||
|
|
||||||
|
let time = timer.hrtime()
|
||||||
|
time = timer.hrtime(time)
|
||||||
|
|
||||||
|
expect(time).toEqual(2000.6)
|
||||||
|
expect(process.hrtime).toBeCalledTimes(2)
|
||||||
|
expect(process.hrtime).nthCalledWith(1)
|
||||||
|
expect(process.hrtime).nthCalledWith(2, [1, 500000])
|
||||||
|
|
||||||
|
process.hrtime = hrtime
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should clear all times', () => {
|
||||||
|
const timer = new Timer()
|
||||||
|
timer.hrtime = jest.fn(() => 'hrtime')
|
||||||
|
|
||||||
|
timer.start('time-1', 'test time-1')
|
||||||
|
timer.start('time-2', 'test time-2')
|
||||||
|
timer.start('time-3', 'test time-3')
|
||||||
|
|
||||||
|
expect(timer._times.size).toEqual(3)
|
||||||
|
|
||||||
|
timer.clear()
|
||||||
|
|
||||||
|
expect(timer._times.size).toEqual(0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@ -1,332 +1,8 @@
|
|||||||
import path from 'path'
|
|
||||||
import { waitUntil } from '../utils'
|
import { waitUntil } from '../utils'
|
||||||
import * as Utils from '../../packages/utils/src/index'
|
|
||||||
|
|
||||||
describe('utils', () => {
|
describe('utils', () => {
|
||||||
test('encodeHtml', () => {
|
|
||||||
const html = '<h1>Hello</h1>'
|
|
||||||
expect(Utils.encodeHtml(html)).toBe('<h1>Hello</h1>')
|
|
||||||
})
|
|
||||||
|
|
||||||
test('getContext', () => {
|
|
||||||
const 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('waitFor', async () => {
|
|
||||||
const delay = 100
|
|
||||||
const s = process.hrtime()
|
|
||||||
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()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('waitUntil', async () => {
|
test('waitUntil', async () => {
|
||||||
expect(await waitUntil(() => true, 0.1, 100)).toBe(false)
|
expect(await waitUntil(() => true, 0.1, 100)).toBe(false)
|
||||||
expect(await waitUntil(() => false, 0.1, 100)).toBe(true)
|
expect(await waitUntil(() => false, 0.1, 100)).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
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)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
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)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
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('flatRoutes', () => {
|
|
||||||
const routes = Utils.flatRoutes([
|
|
||||||
{ name: 'login', path: '/login' },
|
|
||||||
{ name: 'about', path: '/about' },
|
|
||||||
{ name: 'posts',
|
|
||||||
path: '',
|
|
||||||
children: [
|
|
||||||
{ name: 'posts-list',
|
|
||||||
path: ''
|
|
||||||
},
|
|
||||||
{ name: 'posts-create',
|
|
||||||
path: 'post'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
])
|
|
||||||
expect(routes).toMatchObject([ '/login', '/about', '', '/post' ])
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('relativeTo', () => {
|
|
||||||
const path1 = path.join(path.sep, 'foo', 'bar')
|
|
||||||
const path2 = path.join(path.sep, 'foo', 'baz')
|
|
||||||
|
|
||||||
test('makes path relative to dir', () => {
|
|
||||||
expect(Utils.relativeTo(path1, path2)).toBe(Utils.wp(`..${path.sep}baz`))
|
|
||||||
})
|
|
||||||
|
|
||||||
test('keeps webpack inline loaders prepended', () => {
|
|
||||||
expect(Utils.relativeTo(path1, `loader1!loader2!${path2}`))
|
|
||||||
.toBe(Utils.wp(`loader1!loader2!..${path.sep}baz`))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('guardDir', () => {
|
|
||||||
test('Parent dir is guarded', () => {
|
|
||||||
expect(() => {
|
|
||||||
Utils.guardDir({
|
|
||||||
dir1: '/root/parent',
|
|
||||||
dir2: '/root'
|
|
||||||
}, 'dir1', 'dir2')
|
|
||||||
}).toThrow()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('Same dir is guarded', () => {
|
|
||||||
expect(() => {
|
|
||||||
Utils.guardDir({
|
|
||||||
dir1: '/root/parent',
|
|
||||||
dir2: '/root/parent'
|
|
||||||
}, 'dir1', 'dir2')
|
|
||||||
}).toThrow()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('Same level dir is not guarded', () => {
|
|
||||||
expect(() => {
|
|
||||||
Utils.guardDir({
|
|
||||||
dir1: '/root/parent-next',
|
|
||||||
dir2: '/root/parent'
|
|
||||||
}, 'dir1', 'dir2')
|
|
||||||
}).not.toThrow()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('Same level dir is not guarded 2', () => {
|
|
||||||
expect(() => {
|
|
||||||
Utils.guardDir({
|
|
||||||
dir1: '/root/parent',
|
|
||||||
dir2: '/root/parent-next'
|
|
||||||
}, 'dir1', 'dir2')
|
|
||||||
}).not.toThrow()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('Child dir is not guarded', () => {
|
|
||||||
expect(() => {
|
|
||||||
Utils.guardDir({
|
|
||||||
dir1: '/root/parent',
|
|
||||||
dir2: '/root/parent/child'
|
|
||||||
}, 'dir1', 'dir2')
|
|
||||||
}).not.toThrow()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
test('createRoutes should allow snake case routes', () => {
|
|
||||||
const files = [
|
|
||||||
'pages/_param.vue',
|
|
||||||
'pages/subpage/_param.vue',
|
|
||||||
'pages/snake_case_route.vue',
|
|
||||||
'pages/another_route/_id.vue'
|
|
||||||
]
|
|
||||||
const srcDir = '/some/nuxt/app'
|
|
||||||
const pagesDir = 'pages'
|
|
||||||
const routesResult = Utils.createRoutes(files, srcDir, pagesDir)
|
|
||||||
const expectedResult = [
|
|
||||||
{
|
|
||||||
name: 'snake_case_route',
|
|
||||||
path: '/snake_case_route',
|
|
||||||
component: Utils.r('/some/nuxt/app/pages/snake_case_route.vue'),
|
|
||||||
chunkName: 'pages/snake_case_route'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'another_route-id',
|
|
||||||
path: '/another_route/:id?',
|
|
||||||
component: Utils.r('/some/nuxt/app/pages/another_route/_id.vue'),
|
|
||||||
chunkName: 'pages/another_route/_id'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'subpage-param',
|
|
||||||
path: '/subpage/:param?',
|
|
||||||
component: Utils.r('/some/nuxt/app/pages/subpage/_param.vue'),
|
|
||||||
chunkName: 'pages/subpage/_param'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'param',
|
|
||||||
path: '/:param?',
|
|
||||||
component: Utils.r('/some/nuxt/app/pages/_param.vue'),
|
|
||||||
chunkName: 'pages/_param'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
expect(routesResult).toEqual(expectedResult)
|
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user