mirror of
https://github.com/typicode/json-server.git
synced 2025-07-29 13:14:12 +08:00
Add prettier
This commit is contained in:
1
.eslintignore
Normal file
1
.eslintignore
Normal file
@ -0,0 +1 @@
|
|||||||
|
lib
|
14
.eslintrc.js
Normal file
14
.eslintrc.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: ['standard', 'prettier'],
|
||||||
|
plugins: ['prettier'],
|
||||||
|
rules: {
|
||||||
|
'prettier/prettier': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
singleQuote: true,
|
||||||
|
semi: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
env: { mocha: true },
|
||||||
|
}
|
1032
package-lock.json
generated
1032
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
16
package.json
16
package.json
@ -34,12 +34,21 @@
|
|||||||
"babel-preset-env": "^1.3.2",
|
"babel-preset-env": "^1.3.2",
|
||||||
"babel-register": "^6.16.3",
|
"babel-register": "^6.16.3",
|
||||||
"cross-env": "^2.0.1",
|
"cross-env": "^2.0.1",
|
||||||
|
"eslint": "^3.19.0",
|
||||||
|
"eslint-config-prettier": "^2.3.0",
|
||||||
|
"eslint-config-standard": "^10.2.1",
|
||||||
|
"eslint-plugin-import": "^2.6.1",
|
||||||
|
"eslint-plugin-node": "^5.1.0",
|
||||||
|
"eslint-plugin-prettier": "^2.1.2",
|
||||||
|
"eslint-plugin-promise": "^3.5.0",
|
||||||
|
"eslint-plugin-standard": "^3.0.1",
|
||||||
"husky": "^0.14.1",
|
"husky": "^0.14.1",
|
||||||
"markdown-toc": "^0.13.0",
|
"markdown-toc": "^0.13.0",
|
||||||
"mkdirp": "^0.5.1",
|
"mkdirp": "^0.5.1",
|
||||||
"mocha": "^3.2.0",
|
"mocha": "^3.2.0",
|
||||||
"os-tmpdir": "^1.0.1",
|
"os-tmpdir": "^1.0.1",
|
||||||
"pkg-ok": "^1.0.1",
|
"pkg-ok": "^1.0.1",
|
||||||
|
"prettier": "^1.5.2",
|
||||||
"rimraf": "^2.5.2",
|
"rimraf": "^2.5.2",
|
||||||
"server-ready": "^0.3.1",
|
"server-ready": "^0.3.1",
|
||||||
"standard": "^8.3.0",
|
"standard": "^8.3.0",
|
||||||
@ -47,14 +56,15 @@
|
|||||||
"temp-write": "^2.1.0"
|
"temp-write": "^2.1.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "npm run test:cli && npm run test:server && standard",
|
"test": "npm run test:cli && npm run test:server && eslint .",
|
||||||
"test:cli": "npm run build && cross-env NODE_ENV=test mocha test/cli/*.js",
|
"test:cli": "npm run build && cross-env NODE_ENV=test mocha test/cli/*.js",
|
||||||
"test:server": "cross-env NODE_ENV=test mocha test/server/*.js",
|
"test:server": "cross-env NODE_ENV=test mocha test/server/*.js",
|
||||||
"start": "babel-node src/cli/bin",
|
"start": "babel-node src/cli/bin",
|
||||||
"precommit": "npm test",
|
"format": "eslint . --fix",
|
||||||
"build": "babel src -d lib --copy-files",
|
"build": "babel src -d lib --copy-files",
|
||||||
"toc": "markdown-toc -i README.md",
|
"toc": "markdown-toc -i README.md",
|
||||||
"prepublishOnly": "npm run build && pkg-ok"
|
"prepublishOnly": "npm run build && pkg-ok",
|
||||||
|
"precommit": "npm test"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -83,14 +83,15 @@ module.exports = function () {
|
|||||||
.boolean('quiet')
|
.boolean('quiet')
|
||||||
.boolean('no-cors')
|
.boolean('no-cors')
|
||||||
.boolean('no-gzip')
|
.boolean('no-gzip')
|
||||||
.help('help').alias('help', 'h')
|
.help('help')
|
||||||
.version(pkg.version).alias('version', 'v')
|
.alias('help', 'h')
|
||||||
|
.version(pkg.version)
|
||||||
|
.alias('version', 'v')
|
||||||
.example('$0 db.json', '')
|
.example('$0 db.json', '')
|
||||||
.example('$0 file.js', '')
|
.example('$0 file.js', '')
|
||||||
.example('$0 http://example.com/db.json', '')
|
.example('$0 http://example.com/db.json', '')
|
||||||
.epilog('https://github.com/typicode/json-server')
|
.epilog('https://github.com/typicode/json-server')
|
||||||
.require(1, 'Missing <source> argument')
|
.require(1, 'Missing <source> argument').argv
|
||||||
.argv
|
|
||||||
|
|
||||||
run(argv)
|
run(argv)
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,9 @@ module.exports = function (argv) {
|
|||||||
start(() => {
|
start(() => {
|
||||||
// Snapshot
|
// Snapshot
|
||||||
console.log(
|
console.log(
|
||||||
chalk.gray(' Type s + enter at any time to create a snapshot of the database')
|
chalk.gray(
|
||||||
|
' Type s + enter at any time to create a snapshot of the database'
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Support nohup
|
// Support nohup
|
||||||
@ -168,13 +170,15 @@ module.exports = function (argv) {
|
|||||||
console.log(` Creating a snapshot from the CLI won't be possible`)
|
console.log(` Creating a snapshot from the CLI won't be possible`)
|
||||||
})
|
})
|
||||||
process.stdin.setEncoding('utf8')
|
process.stdin.setEncoding('utf8')
|
||||||
process.stdin.on('data', (chunk) => {
|
process.stdin.on('data', chunk => {
|
||||||
if (chunk.trim().toLowerCase() === 's') {
|
if (chunk.trim().toLowerCase() === 's') {
|
||||||
const filename = 'db-' + Date.now() + '.json'
|
const filename = 'db-' + Date.now() + '.json'
|
||||||
const file = path.join(argv.snapshots, filename)
|
const file = path.join(argv.snapshots, filename)
|
||||||
const state = app.db.getState()
|
const state = app.db.getState()
|
||||||
fs.writeFileSync(file, JSON.stringify(state, null, 2), 'utf-8')
|
fs.writeFileSync(file, JSON.stringify(state, null, 2), 'utf-8')
|
||||||
console.log(` Saved snapshot to ${path.relative(process.cwd(), file)}\n`)
|
console.log(
|
||||||
|
` Saved snapshot to ${path.relative(process.cwd(), file)}\n`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -185,7 +189,7 @@ module.exports = function (argv) {
|
|||||||
const source = argv._[0]
|
const source = argv._[0]
|
||||||
|
|
||||||
// Can't watch URL
|
// Can't watch URL
|
||||||
if (is.URL(source)) throw new Error('Can\'t watch URL')
|
if (is.URL(source)) throw new Error("Can't watch URL")
|
||||||
|
|
||||||
// Watch .js or .json file
|
// Watch .js or .json file
|
||||||
// Since lowdb uses atomic writing, directory is watched instead of file
|
// Since lowdb uses atomic writing, directory is watched instead of file
|
||||||
@ -231,7 +235,9 @@ module.exports = function (argv) {
|
|||||||
if (file) {
|
if (file) {
|
||||||
const watchedFile = path.resolve(watchedDir, file)
|
const watchedFile = path.resolve(watchedDir, file)
|
||||||
if (watchedFile === path.resolve(argv.routes)) {
|
if (watchedFile === path.resolve(argv.routes)) {
|
||||||
console.log(chalk.gray(` ${argv.routes} has changed, reloading...`))
|
console.log(
|
||||||
|
chalk.gray(` ${argv.routes} has changed, reloading...`)
|
||||||
|
)
|
||||||
server && server.destroy()
|
server && server.destroy()
|
||||||
start()
|
start()
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,9 @@ module.exports = function (source, cb) {
|
|||||||
const dataFn = require(filename)
|
const dataFn = require(filename)
|
||||||
|
|
||||||
if (typeof dataFn !== 'function') {
|
if (typeof dataFn !== 'function') {
|
||||||
throw new Error('The database is a JavaScript file but the export is not a function.')
|
throw new Error(
|
||||||
|
'The database is a JavaScript file but the export is not a function.'
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run dataFn to generate data
|
// Run dataFn to generate data
|
||||||
|
@ -10,9 +10,7 @@ const objectAssign = require('object-assign')
|
|||||||
module.exports = function(opts) {
|
module.exports = function(opts) {
|
||||||
const userDir = path.join(process.cwd(), 'public')
|
const userDir = path.join(process.cwd(), 'public')
|
||||||
const defaultDir = path.join(__dirname, 'public')
|
const defaultDir = path.join(__dirname, 'public')
|
||||||
const staticDir = fs.existsSync(userDir)
|
const staticDir = fs.existsSync(userDir) ? userDir : defaultDir
|
||||||
? userDir
|
|
||||||
: defaultDir
|
|
||||||
|
|
||||||
opts = objectAssign({ logger: true, static: staticDir }, opts)
|
opts = objectAssign({ logger: true, static: staticDir }, opts)
|
||||||
|
|
||||||
@ -27,10 +25,8 @@ module.exports = function (opts) {
|
|||||||
if (opts.logger) {
|
if (opts.logger) {
|
||||||
arr.push(
|
arr.push(
|
||||||
logger('dev', {
|
logger('dev', {
|
||||||
skip: (req) => (
|
skip: req =>
|
||||||
process.env.NODE_ENV === 'test' ||
|
process.env.NODE_ENV === 'test' || req.path === '/favicon.ico'
|
||||||
req.path === '/favicon.ico'
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -13,12 +13,14 @@ function getRemovable (db, opts) {
|
|||||||
const _ = this
|
const _ = this
|
||||||
const removable = []
|
const removable = []
|
||||||
_.each(db, (coll, collName) => {
|
_.each(db, (coll, collName) => {
|
||||||
_.each(coll, (doc) => {
|
_.each(coll, doc => {
|
||||||
_.each(doc, (value, key) => {
|
_.each(doc, (value, key) => {
|
||||||
if (new RegExp(`${opts.foreignKeySuffix}$`).test(key)) {
|
if (new RegExp(`${opts.foreignKeySuffix}$`).test(key)) {
|
||||||
// Remove foreign key suffix and pluralize it
|
// Remove foreign key suffix and pluralize it
|
||||||
// Example postId -> posts
|
// Example postId -> posts
|
||||||
const refName = pluralize.plural(key.replace(new RegExp(`${opts.foreignKeySuffix}$`), ''))
|
const refName = pluralize.plural(
|
||||||
|
key.replace(new RegExp(`${opts.foreignKeySuffix}$`), '')
|
||||||
|
)
|
||||||
// Test if table exists
|
// Test if table exists
|
||||||
if (db[refName]) {
|
if (db[refName]) {
|
||||||
// Test if references is defined in table
|
// Test if references is defined in table
|
||||||
@ -46,9 +48,7 @@ function createId (coll) {
|
|||||||
let id = _(coll).maxBy(idProperty)[idProperty]
|
let id = _(coll).maxBy(idProperty)[idProperty]
|
||||||
|
|
||||||
// Increment integer id or generate string id
|
// Increment integer id or generate string id
|
||||||
return _.isFinite(id)
|
return _.isFinite(id) ? ++id : shortid.generate()
|
||||||
? ++id
|
|
||||||
: shortid.generate()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,40 +7,30 @@ m.request('db').then(function (data) {
|
|||||||
db = data
|
db = data
|
||||||
})
|
})
|
||||||
|
|
||||||
m.mount(
|
m.mount(document.getElementById('resources'), {
|
||||||
document.getElementById('resources'),
|
|
||||||
{
|
|
||||||
view: function() {
|
view: function() {
|
||||||
var keys = Object.keys(db)
|
var keys = Object.keys(db)
|
||||||
var resourceList = (
|
var resourceList = m(
|
||||||
m(
|
|
||||||
'ul',
|
'ul',
|
||||||
keys
|
keys
|
||||||
.map(function(key) {
|
.map(function(key) {
|
||||||
return m('li', [
|
return m('li', [
|
||||||
m('a', { href: key }, '/' + key),
|
m('a', { href: key }, '/' + key),
|
||||||
m('sup', Array.isArray(db[key])
|
m(
|
||||||
? ' ' + db[key].length + 'x'
|
'sup',
|
||||||
: ' object'
|
Array.isArray(db[key]) ? ' ' + db[key].length + 'x' : ' object'
|
||||||
)
|
)
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
.concat([
|
.concat([m('a', { href: 'db' }, '/db'), m('sup', m('em', ' state'))])
|
||||||
m('a', { href: 'db' }, '/db'),
|
|
||||||
m('sup', m('em', ' state'))
|
|
||||||
])
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return [
|
return [
|
||||||
m('h4', 'Resources'),
|
m('h4', 'Resources'),
|
||||||
keys.length
|
keys.length ? resourceList : m('p', 'No resources found')
|
||||||
? resourceList
|
|
||||||
: m('p', 'No resources found')
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
)
|
|
||||||
|
|
||||||
// Custom routes
|
// Custom routes
|
||||||
var customRoutes = {}
|
var customRoutes = {}
|
||||||
@ -49,22 +39,19 @@ m.request('__rules').then(function (data) {
|
|||||||
customRoutes = data
|
customRoutes = data
|
||||||
})
|
})
|
||||||
|
|
||||||
m.mount(
|
m.mount(document.getElementById('custom-routes'), {
|
||||||
document.getElementById('custom-routes'),
|
|
||||||
{
|
|
||||||
view: function() {
|
view: function() {
|
||||||
var rules = Object.keys(customRoutes)
|
var rules = Object.keys(customRoutes)
|
||||||
if (rules.length) {
|
if (rules.length) {
|
||||||
return [
|
return [
|
||||||
m('h4', 'Custom routes'),
|
m('h4', 'Custom routes'),
|
||||||
m('table', rules.map(function (rule) {
|
m(
|
||||||
return m('tr', [
|
'table',
|
||||||
m('td', rule),
|
rules.map(function(rule) {
|
||||||
m('td', '⇢ ' + customRoutes[rule])
|
return m('tr', [m('td', rule), m('td', '⇢ ' + customRoutes[rule])])
|
||||||
])
|
})
|
||||||
}))
|
)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
)
|
|
||||||
|
@ -2,16 +2,18 @@ const express = require('express')
|
|||||||
const url = require('url')
|
const url = require('url')
|
||||||
const _ = require('lodash')
|
const _ = require('lodash')
|
||||||
function updateQueryString(target, sourceUrl) {
|
function updateQueryString(target, sourceUrl) {
|
||||||
return ~sourceUrl.indexOf('?') ? _.assign(target, url.parse(sourceUrl, true).query) : {}
|
return ~sourceUrl.indexOf('?')
|
||||||
|
? _.assign(target, url.parse(sourceUrl, true).query)
|
||||||
|
: {}
|
||||||
}
|
}
|
||||||
module.exports = (routes) => {
|
module.exports = routes => {
|
||||||
const router = express.Router()
|
const router = express.Router()
|
||||||
|
|
||||||
router.get('/__rules', (req, res) => {
|
router.get('/__rules', (req, res) => {
|
||||||
res.json(routes)
|
res.json(routes)
|
||||||
})
|
})
|
||||||
|
|
||||||
Object.keys(routes).forEach((route) => {
|
Object.keys(routes).forEach(route => {
|
||||||
if (route.indexOf(':') !== -1) {
|
if (route.indexOf(':') !== -1) {
|
||||||
router.all(route, (req, res, next) => {
|
router.all(route, (req, res, next) => {
|
||||||
// Rewrite target url using params
|
// Rewrite target url using params
|
||||||
|
@ -53,7 +53,8 @@ module.exports = (source, opts = { foreignKeySuffix: 'Id' }) => {
|
|||||||
router.use(nested(opts))
|
router.use(nested(opts))
|
||||||
|
|
||||||
// Create routes
|
// Create routes
|
||||||
db.forEach((value, key) => {
|
db
|
||||||
|
.forEach((value, key) => {
|
||||||
if (_.isPlainObject(value)) {
|
if (_.isPlainObject(value)) {
|
||||||
router.use(`/${key}`, singular(db, key))
|
router.use(`/${key}`, singular(db, key))
|
||||||
return
|
return
|
||||||
@ -66,11 +67,13 @@ module.exports = (source, opts = { foreignKeySuffix: 'Id' }) => {
|
|||||||
|
|
||||||
const msg =
|
const msg =
|
||||||
`Type of "${key}" (${typeof value}) ` +
|
`Type of "${key}" (${typeof value}) ` +
|
||||||
(_.isObject(source) ? '' : `in ${source}`) + ' is not supported. ' +
|
(_.isObject(source) ? '' : `in ${source}`) +
|
||||||
|
' is not supported. ' +
|
||||||
'Use objects or arrays of objects.'
|
'Use objects or arrays of objects.'
|
||||||
|
|
||||||
throw new Error(msg)
|
throw new Error(msg)
|
||||||
}).value()
|
})
|
||||||
|
.value()
|
||||||
|
|
||||||
router.use((req, res) => {
|
router.use((req, res) => {
|
||||||
if (!res.locals.data) {
|
if (!res.locals.data) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const express = require('express')
|
const express = require('express')
|
||||||
const pluralize = require('pluralize')
|
const pluralize = require('pluralize')
|
||||||
|
|
||||||
module.exports = (opts) => {
|
module.exports = opts => {
|
||||||
const router = express.Router()
|
const router = express.Router()
|
||||||
|
|
||||||
// Rewrite URL (/:resource/:id/:nested -> /:nested) and request query
|
// Rewrite URL (/:resource/:id/:nested -> /:nested) and request query
|
||||||
|
@ -11,25 +11,31 @@ module.exports = (db, name, opts) => {
|
|||||||
|
|
||||||
// Embed function used in GET /name and GET /name/id
|
// Embed function used in GET /name and GET /name/id
|
||||||
function embed(resource, e) {
|
function embed(resource, e) {
|
||||||
e && [].concat(e)
|
e &&
|
||||||
.forEach((externalResource) => {
|
[].concat(e).forEach(externalResource => {
|
||||||
if (db.get(externalResource).value) {
|
if (db.get(externalResource).value) {
|
||||||
const query = {}
|
const query = {}
|
||||||
const singularResource = pluralize.singular(name)
|
const singularResource = pluralize.singular(name)
|
||||||
query[`${singularResource}${opts.foreignKeySuffix}`] = resource.id
|
query[`${singularResource}${opts.foreignKeySuffix}`] = resource.id
|
||||||
resource[externalResource] = db.get(externalResource).filter(query).value()
|
resource[externalResource] = db
|
||||||
|
.get(externalResource)
|
||||||
|
.filter(query)
|
||||||
|
.value()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expand function used in GET /name and GET /name/id
|
// Expand function used in GET /name and GET /name/id
|
||||||
function expand(resource, e) {
|
function expand(resource, e) {
|
||||||
e && [].concat(e)
|
e &&
|
||||||
.forEach((innerResource) => {
|
[].concat(e).forEach(innerResource => {
|
||||||
const plural = pluralize(innerResource)
|
const plural = pluralize(innerResource)
|
||||||
if (db.get(plural).value()) {
|
if (db.get(plural).value()) {
|
||||||
const prop = `${innerResource}${opts.foreignKeySuffix}`
|
const prop = `${innerResource}${opts.foreignKeySuffix}`
|
||||||
resource[innerResource] = db.get(plural).getById(resource[prop]).value()
|
resource[innerResource] = db
|
||||||
|
.get(plural)
|
||||||
|
.getById(resource[prop])
|
||||||
|
.value()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -66,7 +72,7 @@ module.exports = (db, name, opts) => {
|
|||||||
|
|
||||||
// Automatically delete query parameters that can't be found
|
// Automatically delete query parameters that can't be found
|
||||||
// in the database
|
// in the database
|
||||||
Object.keys(req.query).forEach((query) => {
|
Object.keys(req.query).forEach(query => {
|
||||||
const arr = db.get(name).value()
|
const arr = db.get(name).value()
|
||||||
for (let i in arr) {
|
for (let i in arr) {
|
||||||
if (
|
if (
|
||||||
@ -77,7 +83,8 @@ module.exports = (db, name, opts) => {
|
|||||||
/_gte$/.test(query) ||
|
/_gte$/.test(query) ||
|
||||||
/_ne$/.test(query) ||
|
/_ne$/.test(query) ||
|
||||||
/_like$/.test(query)
|
/_like$/.test(query)
|
||||||
) return
|
)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
delete req.query[query]
|
delete req.query[query]
|
||||||
})
|
})
|
||||||
@ -90,7 +97,7 @@ module.exports = (db, name, opts) => {
|
|||||||
|
|
||||||
q = q.toLowerCase()
|
q = q.toLowerCase()
|
||||||
|
|
||||||
chain = chain.filter((obj) => {
|
chain = chain.filter(obj => {
|
||||||
for (let key in obj) {
|
for (let key in obj) {
|
||||||
const value = obj[key]
|
const value = obj[key]
|
||||||
if (db._.deepQuery(value, q)) {
|
if (db._.deepQuery(value, q)) {
|
||||||
@ -100,14 +107,14 @@ module.exports = (db, name, opts) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.keys(req.query).forEach((key) => {
|
Object.keys(req.query).forEach(key => {
|
||||||
// Don't take into account JSONP query parameters
|
// Don't take into account JSONP query parameters
|
||||||
// jQuery adds a '_' query parameter too
|
// jQuery adds a '_' query parameter too
|
||||||
if (key !== 'callback' && key !== '_') {
|
if (key !== 'callback' && key !== '_') {
|
||||||
// Always use an array, in case req.query is an array
|
// Always use an array, in case req.query is an array
|
||||||
const arr = [].concat(req.query[key])
|
const arr = [].concat(req.query[key])
|
||||||
|
|
||||||
chain = chain.filter((element) => {
|
chain = chain.filter(element => {
|
||||||
return arr
|
return arr
|
||||||
.map(function(value) {
|
.map(function(value) {
|
||||||
const isDifferent = /_ne$/.test(key)
|
const isDifferent = /_ne$/.test(key)
|
||||||
@ -152,7 +159,10 @@ module.exports = (db, name, opts) => {
|
|||||||
// Slice result
|
// Slice result
|
||||||
if (_end || _limit || _page) {
|
if (_end || _limit || _page) {
|
||||||
res.setHeader('X-Total-Count', chain.size())
|
res.setHeader('X-Total-Count', chain.size())
|
||||||
res.setHeader('Access-Control-Expose-Headers', 'X-Total-Count' + (_page ? ', Link' : ''))
|
res.setHeader(
|
||||||
|
'Access-Control-Expose-Headers',
|
||||||
|
'X-Total-Count' + (_page ? ', Link' : '')
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_page) {
|
if (_page) {
|
||||||
@ -164,19 +174,31 @@ module.exports = (db, name, opts) => {
|
|||||||
const fullURL = getFullURL(req)
|
const fullURL = getFullURL(req)
|
||||||
|
|
||||||
if (page.first) {
|
if (page.first) {
|
||||||
links.first = fullURL.replace('page=' + page.current, 'page=' + page.first)
|
links.first = fullURL.replace(
|
||||||
|
'page=' + page.current,
|
||||||
|
'page=' + page.first
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page.prev) {
|
if (page.prev) {
|
||||||
links.prev = fullURL.replace('page=' + page.current, 'page=' + page.prev)
|
links.prev = fullURL.replace(
|
||||||
|
'page=' + page.current,
|
||||||
|
'page=' + page.prev
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page.next) {
|
if (page.next) {
|
||||||
links.next = fullURL.replace('page=' + page.current, 'page=' + page.next)
|
links.next = fullURL.replace(
|
||||||
|
'page=' + page.current,
|
||||||
|
'page=' + page.next
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page.last) {
|
if (page.last) {
|
||||||
links.last = fullURL.replace('page=' + page.current, 'page=' + page.last)
|
links.last = fullURL.replace(
|
||||||
|
'page=' + page.current,
|
||||||
|
'page=' + page.last
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
res.links(links)
|
res.links(links)
|
||||||
@ -192,9 +214,7 @@ module.exports = (db, name, opts) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// embed and expand
|
// embed and expand
|
||||||
chain = chain
|
chain = chain.cloneDeep().forEach(function(element) {
|
||||||
.cloneDeep()
|
|
||||||
.forEach(function (element) {
|
|
||||||
embed(element, _embed)
|
embed(element, _embed)
|
||||||
expand(element, _expand)
|
expand(element, _expand)
|
||||||
})
|
})
|
||||||
@ -208,9 +228,7 @@ module.exports = (db, name, opts) => {
|
|||||||
function show(req, res, next) {
|
function show(req, res, next) {
|
||||||
const _embed = req.query._embed
|
const _embed = req.query._embed
|
||||||
const _expand = req.query._expand
|
const _expand = req.query._expand
|
||||||
const resource = db.get(name)
|
const resource = db.get(name).getById(req.params.id).value()
|
||||||
.getById(req.params.id)
|
|
||||||
.value()
|
|
||||||
|
|
||||||
if (resource) {
|
if (resource) {
|
||||||
// Clone resource to avoid making changes to the underlying object
|
// Clone resource to avoid making changes to the underlying object
|
||||||
@ -232,10 +250,7 @@ module.exports = (db, name, opts) => {
|
|||||||
|
|
||||||
// POST /name
|
// POST /name
|
||||||
function create(req, res, next) {
|
function create(req, res, next) {
|
||||||
const resource = db
|
const resource = db.get(name).insert(req.body).value()
|
||||||
.get(name)
|
|
||||||
.insert(req.body)
|
|
||||||
.value()
|
|
||||||
|
|
||||||
res.setHeader('Access-Control-Expose-Headers', 'Location')
|
res.setHeader('Access-Control-Expose-Headers', 'Location')
|
||||||
res.location(`${getFullURL(req)}/${resource.id}`)
|
res.location(`${getFullURL(req)}/${resource.id}`)
|
||||||
@ -252,7 +267,8 @@ module.exports = (db, name, opts) => {
|
|||||||
const id = req.params.id
|
const id = req.params.id
|
||||||
let chain = db.get(name)
|
let chain = db.get(name)
|
||||||
|
|
||||||
chain = req.method === 'PATCH'
|
chain =
|
||||||
|
req.method === 'PATCH'
|
||||||
? chain.updateById(id, req.body)
|
? chain.updateById(id, req.body)
|
||||||
: chain.replaceById(id, req.body)
|
: chain.replaceById(id, req.body)
|
||||||
|
|
||||||
@ -267,18 +283,14 @@ module.exports = (db, name, opts) => {
|
|||||||
|
|
||||||
// DELETE /name/:id
|
// DELETE /name/:id
|
||||||
function destroy(req, res, next) {
|
function destroy(req, res, next) {
|
||||||
const resource = db.get(name)
|
const resource = db.get(name).removeById(req.params.id).value()
|
||||||
.removeById(req.params.id)
|
|
||||||
.value()
|
|
||||||
|
|
||||||
// Remove dependents documents
|
// Remove dependents documents
|
||||||
console.log({ opts })
|
console.log({ opts })
|
||||||
const removable = db._.getRemovable(db.getState(), opts)
|
const removable = db._.getRemovable(db.getState(), opts)
|
||||||
console.log(removable)
|
console.log(removable)
|
||||||
removable.forEach((item) => {
|
removable.forEach(item => {
|
||||||
db.get(item.name)
|
db.get(item.name).removeById(item.id).value()
|
||||||
.removeById(item.id)
|
|
||||||
.value()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if (resource) {
|
if (resource) {
|
||||||
@ -290,11 +302,10 @@ module.exports = (db, name, opts) => {
|
|||||||
|
|
||||||
const w = write(db)
|
const w = write(db)
|
||||||
|
|
||||||
router.route('/')
|
router.route('/').get(list).post(create, w)
|
||||||
.get(list)
|
|
||||||
.post(create, w)
|
|
||||||
|
|
||||||
router.route('/:id')
|
router
|
||||||
|
.route('/:id')
|
||||||
.get(show)
|
.get(show)
|
||||||
.put(update, w)
|
.put(update, w)
|
||||||
.patch(update, w)
|
.patch(update, w)
|
||||||
|
@ -23,12 +23,9 @@ module.exports = (db, name) => {
|
|||||||
|
|
||||||
function update(req, res, next) {
|
function update(req, res, next) {
|
||||||
if (req.method === 'PUT') {
|
if (req.method === 'PUT') {
|
||||||
db.set(name, req.body)
|
db.set(name, req.body).value()
|
||||||
.value()
|
|
||||||
} else {
|
} else {
|
||||||
db.get(name)
|
db.get(name).assign(req.body).value()
|
||||||
.assign(req.body)
|
|
||||||
.value()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res.locals.data = db.get(name).value()
|
res.locals.data = db.get(name).value()
|
||||||
@ -37,11 +34,7 @@ module.exports = (db, name) => {
|
|||||||
|
|
||||||
const w = write(db)
|
const w = write(db)
|
||||||
|
|
||||||
router.route('/')
|
router.route('/').get(show).post(create, w).put(update, w).patch(update, w)
|
||||||
.get(show)
|
|
||||||
.post(create, w)
|
|
||||||
.put(update, w)
|
|
||||||
.patch(update, w)
|
|
||||||
|
|
||||||
return router
|
return router
|
||||||
}
|
}
|
||||||
|
@ -5,18 +5,16 @@ function validateKey (key) {
|
|||||||
const msg = [
|
const msg = [
|
||||||
`Oops, found / character in database property '${key}'.`,
|
`Oops, found / character in database property '${key}'.`,
|
||||||
'',
|
'',
|
||||||
'/ aren\'t supported, if you want to tweak default routes, see',
|
"/ aren't supported, if you want to tweak default routes, see",
|
||||||
'https://github.com/typicode/json-server/#add-custom-routes'
|
'https://github.com/typicode/json-server/#add-custom-routes'
|
||||||
].join('\n')
|
].join('\n')
|
||||||
throw new Error(msg)
|
throw new Error(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = (obj) => {
|
module.exports = obj => {
|
||||||
if (_.isPlainObject(obj)) {
|
if (_.isPlainObject(obj)) {
|
||||||
Object
|
Object.keys(obj).forEach(validateKey)
|
||||||
.keys(obj)
|
|
||||||
.forEach(validateKey)
|
|
||||||
} else {
|
} else {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Data must be an object. Found ${typeof obj}.` +
|
`Data must be an object. Found ${typeof obj}.` +
|
||||||
|
@ -1,29 +1,37 @@
|
|||||||
// Need some fake data for the gzip test to work
|
// Need some fake data for the gzip test to work
|
||||||
module.exports = function() {
|
module.exports = function() {
|
||||||
return { posts: [
|
return {
|
||||||
|
posts: [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
content: "Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!"
|
content:
|
||||||
|
"Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
content: "Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!"
|
content:
|
||||||
|
"Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
content: "Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!"
|
content:
|
||||||
|
"Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 4,
|
id: 4,
|
||||||
content: "Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!"
|
content:
|
||||||
|
"Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 5,
|
id: 5,
|
||||||
content: "Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!"
|
content:
|
||||||
|
"Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 6,
|
id: 6,
|
||||||
content: "Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!"
|
content:
|
||||||
|
"Oh! The garbage chute was a really wonderful idea. What an incredible smell you've discovered! Let's get out of here! Get away from there... No! wait! Will you forget it? I already tried it. It's magnetically sealed! Put that thing away! You're going to get us all killed. Absolutely, Your Worship. Look, I had everything under control until you led us down here. You know, it's not going to take them long to figure out what happened to us. It could be worst... It's worst. There's something alive in here! That's your imagination. Something just moves past my leg! Look! Did you see that? What? Help!"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]}
|
|
||||||
}
|
}
|
||||||
|
@ -35,13 +35,8 @@ describe('cli', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
dbFile = tempWrite.sync(
|
dbFile = tempWrite.sync(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
posts: [
|
posts: [{ id: 1 }, { _id: 2 }],
|
||||||
{ id: 1 },
|
comments: [{ id: 1, post_id: 1 }]
|
||||||
{ _id: 2 }
|
|
||||||
],
|
|
||||||
comments: [
|
|
||||||
{ id: 1, post_id: 1 }
|
|
||||||
]
|
|
||||||
}),
|
}),
|
||||||
'db.json'
|
'db.json'
|
||||||
)
|
)
|
||||||
@ -60,28 +55,27 @@ describe('cli', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('db.json', () => {
|
describe('db.json', () => {
|
||||||
beforeEach((done) => {
|
beforeEach(done => {
|
||||||
child = cli([dbFile])
|
child = cli([dbFile])
|
||||||
serverReady(PORT, done)
|
serverReady(PORT, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should support JSON file', (done) => {
|
it('should support JSON file', done => {
|
||||||
request.get('/posts').expect(200, done)
|
request.get('/posts').expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should send CORS headers', (done) => {
|
it('should send CORS headers', done => {
|
||||||
const origin = 'http://example.com'
|
const origin = 'http://example.com'
|
||||||
|
|
||||||
request.get('/posts')
|
request
|
||||||
|
.get('/posts')
|
||||||
.set('Origin', origin)
|
.set('Origin', origin)
|
||||||
.expect('access-control-allow-origin', origin)
|
.expect('access-control-allow-origin', origin)
|
||||||
.expect(200, done)
|
.expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should update JSON file', (done) => {
|
it('should update JSON file', done => {
|
||||||
request.post('/posts')
|
request.post('/posts').send({ title: 'hello' }).end(() => {
|
||||||
.send({ title: 'hello' })
|
|
||||||
.end(() => {
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const str = fs.readFileSync(dbFile, 'utf8')
|
const str = fs.readFileSync(dbFile, 'utf8')
|
||||||
assert(str.indexOf('hello') !== -1)
|
assert(str.indexOf('hello') !== -1)
|
||||||
@ -92,18 +86,18 @@ describe('cli', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('seed.js', () => {
|
describe('seed.js', () => {
|
||||||
beforeEach((done) => {
|
beforeEach(done => {
|
||||||
child = cli(['fixtures/seed.js'])
|
child = cli(['fixtures/seed.js'])
|
||||||
serverReady(PORT, done)
|
serverReady(PORT, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should support JS file', (done) => {
|
it('should support JS file', done => {
|
||||||
request.get('/posts').expect(200, done)
|
request.get('/posts').expect(200, done)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('http://localhost:8080/db', () => {
|
describe('http://localhost:8080/db', () => {
|
||||||
beforeEach((done) => {
|
beforeEach(done => {
|
||||||
const fakeServer = express()
|
const fakeServer = express()
|
||||||
fakeServer.get('/db', (req, res) => {
|
fakeServer.get('/db', (req, res) => {
|
||||||
res.jsonp({ posts: [] })
|
res.jsonp({ posts: [] })
|
||||||
@ -114,18 +108,29 @@ describe('cli', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should support URL file', (done) => {
|
it('should support URL file', done => {
|
||||||
request.get('/posts').expect(200, done)
|
request.get('/posts').expect(200, done)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('db.json -r routes.json -m middleware.js -i _id --foreignKeySuffix _id --read-only', () => {
|
describe('db.json -r routes.json -m middleware.js -i _id --foreignKeySuffix _id --read-only', () => {
|
||||||
beforeEach((done) => {
|
beforeEach(done => {
|
||||||
child = cli([ dbFile, '-r', routesFile, '-m', middlewareFiles.en, '-i', '_id', '--read-only', '--foreignKeySuffix', '_id' ])
|
child = cli([
|
||||||
|
dbFile,
|
||||||
|
'-r',
|
||||||
|
routesFile,
|
||||||
|
'-m',
|
||||||
|
middlewareFiles.en,
|
||||||
|
'-i',
|
||||||
|
'_id',
|
||||||
|
'--read-only',
|
||||||
|
'--foreignKeySuffix',
|
||||||
|
'_id'
|
||||||
|
])
|
||||||
serverReady(PORT, done)
|
serverReady(PORT, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should use routes.json and _id as the identifier', (done) => {
|
it('should use routes.json and _id as the identifier', done => {
|
||||||
request.get('/blog/posts/2').expect(200, done)
|
request.get('/blog/posts/2').expect(200, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -134,43 +139,40 @@ describe('cli', () => {
|
|||||||
assert.equal(response.body.length, 1)
|
assert.equal(response.body.length, 1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should apply middlewares', (done) => {
|
it('should apply middlewares', done => {
|
||||||
request.get('/blog/posts/2').expect('X-Hello', 'World', done)
|
request.get('/blog/posts/2').expect('X-Hello', 'World', done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should allow only GET requests', (done) => {
|
it('should allow only GET requests', done => {
|
||||||
request.post('/blog/posts').expect(403, done)
|
request.post('/blog/posts').expect(403, done)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('db.json -m first-middleware.js second-middleware.js', () => {
|
describe('db.json -m first-middleware.js second-middleware.js', () => {
|
||||||
beforeEach((done) => {
|
beforeEach(done => {
|
||||||
child = cli([dbFile, '-m', middlewareFiles.en, middlewareFiles.jp])
|
child = cli([dbFile, '-m', middlewareFiles.en, middlewareFiles.jp])
|
||||||
serverReady(PORT, done)
|
serverReady(PORT, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should apply all middlewares', (done) => {
|
it('should apply all middlewares', done => {
|
||||||
request.get('/posts')
|
request
|
||||||
|
.get('/posts')
|
||||||
.expect('X-Hello', 'World')
|
.expect('X-Hello', 'World')
|
||||||
.expect('X-Konnichiwa', 'Sekai', done)
|
.expect('X-Konnichiwa', 'Sekai', done)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('db.json -d 1000', () => {
|
describe('db.json -d 1000', () => {
|
||||||
beforeEach((done) => {
|
beforeEach(done => {
|
||||||
child = cli([dbFile, '-d', 1000])
|
child = cli([dbFile, '-d', 1000])
|
||||||
serverReady(PORT, done)
|
serverReady(PORT, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should delay response', (done) => {
|
it('should delay response', done => {
|
||||||
const start = new Date()
|
const start = new Date()
|
||||||
request.get('/posts').expect(200, function(err) {
|
request.get('/posts').expect(200, function(err) {
|
||||||
const end = new Date()
|
const end = new Date()
|
||||||
done(
|
done(end - start > 1000 ? err : new Error("Request wasn't delayed"))
|
||||||
end - start > 1000
|
|
||||||
? err
|
|
||||||
: new Error('Request wasn\'t delayed')
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -179,7 +181,7 @@ describe('cli', () => {
|
|||||||
const snapshotsDir = path.join(osTmpdir(), 'snapshots')
|
const snapshotsDir = path.join(osTmpdir(), 'snapshots')
|
||||||
const publicDir = 'fixtures/public'
|
const publicDir = 'fixtures/public'
|
||||||
|
|
||||||
beforeEach((done) => {
|
beforeEach(done => {
|
||||||
rimraf.sync(snapshotsDir)
|
rimraf.sync(snapshotsDir)
|
||||||
mkdirp.sync(snapshotsDir)
|
mkdirp.sync(snapshotsDir)
|
||||||
|
|
||||||
@ -190,7 +192,7 @@ describe('cli', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should serve fixtures/public', (done) => {
|
it('should serve fixtures/public', done => {
|
||||||
request.get('/').expect(/Hello/, done)
|
request.get('/').expect(/Hello/, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -200,21 +202,23 @@ describe('cli', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('fixtures/seed.json --no-cors=true', () => {
|
describe('fixtures/seed.json --no-cors=true', () => {
|
||||||
beforeEach((done) => {
|
beforeEach(done => {
|
||||||
child = cli(['fixtures/seed.js', '--no-cors=true'])
|
child = cli(['fixtures/seed.js', '--no-cors=true'])
|
||||||
serverReady(PORT, done)
|
serverReady(PORT, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not send Access-Control-Allow-Origin headers', (done) => {
|
it('should not send Access-Control-Allow-Origin headers', done => {
|
||||||
const origin = 'http://example.com'
|
const origin = 'http://example.com'
|
||||||
|
|
||||||
request.get('/posts')
|
request
|
||||||
|
.get('/posts')
|
||||||
.set('Origin', origin)
|
.set('Origin', origin)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end((err, res) => {
|
.end((err, res) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
done(err)
|
done(err)
|
||||||
} if ('access-control-allow-origin' in res.headers) {
|
}
|
||||||
|
if ('access-control-allow-origin' in res.headers) {
|
||||||
done(new Error('CORS headers were not excluded from response'))
|
done(new Error('CORS headers were not excluded from response'))
|
||||||
} else {
|
} else {
|
||||||
done()
|
done()
|
||||||
@ -224,15 +228,13 @@ describe('cli', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('fixtures/seed.json --no-gzip=true', () => {
|
describe('fixtures/seed.json --no-gzip=true', () => {
|
||||||
beforeEach((done) => {
|
beforeEach(done => {
|
||||||
child = cli(['fixtures/seed.js', '--no-gzip=true'])
|
child = cli(['fixtures/seed.js', '--no-gzip=true'])
|
||||||
serverReady(PORT, done)
|
serverReady(PORT, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not set Content-Encoding to gzip', (done) => {
|
it('should not set Content-Encoding to gzip', done => {
|
||||||
request.get('/posts')
|
request.get('/posts').expect(200).end(function(err, res) {
|
||||||
.expect(200)
|
|
||||||
.end(function (err, res) {
|
|
||||||
if (err) {
|
if (err) {
|
||||||
done(err)
|
done(err)
|
||||||
} else if ('content-encoding' in res.headers) {
|
} else if ('content-encoding' in res.headers) {
|
||||||
@ -245,19 +247,19 @@ describe('cli', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('--watch db.json -r routes.json', () => {
|
describe('--watch db.json -r routes.json', () => {
|
||||||
beforeEach((done) => {
|
beforeEach(done => {
|
||||||
child = cli([dbFile, '-r', routesFile, '--watch'])
|
child = cli([dbFile, '-r', routesFile, '--watch'])
|
||||||
serverReady(PORT, done)
|
serverReady(PORT, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should watch db file', (done) => {
|
it('should watch db file', done => {
|
||||||
fs.writeFileSync(dbFile, JSON.stringify({ foo: [] }))
|
fs.writeFileSync(dbFile, JSON.stringify({ foo: [] }))
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
request.get('/foo').expect(200, done)
|
request.get('/foo').expect(200, done)
|
||||||
}, 1000)
|
}, 1000)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should watch routes file', (done) => {
|
it('should watch routes file', done => {
|
||||||
fs.writeFileSync(routesFile, JSON.stringify({ '/api/': '/' }))
|
fs.writeFileSync(routesFile, JSON.stringify({ '/api/': '/' }))
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
request.get('/api/posts').expect(200, done)
|
request.get('/api/posts').expect(200, done)
|
||||||
@ -266,28 +268,25 @@ describe('cli', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('non existent db.json', () => {
|
describe('non existent db.json', () => {
|
||||||
beforeEach((done) => {
|
beforeEach(done => {
|
||||||
fs.unlinkSync(dbFile)
|
fs.unlinkSync(dbFile)
|
||||||
child = cli([dbFile])
|
child = cli([dbFile])
|
||||||
serverReady(PORT, done)
|
serverReady(PORT, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should create JSON file if it doesn\'t exist', (done) => {
|
it("should create JSON file if it doesn't exist", done => {
|
||||||
request.get('/posts').expect(200, done)
|
request.get('/posts').expect(200, done)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('db.json with error', () => {
|
describe('db.json with error', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
dbFile = tempWrite.sync(
|
dbFile = tempWrite.sync(JSON.stringify({ 'a/b': [] }), 'db-error.json')
|
||||||
JSON.stringify({ 'a/b': [] }),
|
|
||||||
'db-error.json'
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should exit with an error', (done) => {
|
it('should exit with an error', done => {
|
||||||
child = cli([dbFile])
|
child = cli([dbFile])
|
||||||
child.on('exit', (code) => {
|
child.on('exit', code => {
|
||||||
if (code === 1) {
|
if (code === 1) {
|
||||||
return done()
|
return done()
|
||||||
}
|
}
|
||||||
|
@ -13,19 +13,14 @@ describe('mixins', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
db = {
|
db = {
|
||||||
posts: [
|
posts: [{ id: 1, comment: 1 }],
|
||||||
{ id: 1, comment: 1 }
|
|
||||||
],
|
|
||||||
comments: [
|
comments: [
|
||||||
{ id: 1, postId: 1 },
|
{ id: 1, postId: 1 },
|
||||||
// Comments below references a post that doesn't exist
|
// Comments below references a post that doesn't exist
|
||||||
{ id: 2, postId: 2 },
|
{ id: 2, postId: 2 },
|
||||||
{ id: 3, postId: 2 }
|
{ id: 3, postId: 2 }
|
||||||
],
|
],
|
||||||
photos: [
|
photos: [{ id: '1' }, { id: '2' }]
|
||||||
{ id: '1' },
|
|
||||||
{ id: '2' }
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -11,10 +11,7 @@ describe('Server with custom foreign key', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
db = {}
|
db = {}
|
||||||
|
|
||||||
db.posts = [
|
db.posts = [{ id: 1, body: 'foo' }, { id: 2, body: 'bar' }]
|
||||||
{ id: 1, body: 'foo' },
|
|
||||||
{ id: 2, body: 'bar' }
|
|
||||||
]
|
|
||||||
|
|
||||||
db.comments = [
|
db.comments = [
|
||||||
{ id: 1, post_id: 1 },
|
{ id: 1, post_id: 1 },
|
||||||
@ -29,26 +26,21 @@ describe('Server with custom foreign key', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:parent/:parentId/:resource', () => {
|
describe('GET /:parent/:parentId/:resource', () => {
|
||||||
it('should respond with json and corresponding nested resources', () => (
|
it('should respond with json and corresponding nested resources', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/posts/1/comments')
|
.get('/posts/1/comments')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([
|
.expect([db.comments[0], db.comments[1]])
|
||||||
db.comments[0],
|
.expect(200))
|
||||||
db.comments[1]
|
|
||||||
])
|
|
||||||
.expect(200)
|
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource/:id', () => {
|
describe('GET /:resource/:id', () => {
|
||||||
it('should respond with json and corresponding resource', () => (
|
it('should respond with json and corresponding resource', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/posts/1')
|
.get('/posts/1')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(db.posts[0])
|
.expect(db.posts[0])
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?_embed=', () => {
|
describe('GET /:resource?_embed=', () => {
|
||||||
@ -103,22 +95,18 @@ describe('Server with custom foreign key', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('POST /:parent/:parentId/:resource', () => {
|
describe('POST /:parent/:parentId/:resource', () => {
|
||||||
it('should respond with json and set parentId', () => (
|
it('should respond with json and set parentId', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.post('/posts/1/comments')
|
.post('/posts/1/comments')
|
||||||
.send({ body: 'foo' })
|
.send({ body: 'foo' })
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect({ id: 4, post_id: 1, body: 'foo' })
|
.expect({ id: 4, post_id: 1, body: 'foo' })
|
||||||
.expect(201)
|
.expect(201))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('DELETE /:resource/:id', () => {
|
describe('DELETE /:resource/:id', () => {
|
||||||
it('should respond with empty data, destroy resource and dependent resources', async () => {
|
it('should respond with empty data, destroy resource and dependent resources', async () => {
|
||||||
await request(server)
|
await request(server).del('/posts/1').expect({}).expect(200)
|
||||||
.del('/posts/1')
|
|
||||||
.expect({})
|
|
||||||
.expect(200)
|
|
||||||
assert.equal(db.posts.length, 1)
|
assert.equal(db.posts.length, 1)
|
||||||
assert.equal(db.comments.length, 1)
|
assert.equal(db.comments.length, 1)
|
||||||
})
|
})
|
||||||
|
@ -18,10 +18,7 @@ describe('Server', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
db = {}
|
db = {}
|
||||||
|
|
||||||
db.posts = [
|
db.posts = [{ id: 1, body: 'foo' }, { id: 2, body: 'bar' }]
|
||||||
{ id: 1, body: 'foo' },
|
|
||||||
{ id: 2, body: 'bar' }
|
|
||||||
]
|
|
||||||
|
|
||||||
db.tags = [
|
db.tags = [
|
||||||
{ id: 1, body: 'Technology' },
|
{ id: 1, body: 'Technology' },
|
||||||
@ -58,14 +55,9 @@ describe('Server', () => {
|
|||||||
{ id: 'abcd-1234', url: 'http://example.com', postId: 1, userId: 1 }
|
{ id: 'abcd-1234', url: 'http://example.com', postId: 1, userId: 1 }
|
||||||
]
|
]
|
||||||
|
|
||||||
db.stringIds = [
|
db.stringIds = [{ id: '1234' }]
|
||||||
{ id: '1234' }
|
|
||||||
]
|
|
||||||
|
|
||||||
db.deep = [
|
db.deep = [{ a: { b: 1 } }, { a: 1 }]
|
||||||
{ a: { b: 1 } },
|
|
||||||
{ a: 1 }
|
|
||||||
]
|
|
||||||
|
|
||||||
db.nested = [
|
db.nested = [
|
||||||
{ resource: { name: 'dewey' } },
|
{ resource: { name: 'dewey' } },
|
||||||
@ -99,17 +91,16 @@ describe('Server', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /db', () => {
|
describe('GET /db', () => {
|
||||||
it('should respond with json and full database', () => (
|
it('should respond with json and full database', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/db')
|
.get('/db')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(db)
|
.expect(db)
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource', () => {
|
describe('GET /:resource', () => {
|
||||||
it('should respond with json and corresponding resources', () => (
|
it('should respond with json and corresponding resources', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/posts')
|
.get('/posts')
|
||||||
.set('Origin', 'http://example.com')
|
.set('Origin', 'http://example.com')
|
||||||
@ -117,64 +108,54 @@ describe('Server', () => {
|
|||||||
.expect('Access-Control-Allow-Credentials', 'true')
|
.expect('Access-Control-Allow-Credentials', 'true')
|
||||||
.expect('Access-Control-Allow-Origin', 'http://example.com')
|
.expect('Access-Control-Allow-Origin', 'http://example.com')
|
||||||
.expect(db.posts)
|
.expect(db.posts)
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
|
|
||||||
it('should respond with 404 if resource is not found', () => (
|
it('should respond with 404 if resource is not found', () =>
|
||||||
request(server)
|
request(server).get('/undefined').expect(404))
|
||||||
.get('/undefined')
|
|
||||||
.expect(404)
|
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?attr=&attr=', () => {
|
describe('GET /:resource?attr=&attr=', () => {
|
||||||
it('should respond with json and filter resources', () => (
|
it('should respond with json and filter resources', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?postId=1&published=true')
|
.get('/comments?postId=1&published=true')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([db.comments[0]])
|
.expect([db.comments[0]])
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
|
|
||||||
it('should be strict', () => (
|
it('should be strict', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/users?tel=123')
|
.get('/users?tel=123')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([db.users[1]])
|
.expect([db.users[1]])
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
|
|
||||||
it('should support multiple filters', () => (
|
it('should support multiple filters', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?id=1&id=2')
|
.get('/comments?id=1&id=2')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([db.comments[0], db.comments[1]])
|
.expect([db.comments[0], db.comments[1]])
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
|
|
||||||
it('should support deep filter', () => (
|
it('should support deep filter', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/deep?a.b=1')
|
.get('/deep?a.b=1')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([db.deep[0]])
|
.expect([db.deep[0]])
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
|
|
||||||
it('should ignore JSONP query parameters callback and _ ', () => (
|
it('should ignore JSONP query parameters callback and _ ', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?callback=1&_=1')
|
.get('/comments?callback=1&_=1')
|
||||||
.expect('Content-Type', /text/)
|
.expect('Content-Type', /text/)
|
||||||
.expect(new RegExp(db.comments[0].body)) // JSONP returns text
|
.expect(new RegExp(db.comments[0].body)) // JSONP returns text
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
|
|
||||||
it('should ignore unknown query parameters', () => (
|
it('should ignore unknown query parameters', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?foo=1&bar=2')
|
.get('/comments?foo=1&bar=2')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(db.comments)
|
.expect(db.comments)
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
|
|
||||||
// https://github.com/typicode/json-server/issues/510
|
// https://github.com/typicode/json-server/issues/510
|
||||||
it('should not fail with null value', () => {
|
it('should not fail with null value', () => {
|
||||||
@ -188,147 +169,138 @@ describe('Server', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?q=', () => {
|
describe('GET /:resource?q=', () => {
|
||||||
it('should respond with json and make a full-text search', () => (
|
it('should respond with json and make a full-text search', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/tags?q=pho')
|
.get('/tags?q=pho')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([db.tags[1], db.tags[2]])
|
.expect([db.tags[1], db.tags[2]])
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
|
|
||||||
it('should respond with json and make a deep full-text search', () => (
|
it('should respond with json and make a deep full-text search', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/deep?q=1')
|
.get('/deep?q=1')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(db.deep)
|
.expect(db.deep)
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
|
|
||||||
it('should return an empty array when nothing is matched', () => (
|
it('should return an empty array when nothing is matched', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/tags?q=nope')
|
.get('/tags?q=nope')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([])
|
.expect([])
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
|
|
||||||
it('should support other query parameters', () => (
|
it('should support other query parameters', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?q=qu&published=true')
|
.get('/comments?q=qu&published=true')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([db.comments[3]])
|
.expect([db.comments[3]])
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
|
|
||||||
it('should ignore duplicate q query parameters', () => (
|
it('should ignore duplicate q query parameters', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?q=foo&q=bar')
|
.get('/comments?q=foo&q=bar')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([db.comments[0]])
|
.expect([db.comments[0]])
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
|
|
||||||
it('should support filtering by boolean value false', () => (
|
it('should support filtering by boolean value false', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?published=false')
|
.get('/comments?published=false')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([db.comments[1], db.comments[2], db.comments[4]])
|
.expect([db.comments[1], db.comments[2], db.comments[4]])
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?_end=', () => {
|
describe('GET /:resource?_end=', () => {
|
||||||
it('should respond with a sliced array', () => (
|
it('should respond with a sliced array', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?_end=2')
|
.get('/comments?_end=2')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect('x-total-count', db.comments.length.toString())
|
.expect('x-total-count', db.comments.length.toString())
|
||||||
.expect('Access-Control-Expose-Headers', 'X-Total-Count')
|
.expect('Access-Control-Expose-Headers', 'X-Total-Count')
|
||||||
.expect(db.comments.slice(0, 2))
|
.expect(db.comments.slice(0, 2))
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?_sort=', () => {
|
describe('GET /:resource?_sort=', () => {
|
||||||
it('should respond with json and sort on a field', () => (
|
it('should respond with json and sort on a field', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/tags?_sort=body')
|
.get('/tags?_sort=body')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([db.tags[1], db.tags[0], db.tags[2]])
|
.expect([db.tags[1], db.tags[0], db.tags[2]])
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
|
|
||||||
it('should reverse sorting with _order=DESC', () => (
|
it('should reverse sorting with _order=DESC', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/tags?_sort=body&_order=DESC')
|
.get('/tags?_sort=body&_order=DESC')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([db.tags[2], db.tags[0], db.tags[1]])
|
.expect([db.tags[2], db.tags[0], db.tags[1]])
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
|
|
||||||
it('should sort on numerical field', () => (
|
it('should sort on numerical field', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/posts?_sort=id&_order=DESC')
|
.get('/posts?_sort=id&_order=DESC')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(db.posts.reverse())
|
.expect(db.posts.reverse())
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
|
|
||||||
it('should sort on nested field', () => (
|
it('should sort on nested field', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/nested?_sort=resource.name')
|
.get('/nested?_sort=resource.name')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([db.nested[1], db.nested[0], db.nested[2]])
|
.expect([db.nested[1], db.nested[0], db.nested[2]])
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
|
|
||||||
it('should sort on multiple fields', () => (
|
it('should sort on multiple fields', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/buyers?_sort=country,total&_order=asc,desc')
|
.get('/buyers?_sort=country,total&_order=asc,desc')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([
|
.expect([
|
||||||
db.buyers[8], db.buyers[7], db.buyers[6],
|
db.buyers[8],
|
||||||
db.buyers[3], db.buyers[4], db.buyers[5],
|
db.buyers[7],
|
||||||
db.buyers[2], db.buyers[1], db.buyers[0]
|
db.buyers[6],
|
||||||
|
db.buyers[3],
|
||||||
|
db.buyers[4],
|
||||||
|
db.buyers[5],
|
||||||
|
db.buyers[2],
|
||||||
|
db.buyers[1],
|
||||||
|
db.buyers[0]
|
||||||
])
|
])
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?_start=&_end=', () => {
|
describe('GET /:resource?_start=&_end=', () => {
|
||||||
it('should respond with a sliced array', () => (
|
it('should respond with a sliced array', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?_start=1&_end=2')
|
.get('/comments?_start=1&_end=2')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect('X-Total-Count', db.comments.length.toString())
|
.expect('X-Total-Count', db.comments.length.toString())
|
||||||
.expect('Access-Control-Expose-Headers', 'X-Total-Count')
|
.expect('Access-Control-Expose-Headers', 'X-Total-Count')
|
||||||
.expect(db.comments.slice(1, 2))
|
.expect(db.comments.slice(1, 2))
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?_start=&_limit=', () => {
|
describe('GET /:resource?_start=&_limit=', () => {
|
||||||
it('should respond with a limited array', () => (
|
it('should respond with a limited array', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?_start=1&_limit=1')
|
.get('/comments?_start=1&_limit=1')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect('X-Total-Count', db.comments.length.toString())
|
.expect('X-Total-Count', db.comments.length.toString())
|
||||||
.expect('Access-Control-Expose-Headers', 'X-Total-Count')
|
.expect('Access-Control-Expose-Headers', 'X-Total-Count')
|
||||||
.expect(db.comments.slice(1, 2))
|
.expect(db.comments.slice(1, 2))
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?_page=', () => {
|
describe('GET /:resource?_page=', () => {
|
||||||
it('should paginate', () => (
|
it('should paginate', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/list?_page=2')
|
.get('/list?_page=2')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect('x-total-count', db.list.length.toString())
|
.expect('x-total-count', db.list.length.toString())
|
||||||
.expect('Access-Control-Expose-Headers', 'X-Total-Count, Link')
|
.expect('Access-Control-Expose-Headers', 'X-Total-Count, Link')
|
||||||
.expect(db.list.slice(10, 20))
|
.expect(db.list.slice(10, 20))
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?_page=&_limit=', () => {
|
describe('GET /:resource?_page=&_limit=', () => {
|
||||||
@ -352,83 +324,69 @@ describe('Server', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?attr_gte=&attr_lte=', () => {
|
describe('GET /:resource?attr_gte=&attr_lte=', () => {
|
||||||
it('should respond with a limited array', () => (
|
it('should respond with a limited array', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?id_gte=2&id_lte=3')
|
.get('/comments?id_gte=2&id_lte=3')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(db.comments.slice(1, 3))
|
.expect(db.comments.slice(1, 3))
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?attr_ne=', () => {
|
describe('GET /:resource?attr_ne=', () => {
|
||||||
it('should respond with a limited array', () => (
|
it('should respond with a limited array', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/comments?id_ne=1')
|
.get('/comments?id_ne=1')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(db.comments.slice(1))
|
.expect(db.comments.slice(1))
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?attr_like=', () => {
|
describe('GET /:resource?attr_like=', () => {
|
||||||
it('should respond with an array that matches the like operator (case insensitive)', () => (
|
it('should respond with an array that matches the like operator (case insensitive)', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/tags?body_like=photo')
|
.get('/tags?body_like=photo')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([
|
.expect([db.tags[1], db.tags[2]])
|
||||||
db.tags[1],
|
.expect(200))
|
||||||
db.tags[2]
|
|
||||||
])
|
|
||||||
.expect(200)
|
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:parent/:parentId/:resource', () => {
|
describe('GET /:parent/:parentId/:resource', () => {
|
||||||
it('should respond with json and corresponding nested resources', () => (
|
it('should respond with json and corresponding nested resources', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/posts/1/comments')
|
.get('/posts/1/comments')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect([
|
.expect([db.comments[0], db.comments[1]])
|
||||||
db.comments[0],
|
.expect(200))
|
||||||
db.comments[1]
|
|
||||||
])
|
|
||||||
.expect(200)
|
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource/:id', () => {
|
describe('GET /:resource/:id', () => {
|
||||||
it('should respond with json and corresponding resource', () => (
|
it('should respond with json and corresponding resource', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/posts/1')
|
.get('/posts/1')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(db.posts[0])
|
.expect(db.posts[0])
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
|
|
||||||
it('should support string id, respond with json and corresponding resource', () => (
|
it('should support string id, respond with json and corresponding resource', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/refs/abcd-1234')
|
.get('/refs/abcd-1234')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(db.refs[0])
|
.expect(db.refs[0])
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
|
|
||||||
it('should support integer id as string', () => (
|
it('should support integer id as string', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/stringIds/1234')
|
.get('/stringIds/1234')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(db.stringIds[0])
|
.expect(db.stringIds[0])
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
|
|
||||||
it('should respond with 404 if resource is not found', () => (
|
it('should respond with 404 if resource is not found', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/posts/9001')
|
.get('/posts/9001')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect({})
|
.expect({})
|
||||||
.expect(404)
|
.expect(404))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource?_embed=', () => {
|
describe('GET /:resource?_embed=', () => {
|
||||||
@ -570,14 +528,13 @@ describe('Server', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('POST /:parent/:parentId/:resource', () => {
|
describe('POST /:parent/:parentId/:resource', () => {
|
||||||
it('should respond with json and set parentId', () => (
|
it('should respond with json and set parentId', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.post('/posts/1/comments')
|
.post('/posts/1/comments')
|
||||||
.send({ body: 'foo' })
|
.send({ body: 'foo' })
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect({ id: 6, postId: 1, body: 'foo' })
|
.expect({ id: 6, postId: 1, body: 'foo' })
|
||||||
.expect(201)
|
.expect(201))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('PUT /:resource/:id', () => {
|
describe('PUT /:resource/:id', () => {
|
||||||
@ -598,14 +555,13 @@ describe('Server', () => {
|
|||||||
assert.deepStrictEqual(db.posts[0], post)
|
assert.deepStrictEqual(db.posts[0], post)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should respond with 404 if resource is not found', () => (
|
it('should respond with 404 if resource is not found', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.put('/posts/9001')
|
.put('/posts/9001')
|
||||||
.send({ id: 1, body: 'bar' })
|
.send({ id: 1, body: 'bar' })
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect({})
|
.expect({})
|
||||||
.expect(404)
|
.expect(404))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('PATCH /:resource/:id', () => {
|
describe('PATCH /:resource/:id', () => {
|
||||||
@ -623,61 +579,53 @@ describe('Server', () => {
|
|||||||
assert.deepStrictEqual(db.posts[0], post)
|
assert.deepStrictEqual(db.posts[0], post)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should respond with 404 if resource is not found', () => (
|
it('should respond with 404 if resource is not found', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.patch('/posts/9001')
|
.patch('/posts/9001')
|
||||||
.send({ body: 'bar' })
|
.send({ body: 'bar' })
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect({})
|
.expect({})
|
||||||
.expect(404)
|
.expect(404))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('DELETE /:resource/:id', () => {
|
describe('DELETE /:resource/:id', () => {
|
||||||
it('should respond with empty data, destroy resource and dependent resources', async () => {
|
it('should respond with empty data, destroy resource and dependent resources', async () => {
|
||||||
await request(server)
|
await request(server).del('/posts/1').expect({}).expect(200)
|
||||||
.del('/posts/1')
|
|
||||||
.expect({})
|
|
||||||
.expect(200)
|
|
||||||
assert.equal(db.posts.length, 1)
|
assert.equal(db.posts.length, 1)
|
||||||
assert.equal(db.comments.length, 3)
|
assert.equal(db.comments.length, 3)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should respond with 404 if resource is not found', () => (
|
it('should respond with 404 if resource is not found', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.del('/posts/9001')
|
.del('/posts/9001')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect({})
|
.expect({})
|
||||||
.expect(404)
|
.expect(404))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Static routes', () => {
|
describe('Static routes', () => {
|
||||||
describe('GET /', () => {
|
describe('GET /', () => {
|
||||||
it('should respond with html', () => (
|
it('should respond with html', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/')
|
.get('/')
|
||||||
.expect(/You're successfully running JSON Server/)
|
.expect(/You're successfully running JSON Server/)
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /main.js', () => {
|
describe('GET /main.js', () => {
|
||||||
it('should respond with js', () => (
|
it('should respond with js', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/main.js')
|
.get('/main.js')
|
||||||
.expect('Content-Type', /javascript/)
|
.expect('Content-Type', /javascript/)
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /style.css', () => {
|
describe('GET /style.css', () => {
|
||||||
it('should respond with css', () => (
|
it('should respond with css', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/style.css')
|
.get('/style.css')
|
||||||
.expect('Content-Type', /css/)
|
.expect('Content-Type', /css/)
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -688,41 +636,29 @@ describe('Server', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('Responses', () => {
|
describe('Responses', () => {
|
||||||
it('should have no cache headers (for IE)', () => (
|
it('should have no cache headers (for IE)', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/db')
|
.get('/db')
|
||||||
.expect('Cache-Control', 'no-cache')
|
.expect('Cache-Control', 'no-cache')
|
||||||
.expect('Pragma', 'no-cache')
|
.expect('Pragma', 'no-cache')
|
||||||
.expect('Expires', '-1')
|
.expect('Expires', '-1'))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Rewriter', () => {
|
describe('Rewriter', () => {
|
||||||
it('should rewrite using prefix', () => (
|
it('should rewrite using prefix', () =>
|
||||||
request(server)
|
request(server).get('/api/posts/1').expect(db.posts[0]))
|
||||||
.get('/api/posts/1')
|
|
||||||
.expect(db.posts[0])
|
|
||||||
))
|
|
||||||
|
|
||||||
it('should rewrite using params', () => (
|
it('should rewrite using params', () =>
|
||||||
request(server)
|
request(server).get('/blog/posts/1/show').expect(db.posts[0]))
|
||||||
.get('/blog/posts/1/show')
|
|
||||||
.expect(db.posts[0])
|
|
||||||
))
|
|
||||||
|
|
||||||
it('should rewrite using query without params', () => {
|
it('should rewrite using query without params', () => {
|
||||||
const expectedPost = _.cloneDeep(db.posts[0])
|
const expectedPost = _.cloneDeep(db.posts[0])
|
||||||
expectedPost.comments = [db.comments[0], db.comments[1]]
|
expectedPost.comments = [db.comments[0], db.comments[1]]
|
||||||
return request(server)
|
return request(server).get('/firstpostwithcomments').expect(expectedPost)
|
||||||
.get('/firstpostwithcomments')
|
|
||||||
.expect(expectedPost)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should rewrite using params and query', () => (
|
it('should rewrite using params and query', () =>
|
||||||
request(server)
|
request(server).get('/comments/special/1-quux').expect([db.comments[4]]))
|
||||||
.get('/comments/special/1-quux')
|
|
||||||
.expect([db.comments[4]])
|
|
||||||
))
|
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// it('should rewrite query params', () => (
|
// it('should rewrite query params', () => (
|
||||||
@ -732,11 +668,8 @@ describe('Server', () => {
|
|||||||
// .end(done)
|
// .end(done)
|
||||||
// })
|
// })
|
||||||
|
|
||||||
it('should expose routes', () => (
|
it('should expose routes', () =>
|
||||||
request(server)
|
request(server).get('/__rules').expect(rewriterRules))
|
||||||
.get('/__rules')
|
|
||||||
.expect(rewriterRules)
|
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('router.render', () => {
|
describe('router.render', () => {
|
||||||
@ -746,41 +679,36 @@ describe('Server', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should be possible to wrap response', () => (
|
it('should be possible to wrap response', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/posts/1')
|
.get('/posts/1')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect({ data: db.posts[0] })
|
.expect({ data: db.posts[0] })
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('router.db._.id', () => {
|
describe('router.db._.id', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
router.db.setState({
|
router.db.setState({
|
||||||
posts: [
|
posts: [{ _id: 1 }]
|
||||||
{ _id: 1 }
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
|
|
||||||
router.db._.id = '_id'
|
router.db._.id = '_id'
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should be possible to GET using a different id property', () => (
|
it('should be possible to GET using a different id property', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.get('/posts/1')
|
.get('/posts/1')
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(router.db.getState().posts[0])
|
.expect(router.db.getState().posts[0])
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
|
|
||||||
it('should be possible to POST using a different id property', () => (
|
it('should be possible to POST using a different id property', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.post('/posts')
|
.post('/posts')
|
||||||
.send({ body: 'hello' })
|
.send({ body: 'hello' })
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect({ _id: 2, body: 'hello' })
|
.expect({ _id: 2, body: 'hello' })
|
||||||
.expect(201)
|
.expect(201))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -21,43 +21,30 @@ describe('Server', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('GET /:resource', () => {
|
describe('GET /:resource', () => {
|
||||||
it('should respond with corresponding resource', () => (
|
it('should respond with corresponding resource', () =>
|
||||||
request(server)
|
request(server).get('/user').expect(db.user).expect(200))
|
||||||
.get('/user')
|
|
||||||
.expect(db.user)
|
|
||||||
.expect(200)
|
|
||||||
))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('POST /:resource', () => {
|
describe('POST /:resource', () => {
|
||||||
it('should create resource', () => {
|
it('should create resource', () => {
|
||||||
const user = { name: 'bar' }
|
const user = { name: 'bar' }
|
||||||
return request(server)
|
return request(server).post('/user').send(user).expect(user).expect(201)
|
||||||
.post('/user')
|
|
||||||
.send(user)
|
|
||||||
.expect(user)
|
|
||||||
.expect(201)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('PUT /:resource', () => {
|
describe('PUT /:resource', () => {
|
||||||
it('should update resource', () => {
|
it('should update resource', () => {
|
||||||
const user = { name: 'bar' }
|
const user = { name: 'bar' }
|
||||||
return request(server)
|
return request(server).put('/user').send(user).expect(user).expect(200)
|
||||||
.put('/user')
|
|
||||||
.send(user)
|
|
||||||
.expect(user)
|
|
||||||
.expect(200)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('PATCH /:resource', () => {
|
describe('PATCH /:resource', () => {
|
||||||
it('should update resource', () => (
|
it('should update resource', () =>
|
||||||
request(server)
|
request(server)
|
||||||
.patch('/user')
|
.patch('/user')
|
||||||
.send({ name: 'bar' })
|
.send({ name: 'bar' })
|
||||||
.expect({ name: 'bar', email: 'foo@example.com' })
|
.expect({ name: 'bar', email: 'foo@example.com' })
|
||||||
.expect(200)
|
.expect(200))
|
||||||
))
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -7,70 +7,52 @@ describe('utils', () => {
|
|||||||
const perPage = 2
|
const perPage = 2
|
||||||
|
|
||||||
it('should return first page', () => {
|
it('should return first page', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(utils.getPage(array, 1, perPage), {
|
||||||
utils.getPage(array, 1, perPage),
|
|
||||||
{
|
|
||||||
items: [1, 2],
|
items: [1, 2],
|
||||||
current: 1,
|
current: 1,
|
||||||
first: 1,
|
first: 1,
|
||||||
next: 2,
|
next: 2,
|
||||||
last: 3
|
last: 3
|
||||||
}
|
})
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return second page', () => {
|
it('should return second page', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(utils.getPage(array, 2, perPage), {
|
||||||
utils.getPage(array, 2, perPage),
|
|
||||||
{
|
|
||||||
items: [3, 4],
|
items: [3, 4],
|
||||||
current: 2,
|
current: 2,
|
||||||
first: 1,
|
first: 1,
|
||||||
prev: 1,
|
prev: 1,
|
||||||
next: 3,
|
next: 3,
|
||||||
last: 3
|
last: 3
|
||||||
}
|
})
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return third page (last)', () => {
|
it('should return third page (last)', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(utils.getPage(array, 3, perPage), {
|
||||||
utils.getPage(array, 3, perPage),
|
|
||||||
{
|
|
||||||
items: [5],
|
items: [5],
|
||||||
current: 3,
|
current: 3,
|
||||||
first: 1,
|
first: 1,
|
||||||
prev: 2,
|
prev: 2,
|
||||||
last: 3
|
last: 3
|
||||||
}
|
})
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return an empty array if page is greater than the last page', () => {
|
it('should return an empty array if page is greater than the last page', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(utils.getPage(array, 99, perPage), {
|
||||||
utils.getPage(array, 99, perPage),
|
|
||||||
{
|
|
||||||
items: []
|
items: []
|
||||||
}
|
})
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return the array if perPage is greater than the array size', () => {
|
it('should return the array if perPage is greater than the array size', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(utils.getPage(array, 1, 99), {
|
||||||
utils.getPage(array, 1, 99),
|
|
||||||
{
|
|
||||||
items: array
|
items: array
|
||||||
}
|
})
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return an empty array if the array is empty', () => {
|
it('should return an empty array if the array is empty', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(utils.getPage([], 1, 1), {
|
||||||
utils.getPage([], 1, 1),
|
|
||||||
{
|
|
||||||
items: []
|
items: []
|
||||||
}
|
})
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -3,22 +3,14 @@ const validateData = require('../../src/server/router/validate-data')
|
|||||||
|
|
||||||
describe('validateData', () => {
|
describe('validateData', () => {
|
||||||
it('should throw an error if data contains /', () => {
|
it('should throw an error if data contains /', () => {
|
||||||
assert.throws(
|
assert.throws(() => validateData({ 'a/b': [] }), /found \//)
|
||||||
() => validateData({ 'a/b': [] }),
|
|
||||||
/found \//
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should throw an error if data is an array', () => {
|
it('should throw an error if data is an array', () => {
|
||||||
assert.throws(
|
assert.throws(() => validateData([]), /must be an object/)
|
||||||
() => validateData([]),
|
|
||||||
/must be an object/
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('shouldn\'t throw an error', () => {
|
it("shouldn't throw an error", () => {
|
||||||
assert.doesNotThrow(
|
assert.doesNotThrow(() => validateData({ a: [] }))
|
||||||
() => validateData({ a: [] })
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user