From 954c0b61d35ec306100ba178ff9ae3e2fb96492f Mon Sep 17 00:00:00 2001 From: typicode Date: Thu, 6 Oct 2016 00:15:13 +0200 Subject: [PATCH] ES2015 --- .babelrc | 2 +- package.json | 14 +- src/cli/index.js | 12 +- src/cli/run.js | 79 ++++---- src/cli/utils/is.js | 16 +- src/cli/utils/load.js | 31 +-- src/server/body-parser.js | 2 +- src/server/defaults.js | 40 ++-- src/server/index.js | 8 +- src/server/mixins.js | 51 +++-- src/server/rewriter.js | 14 +- src/server/router/index.js | 53 +++--- src/server/router/nested.js | 20 +- src/server/router/plural.js | 139 +++++++------- src/server/router/singular.js | 6 +- src/server/utils.js | 24 +-- test/cli/index.js | 213 +++++++++++---------- test/mocha.opts | 2 + test/server/mixins.js | 66 ++++--- test/server/plural.js | 347 +++++++++++++++++----------------- test/server/singular.js | 15 +- test/server/utils.js | 10 +- 22 files changed, 590 insertions(+), 574 deletions(-) create mode 100644 test/mocha.opts diff --git a/.babelrc b/.babelrc index 3c078e9..45001da 100644 --- a/.babelrc +++ b/.babelrc @@ -1,5 +1,5 @@ { "presets": [ - "es2015" + ["es2015", { "loose": true }] ] } diff --git a/package.json b/package.json index da91d39..ab51929 100644 --- a/package.json +++ b/package.json @@ -39,14 +39,14 @@ "os-tmpdir": "^1.0.1", "rimraf": "^2.5.2", "server-ready": "^0.2.0", - "standard": "^7.1.2", + "standard": "^8.3.0", "supertest": "^1.2.0", "temp-write": "^2.1.0" }, "scripts": { "test": "npm run test:cli && npm run test:server && standard", - "test:cli": "cross-env NODE_ENV=test mocha -R spec test/cli/*.js", - "test:server": "cross-env NODE_ENV=test mocha -R spec test/server/*.js", + "test:cli": "cross-env NODE_ENV=test mocha test/cli/*.js", + "test:server": "cross-env NODE_ENV=test mocha test/server/*.js", "start": "node bin", "prepush": "npm t", "build": "babel src -d lib" @@ -76,5 +76,11 @@ "bugs": { "url": "https://github.com/typicode/json-server/issues" }, - "homepage": "https://github.com/typicode/json-server" + "homepage": "https://github.com/typicode/json-server", + "standard": { + "fix": true, + "env": { + "mocha": true + } + } } diff --git a/src/cli/index.js b/src/cli/index.js index 29c7f71..8f62da1 100644 --- a/src/cli/index.js +++ b/src/cli/index.js @@ -1,12 +1,12 @@ -var updateNotifier = require('update-notifier') -var yargs = require('yargs') -var run = require('./run') -var pkg = require('../../package.json') +const updateNotifier = require('update-notifier') +const yargs = require('yargs') +const run = require('./run') +const pkg = require('../../package.json') module.exports = function () { - updateNotifier({ pkg: pkg }).notify() + updateNotifier({ pkg }).notify() - var argv = yargs + const argv = yargs .config('config') .usage('$0 [options] ') .options({ diff --git a/src/cli/run.js b/src/cli/run.js index 975fbce..2c35ccc 100644 --- a/src/cli/run.js +++ b/src/cli/run.js @@ -1,22 +1,22 @@ -var fs = require('fs') -var path = require('path') -var _ = require('lodash') -var chalk = require('chalk') -var chokidar = require('chokidar') -var enableDestroy = require('server-destroy') -var pause = require('connect-pause') -var is = require('./utils/is') -var load = require('./utils/load') -var jsonServer = require('../server') +const fs = require('fs') +const path = require('path') +const _ = require('lodash') +const chalk = require('chalk') +const chokidar = require('chokidar') +const enableDestroy = require('server-destroy') +const pause = require('connect-pause') +const is = require('./utils/is') +const load = require('./utils/load') +const jsonServer = require('../server') function prettyPrint (argv, object, rules) { - var host = argv.host === '0.0.0.0' ? 'localhost' : argv.host - var port = argv.port - var root = 'http://' + host + ':' + port + const host = argv.host === '0.0.0.0' ? 'localhost' : argv.host + const port = argv.port + const root = `http://${host}:${port}` console.log() console.log(chalk.bold(' Resources')) - for (var prop in object) { + for (let prop in object) { console.log(' ' + root + '/' + prop) } @@ -35,15 +35,15 @@ function prettyPrint (argv, object, rules) { } function createApp (source, object, routes, middlewares, argv) { - var app = jsonServer.create() + const app = jsonServer.create() - var router = jsonServer.router( + const router = jsonServer.router( is.JSON(source) ? source : object ) - var defaultsOpts = { + const defaultsOpts = { logger: !argv.quiet, readOnly: argv.readOnly, noCors: argv.noCors, @@ -54,11 +54,11 @@ function createApp (source, object, routes, middlewares, argv) { defaultsOpts.static = path.join(process.cwd(), argv.static) } - var defaults = jsonServer.defaults(defaultsOpts) + const defaults = jsonServer.defaults(defaultsOpts) app.use(defaults) if (routes) { - var rewriter = jsonServer.rewriter(routes) + const rewriter = jsonServer.rewriter(routes) app.use(rewriter) } @@ -78,18 +78,18 @@ function createApp (source, object, routes, middlewares, argv) { } module.exports = function (argv) { - var source = argv._[0] - var app - var server + const source = argv._[0] + let app + let server if (!fs.existsSync(argv.snapshots)) { - console.log('Error: snapshots directory ' + argv.snapshots + ' doesn\'t exist') + console.log(`Error: snapshots directory ${argv.snapshots} doesn't exist`) process.exit(1) } // noop log fn if (argv.quiet) { - console.log = function () {} + console.log = () => {} } console.log() @@ -100,17 +100,18 @@ module.exports = function (argv) { console.log(chalk.gray(' Loading', source)) // Load JSON, JS or HTTP database - load(source, function (err, data) { + load(source, (err, data) => { if (err) throw err // Load additional routes + let routes if (argv.routes) { console.log(chalk.gray(' Loading', argv.routes)) - var routes = JSON.parse(fs.readFileSync(argv.routes)) + routes = JSON.parse(fs.readFileSync(argv.routes)) } // Load middlewares - var middlewares + let middlewares if (argv.middlewares) { middlewares = argv.middlewares.map(function (m) { console.log(chalk.gray(' Loading', m)) @@ -136,7 +137,7 @@ module.exports = function (argv) { } // Start server - start(function () { + start(() => { // Snapshot console.log( chalk.gray(' Type s + enter at any time to create a snapshot of the database') @@ -144,13 +145,13 @@ module.exports = function (argv) { process.stdin.resume() process.stdin.setEncoding('utf8') - process.stdin.on('data', function (chunk) { + process.stdin.on('data', (chunk) => { if (chunk.trim().toLowerCase() === 's') { - var filename = 'db-' + Date.now() + '.json' - var file = path.join(argv.snapshots, filename) - var state = app.db.getState() + const filename = 'db-' + Date.now() + '.json' + const file = path.join(argv.snapshots, filename) + const state = app.db.getState() 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`) } }) @@ -158,7 +159,7 @@ module.exports = function (argv) { if (argv.watch) { console.log(chalk.gray(' Watching...')) console.log() - var source = argv._[0] + const source = argv._[0] // Can't watch URL if (is.URL(source)) throw new Error('Can\'t watch URL') @@ -167,19 +168,19 @@ module.exports = function (argv) { // Since lowdb uses atomic writing, directory is watched instead of file chokidar .watch(path.dirname(source)) - .on('change', function (file) { + .on('change', (file) => { if (path.resolve(file) === path.resolve(source)) { if (is.JSON(file)) { var obj = JSON.parse(fs.readFileSync(file)) // Compare .json file content with in memory database var isDatabaseDifferent = !_.isEqual(obj, app.db.getState()) if (isDatabaseDifferent) { - console.log(chalk.gray(' ' + file + ' has changed, reloading...')) + console.log(chalk.gray(` ${file} has changed, reloading...`)) server && server.destroy() start() } } else { - console.log(chalk.gray(' ' + file + ' has changed, reloading...')) + console.log(chalk.gray(` ${file} has changed, reloading...`)) server && server.destroy() start() } @@ -190,8 +191,8 @@ module.exports = function (argv) { if (argv.routes) { chokidar .watch(argv.routes) - .on('change', function (file) { - console.log(chalk.gray(' ' + file + ' has changed, reloading...')) + .on('change', (file) => { + console.log(chalk.gray(` ${file} has changed, reloading...`)) server && server.destroy() start() }) diff --git a/src/cli/utils/is.js b/src/cli/utils/is.js index a59da21..2f5b8df 100644 --- a/src/cli/utils/is.js +++ b/src/cli/utils/is.js @@ -1,17 +1,17 @@ module.exports = { - JSON: isJSON, - JS: isJS, - URL: isURL + JSON, + JS, + URL } -function isJSON (s) { - return !isURL(s) && /\.json$/.test(s) +function JSON (s) { + return !URL(s) && /\.json$/.test(s) } -function isJS (s) { - return !isURL(s) && /\.js$/.test(s) +function JS (s) { + return !URL(s) && /\.js$/.test(s) } -function isURL (s) { +function URL (s) { return /^(http|https):/.test(s) } diff --git a/src/cli/utils/load.js b/src/cli/utils/load.js index 28a1e94..e14a2a5 100644 --- a/src/cli/utils/load.js +++ b/src/cli/utils/load.js @@ -1,30 +1,37 @@ -var path = require('path') -var request = require('request') -var low = require('lowdb') -var fileAsync = require('lowdb/lib/file-async') -var is = require('./is') +const path = require('path') +const request = require('request') +const low = require('lowdb') +const fileAsync = require('lowdb/lib/file-async') +const is = require('./is') module.exports = function (source, cb) { - var data - if (is.URL(source)) { - request({ url: source, json: true }, function (err, response) { + // Load remote data + const opts = { + url: source, + json: true + } + + request(opts, (err, response) => { if (err) return cb(err) cb(null, response.body) }) } else if (is.JS(source)) { - var filename = path.resolve(source) + // Clear cache + const filename = path.resolve(source) delete require.cache[filename] - var dataFn = require(filename) + const dataFn = require(filename) if (typeof dataFn !== 'function') { throw new Error('The database is a JavaScript file but the export is not a function.') } - data = dataFn() + // Run dataFn to generate data + const data = dataFn() cb(null, data) } else if (is.JSON(source)) { - data = low(source, { storage: fileAsync }).getState() + // Load JSON using lowdb + const data = low(source, { storage: fileAsync }).getState() cb(null, data) } else { throw new Error('Unsupported source ' + source) diff --git a/src/server/body-parser.js b/src/server/body-parser.js index bc95924..eeeda21 100644 --- a/src/server/body-parser.js +++ b/src/server/body-parser.js @@ -1,4 +1,4 @@ -var bodyParser = require('body-parser') +const bodyParser = require('body-parser') module.exports = [ bodyParser.json({limit: '10mb', extended: false}), diff --git a/src/server/defaults.js b/src/server/defaults.js index cedd843..44265a3 100644 --- a/src/server/defaults.js +++ b/src/server/defaults.js @@ -1,22 +1,22 @@ -var fs = require('fs') -var path = require('path') -var express = require('express') -var logger = require('morgan') -var cors = require('cors') -var compression = require('compression') -var errorhandler = require('errorhandler') -var objectAssign = require('object-assign') +const fs = require('fs') +const path = require('path') +const express = require('express') +const logger = require('morgan') +const cors = require('cors') +const compression = require('compression') +const errorhandler = require('errorhandler') +const objectAssign = require('object-assign') module.exports = function (opts) { - var userDir = path.join(process.cwd(), 'public') - var defaultDir = path.join(__dirname, 'public') - var staticDir = fs.existsSync(userDir) + const userDir = path.join(process.cwd(), 'public') + const defaultDir = path.join(__dirname, 'public') + const staticDir = fs.existsSync(userDir) ? userDir : defaultDir opts = objectAssign({ logger: true, static: staticDir }, opts) - var arr = [] + const arr = [] // Compress all requests if (!opts.noGzip) { @@ -25,12 +25,14 @@ module.exports = function (opts) { // Logger if (opts.logger) { - arr.push(logger('dev', { - skip: function (req, res) { - return process.env.NODE_ENV === 'test' || + arr.push( + logger('dev', { + skip: (req) => ( + process.env.NODE_ENV === 'test' || req.path === '/favicon.ico' - } - })) + ) + }) + ) } // Enable CORS for all the requests, including static files @@ -48,7 +50,7 @@ module.exports = function (opts) { // No cache for IE // https://support.microsoft.com/en-us/kb/234067 - arr.push(function (req, res, next) { + arr.push((req, res, next) => { res.header('Cache-Control', 'no-cache') res.header('Pragma', 'no-cache') res.header('Expires', '-1') @@ -57,7 +59,7 @@ module.exports = function (opts) { // Read-only if (opts.readOnly) { - arr.push(function (req, res, next) { + arr.push((req, res, next) => { if (req.method === 'GET') { next() // Continue } else { diff --git a/src/server/index.js b/src/server/index.js index ffc8418..dd98979 100644 --- a/src/server/index.js +++ b/src/server/index.js @@ -1,11 +1,7 @@ -var express = require('express') +const express = require('express') module.exports = { - create: function () { - var server = express() - server.set('json spaces', 2) - return server - }, + create: () => express().set('json spaces', 2), defaults: require('./defaults'), router: require('./router'), rewriter: require('./rewriter'), diff --git a/src/server/mixins.js b/src/server/mixins.js index 43dab7f..4c3aa0b 100644 --- a/src/server/mixins.js +++ b/src/server/mixins.js @@ -1,28 +1,28 @@ -var uuid = require('node-uuid') -var pluralize = require('pluralize') +const uuid = require('node-uuid') +const pluralize = require('pluralize') module.exports = { - getRemovable: getRemovable, - createId: createId, - deepQuery: deepQuery + getRemovable, + createId, + deepQuery } // Returns document ids that have unsatisfied relations // Example: a comment that references a post that doesn't exist function getRemovable (db) { - var _ = this - var removable = [] - _.each(db, function (coll, collName) { - _.each(coll, function (doc) { - _.each(doc, function (value, key) { + const _ = this + const removable = [] + _.each(db, (coll, collName) => { + _.each(coll, (doc) => { + _.each(doc, (value, key) => { if (/Id$/.test(key)) { - var refName = pluralize.plural(key.slice(0, -2)) + const refName = pluralize.plural(key.slice(0, -2)) // Test if table exists if (db[refName]) { // Test if references is defined in table - var ref = _.getById(db[refName], value) + const ref = _.getById(db[refName], value) if (_.isUndefined(ref)) { - removable.push({name: collName, id: doc.id}) + removable.push({ name: collName, id: doc.id }) } } } @@ -36,36 +36,31 @@ function getRemovable (db) { // Return incremented id or uuid // Used to override underscore-db's createId with utils.createId function createId (coll) { - var _ = this - var idProperty = _.__id() + const _ = this + const idProperty = _.__id() if (_.isEmpty(coll)) { return 1 } else { - var id = _.maxBy(coll, function (doc) { - return doc[idProperty] - })[idProperty] + let id = _(coll).maxBy(idProperty)[idProperty] - if (_.isFinite(id)) { - // Increment integer id - return ++id - } else { - // Generate string id - return uuid() - } + // Increment integer id or generate string id + return _.isFinite(id) + ? ++id + : uuid() } } function deepQuery (value, q) { - var _ = this + const _ = this if (value && q) { if (_.isArray(value)) { - for (var i = 0; i < value.length; i++) { + for (let i = 0; i < value.length; i++) { if (_.deepQuery(value[i], q)) { return true } } } else if (_.isObject(value) && !_.isArray(value)) { - for (var k in value) { + for (let k in value) { if (_.deepQuery(value[k], q)) { return true } diff --git a/src/server/rewriter.js b/src/server/rewriter.js index e61cc4b..189fb36 100644 --- a/src/server/rewriter.js +++ b/src/server/rewriter.js @@ -1,21 +1,21 @@ -var express = require('express') +const express = require('express') module.exports = function (routes) { - var router = express.Router() + const router = express.Router() - Object.keys(routes).forEach(function (route) { + Object.keys(routes).forEach((route) => { if (route.indexOf(':') !== -1) { - router.all(route, function (req, res, next) { + router.all(route, (req, res, next) => { // Rewrite target url using params - var target = routes[route] - for (var param in req.params) { + let target = routes[route] + for (let param in req.params) { target = target.replace(':' + param, req.params[param]) } req.url = target next() }) } else { - router.all(route + '*', function (req, res, next) { + router.all(route + '*', (req, res, next) => { // Rewrite url by replacing prefix req.url = req.url.replace(route, routes[route]) next() diff --git a/src/server/router/index.js b/src/server/router/index.js index e103c52..d95d79e 100644 --- a/src/server/router/index.js +++ b/src/server/router/index.js @@ -1,25 +1,25 @@ -var express = require('express') -var methodOverride = require('method-override') -var _ = require('lodash') -var _db = require('underscore-db') -var low = require('lowdb') -var fileAsync = require('lowdb/lib/file-async') -var bodyParser = require('../body-parser') -var plural = require('./plural') -var nested = require('./nested') -var singular = require('./singular') -var mixins = require('../mixins') +const express = require('express') +const methodOverride = require('method-override') +const _ = require('lodash') +const _db = require('underscore-db') +const low = require('lowdb') +const fileAsync = require('lowdb/lib/file-async') +const bodyParser = require('../body-parser') +const plural = require('./plural') +const nested = require('./nested') +const singular = require('./singular') +const mixins = require('../mixins') -module.exports = function (source) { +module.exports = (source) => { // Create router - var router = express.Router() + const router = express.Router() // Add middlewares router.use(methodOverride()) router.use(bodyParser) // Create database - var db + let db if (_.isObject(source)) { db = low() db.setState(source) @@ -37,40 +37,39 @@ module.exports = function (source) { router.db = db // Expose render - router.render = function (req, res) { + router.render = (req, res) => { res.jsonp(res.locals.data) } // GET /db - function showDatabase (req, res, next) { + router.get('/db', (req, res) => { res.jsonp(db.getState()) - } - - router.get('/db', showDatabase) + }) + // Handle /:parent/:parentId/:resource router.use(nested()) // Create routes - db.forEach(function (value, key) { + db.forEach((value, key) => { if (_.isPlainObject(value)) { - router.use('/' + key, singular(db, key)) + router.use(`/${key}`, singular(db, key)) return } if (_.isArray(value)) { - router.use('/' + key, plural(db, key)) + router.use(`/${key}`, plural(db, key)) return } - var msg = - 'Type of "' + key + '" (' + typeof value + ') ' + - (_.isObject(source) ? '' : 'in ' + source) + ' is not supported. ' + + const msg = + `Type of "${key}" (${typeof value}) ` + + (_.isObject(source) ? '' : `in ${source}`) + ' is not supported. ' + 'Use objects or arrays of objects.' throw new Error(msg) }).value() - router.use(function (req, res) { + router.use((req, res) => { if (!res.locals.data) { res.status(404) res.locals.data = {} @@ -79,7 +78,7 @@ module.exports = function (source) { router.render(req, res) }) - router.use(function (err, req, res, next) { + router.use((err, req, res, next) => { console.error(err.stack) res.status(500).send(err.stack) }) diff --git a/src/server/router/nested.js b/src/server/router/nested.js index 3910177..61a1a59 100644 --- a/src/server/router/nested.js +++ b/src/server/router/nested.js @@ -1,22 +1,22 @@ -var express = require('express') -var pluralize = require('pluralize') +const express = require('express') +const pluralize = require('pluralize') -module.exports = function () { - var router = express.Router() +module.exports = () => { + const router = express.Router() // Rewrite URL (/:resource/:id/:nested -> /:nested) and request query function get (req, res, next) { - var prop = pluralize.singular(req.params.resource) - req.query[prop + 'Id'] = req.params.id - req.url = '/' + req.params.nested + const prop = pluralize.singular(req.params.resource) + req.query[`${prop}Id`] = req.params.id + req.url = `/${req.params.nested}` next() } // Rewrite URL (/:resource/:id/:nested -> /:nested) and request body function post (req, res, next) { - var prop = pluralize.singular(req.params.resource) - req.body[prop + 'Id'] = req.params.id - req.url = '/' + req.params.nested + const prop = pluralize.singular(req.params.resource) + req.body[`${prop}Id`] = req.params.id + req.url = `/${req.params.nested}` next() } diff --git a/src/server/router/plural.js b/src/server/router/plural.js index 8fde9be..7b88089 100644 --- a/src/server/router/plural.js +++ b/src/server/router/plural.js @@ -1,20 +1,21 @@ -var express = require('express') -var _ = require('lodash') -var pluralize = require('pluralize') -var utils = require('../utils') +const url = require('url') +const express = require('express') +const _ = require('lodash') +const pluralize = require('pluralize') +const utils = require('../utils') -module.exports = function (db, name) { +module.exports = (db, name) => { // Create router - var router = express.Router() + const router = express.Router() // Embed function used in GET /name and GET /name/id function embed (resource, e) { e && [].concat(e) - .forEach(function (externalResource) { + .forEach((externalResource) => { if (db.get(externalResource).value) { - var query = {} - var singularResource = pluralize.singular(name) - query[singularResource + 'Id'] = resource.id + const query = {} + const singularResource = pluralize.singular(name) + query[`${singularResource}Id`] = resource.id resource[externalResource] = db.get(externalResource).filter(query).value() } }) @@ -23,17 +24,22 @@ module.exports = function (db, name) { // Expand function used in GET /name and GET /name/id function expand (resource, e) { e && [].concat(e) - .forEach(function (innerResource) { - var plural = pluralize(innerResource) + .forEach((innerResource) => { + const plural = pluralize(innerResource) if (db.get(plural).value()) { - var prop = innerResource + 'Id' + const prop = `${innerResource}Id` resource[innerResource] = db.get(plural).getById(resource[prop]).value() } }) } function getFullURL (req) { - return req.protocol + '://' + req.get('host') + req.originalUrl + const root = url.format({ + protocol: req.protocol, + host: req.get('host') + }) + + return `${root}${req.originalUrl}` } // GET /name @@ -44,19 +50,19 @@ module.exports = function (db, name) { // GET /name?_embed=&_expand= function list (req, res, next) { // Resource chain - var chain = db.get(name) + let chain = db.get(name) // Remove q, _start, _end, ... from req.query to avoid filtering using those // parameters - var q = req.query.q - var _start = req.query._start - var _end = req.query._end - var _page = req.query._page - var _sort = req.query._sort - var _order = req.query._order - var _limit = req.query._limit - var _embed = req.query._embed - var _expand = req.query._expand + let q = req.query.q + let _start = req.query._start + let _end = req.query._end + let _page = req.query._page + let _sort = req.query._sort + let _order = req.query._order + let _limit = req.query._limit + let _embed = req.query._embed + let _expand = req.query._expand delete req.query.q delete req.query._start delete req.query._end @@ -68,9 +74,9 @@ module.exports = function (db, name) { // Automatically delete query parameters that can't be found // in the database - Object.keys(req.query).forEach(function (query) { - var arr = db.get(name).value() - for (var i in arr) { + Object.keys(req.query).forEach((query) => { + const arr = db.get(name).value() + for (let i in arr) { if ( _.has(arr[i], query) || query === 'callback' || @@ -88,9 +94,9 @@ module.exports = function (db, name) { // Full-text search q = q.toLowerCase() - chain = chain.filter(function (obj) { - for (var key in obj) { - var value = obj[key] + chain = chain.filter((obj) => { + for (let key in obj) { + const value = obj[key] if (db._.deepQuery(value, q)) { return true } @@ -98,34 +104,32 @@ module.exports = function (db, name) { }) } - Object.keys(req.query).forEach(function (key) { + Object.keys(req.query).forEach((key) => { // Don't take into account JSONP query parameters // jQuery adds a '_' query parameter too if (key !== 'callback' && key !== '_') { // Always use an array, in case req.query is an array - var arr = [].concat(req.query[key]) + const arr = [].concat(req.query[key]) - chain = chain.filter(function (element) { + chain = chain.filter((element) => { return arr .map(function (value) { - var isDifferent = key.indexOf('_ne') !== -1 - var isRange = key.indexOf('_lte') !== -1 || key.indexOf('_gte') !== -1 - var isLike = key.indexOf('_like') !== -1 - var path = key.replace(/(_lte|_gte|_ne|_like)$/, '') - var elementValue = _.get(element, path) + const isDifferent = key.indexOf('_ne') !== -1 + const isRange = key.indexOf('_lte') !== -1 || key.indexOf('_gte') !== -1 + const isLike = key.indexOf('_like') !== -1 + const path = key.replace(/(_lte|_gte|_ne|_like)$/, '') + const elementValue = _.get(element, path) if (!elementValue) { - return false + return } if (isRange) { - var isLowerThan = key.indexOf('_gte') !== -1 + const isLowerThan = key.indexOf('_gte') !== -1 - if (isLowerThan) { - return value <= elementValue - } else { - return value >= elementValue - } + return isLowerThan + ? value <= elementValue + : value >= elementValue } else if (isDifferent) { return value !== elementValue.toString() } else if (isLike) { @@ -133,9 +137,8 @@ module.exports = function (db, name) { } else { return value === elementValue.toString() } - }).reduce(function (a, b) { - return a || b }) + .reduce((a, b) => a || b) }) } }) @@ -163,9 +166,9 @@ module.exports = function (db, name) { _page = parseInt(_page, 10) _page = _page >= 1 ? _page : 1 _limit = parseInt(_limit, 10) || 10 - var page = utils.getPage(chain.value(), _page, _limit) - var links = {} - var fullURL = getFullURL(req) + const page = utils.getPage(chain.value(), _page, _limit) + const links = {} + const fullURL = getFullURL(req) if (page.first) { links.first = fullURL.replace('page=' + page.current, 'page=' + page.first) @@ -210,23 +213,25 @@ module.exports = function (db, name) { // GET /name/:id // GET /name/:id?_embed=&_expand function show (req, res, next) { - var _embed = req.query._embed - var _expand = req.query._expand - var resource = db.get(name).getById(req.params.id).value() + const _embed = req.query._embed + const _expand = req.query._expand + const resource = db.get(name) + .getById(req.params.id) + .value() if (resource) { // Clone resource to avoid making changes to the underlying object - resource = _.cloneDeep(resource) + const clone = _.cloneDeep(resource) // Embed other resources based on resource id // /posts/1?_embed=comments - embed(resource, _embed) + embed(clone, _embed) // Expand inner resources based on id // /posts/1?_expand=user - expand(resource, _expand) + expand(clone, _expand) - res.locals.data = resource + res.locals.data = clone } next() @@ -234,7 +239,7 @@ module.exports = function (db, name) { // POST /name function create (req, res, next) { - var resource = db.get(name) + const resource = db.get(name) .insert(req.body) .value() @@ -246,14 +251,14 @@ module.exports = function (db, name) { // PUT /name/:id // PATCH /name/:id function update (req, res, next) { - var id = req.params.id - var chain = db.get(name) + const id = req.params.id + let chain = db.get(name) chain = req.method === 'PATCH' ? chain.updateById(id, req.body) : chain.replaceById(id, req.body) - var resource = chain.value() + const resource = chain.value() if (resource) { res.locals.data = resource @@ -264,13 +269,17 @@ module.exports = function (db, name) { // DELETE /name/:id function destroy (req, res, next) { - var resource = db.get(name).removeById(req.params.id).value() + const resource = db.get(name) + .removeById(req.params.id) + .value() // Remove dependents documents - var removable = db._.getRemovable(db.getState()) + const removable = db._.getRemovable(db.getState()) - _.each(removable, function (item) { - db.get(item.name).removeById(item.id).value() + removable.forEach((item) => { + db.get(item.name) + .removeById(item.id) + .value() }) if (resource) { diff --git a/src/server/router/singular.js b/src/server/router/singular.js index c5c6291..f33bbda 100644 --- a/src/server/router/singular.js +++ b/src/server/router/singular.js @@ -1,7 +1,7 @@ -var express = require('express') +const express = require('express') -module.exports = function (db, name) { - var router = express.Router() +module.exports = (db, name) => { + const router = express.Router() function show (req, res, next) { res.locals.data = db.get(name).value() diff --git a/src/server/utils.js b/src/server/utils.js index 8f8307a..f7a5c9a 100644 --- a/src/server/utils.js +++ b/src/server/utils.js @@ -1,27 +1,5 @@ module.exports = { - toNative: toNative, - getPage: getPage -} - -// Turns string to native. -// Example: -// 'true' -> true -// '1' -> 1 -function toNative (value) { - if (typeof value === 'string') { - if ( - value === '' || - value.trim() !== value || - (value.length > 1 && value[0] === '0') - ) { - return value - } else if (value === 'true' || value === 'false') { - return value === 'true' - } else if (!isNaN(+value)) { - return +value - } - } - return value + getPage } function getPage (array, page, perPage) { diff --git a/test/cli/index.js b/test/cli/index.js index ce9657c..de47602 100644 --- a/test/cli/index.js +++ b/test/cli/index.js @@ -1,70 +1,73 @@ -var fs = require('fs') -var path = require('path') -var cp = require('child_process') -var assert = require('assert') -var supertest = require('supertest') -var osTmpdir = require('os-tmpdir') -var tempWrite = require('temp-write') -var mkdirp = require('mkdirp') -var rimraf = require('rimraf') -var express = require('express') -var serverReady = require('server-ready') -var pkg = require('../../package.json') +const fs = require('fs') +const path = require('path') +const cp = require('child_process') +const assert = require('assert') +const supertest = require('supertest') +const osTmpdir = require('os-tmpdir') +const tempWrite = require('temp-write') +const mkdirp = require('mkdirp') +const rimraf = require('rimraf') +const express = require('express') +const serverReady = require('server-ready') +const pkg = require('../../package.json') -var PORT = 3100 +let PORT = 3100 + +const middlewareFiles = { + en: './fixtures/middlewares/en.js', + jp: './fixtures/middlewares/jp.js' +} function cli (args) { - var bin = path.join(__dirname, '../..', pkg.bin) + const bin = path.join(__dirname, '../..', pkg.bin) return cp.spawn('node', [bin, '-p', PORT].concat(args), { cwd: __dirname, stdio: ['pipe', process.stdout, process.stderr] }) } -/* global beforeEach, afterEach, describe, it */ +describe('cli', () => { + let child + let request + let dbFile + let routesFile -describe('cli', function () { - var child - var request - var dbFile - var routesFile - var middlewareFiles = { - en: './fixtures/middlewares/en.js', - jp: './fixtures/middlewares/jp.js' - } + beforeEach(() => { + dbFile = tempWrite.sync( + JSON.stringify({ + posts: [ + { id: 1 }, + { _id: 2 } + ] + }), + 'db.json' + ) - beforeEach(function () { - dbFile = tempWrite.sync(JSON.stringify({ - posts: [ - { id: 1 }, - { _id: 2 } - ] - }), 'db.json') - - routesFile = tempWrite.sync(JSON.stringify({ - '/blog/': '/' - }), 'routes.json') + routesFile = tempWrite.sync( + JSON.stringify({ '/blog/': '/' }), + 'routes.json' + ) ++PORT - request = supertest('http://localhost:' + PORT) + request = supertest(`http://localhost:${PORT}`) }) - afterEach(function () { + afterEach(() => { child.kill() }) - describe('db.json', function () { - beforeEach(function (done) { - child = cli([dbFile]) + describe('db.json', () => { + beforeEach((done) => { + child = cli([ dbFile ]) serverReady(PORT, done) }) - it('should support JSON file', function (done) { + it('should support JSON file', (done) => { request.get('/posts').expect(200, done) }) - it('should send CORS headers', function (done) { - var origin = 'http://example.com' + it('should send CORS headers', (done) => { + const origin = 'http://example.com' request.get('/posts') .set('Origin', origin) @@ -72,12 +75,12 @@ describe('cli', function () { .expect(200, done) }) - it('should update JSON file', function (done) { + it('should update JSON file', (done) => { request.post('/posts') .send({ title: 'hello' }) - .end(function () { - setTimeout(function () { - var str = fs.readFileSync(dbFile, 'utf8') + .end(() => { + setTimeout(() => { + const str = fs.readFileSync(dbFile, 'utf8') assert(str.indexOf('hello') !== -1) done() }, 1000) @@ -85,118 +88,122 @@ describe('cli', function () { }) }) - describe('seed.js', function () { - beforeEach(function (done) { - child = cli(['fixtures/seed.js']) + describe('seed.js', () => { + beforeEach((done) => { + child = cli([ 'fixtures/seed.js' ]) serverReady(PORT, done) }) - it('should support JS file', function (done) { + it('should support JS file', (done) => { request.get('/posts').expect(200, done) }) }) - describe('http://localhost:8080/db', function () { - beforeEach(function (done) { - var fakeServer = express() - fakeServer.get('/db', function (req, res) { + describe('http://localhost:8080/db', () => { + beforeEach((done) => { + const fakeServer = express() + fakeServer.get('/db', (req, res) => { res.jsonp({ posts: [] }) }) - fakeServer.listen(8080, function () { - child = cli(['http://localhost:8080/db']) + fakeServer.listen(8080, () => { + child = cli([ 'http://localhost:8080/db' ]) serverReady(PORT, done) }) }) - it('should support URL file', function (done) { + it('should support URL file', (done) => { request.get('/posts').expect(200, done) }) }) - describe('db.json -r routes.json -m middleware.js -i _id --read-only', function () { - beforeEach(function (done) { - child = cli([dbFile, '-r', routesFile, '-m', middlewareFiles.en, '-i', '_id', '--read-only']) + describe('db.json -r routes.json -m middleware.js -i _id --read-only', () => { + beforeEach((done) => { + child = cli([ dbFile, '-r', routesFile, '-m', middlewareFiles.en, '-i', '_id', '--read-only' ]) serverReady(PORT, done) }) - it('should use routes.json and _id as the identifier', function (done) { + it('should use routes.json and _id as the identifier', (done) => { request.get('/blog/posts/2').expect(200, done) }) - it('should apply middlewares', function (done) { + it('should apply middlewares', (done) => { request.get('/blog/posts/2').expect('X-Hello', 'World', done) }) - it('should allow only GET requests', function (done) { + it('should allow only GET requests', (done) => { request.post('/blog/posts').expect(403, done) }) }) - describe('db.json -m first-middleware.js second-middleware.js', function () { - beforeEach(function (done) { - child = cli([dbFile, '-m', middlewareFiles.en, middlewareFiles.jp]) + describe('db.json -m first-middleware.js second-middleware.js', () => { + beforeEach((done) => { + child = cli([ dbFile, '-m', middlewareFiles.en, middlewareFiles.jp ]) serverReady(PORT, done) }) - it('should apply all middlewares', function (done) { + it('should apply all middlewares', (done) => { request.get('/posts') .expect('X-Hello', 'World') .expect('X-Konnichiwa', 'Sekai', done) }) }) - describe('db.json -d 1000', function () { - beforeEach(function (done) { - child = cli([dbFile, '-d', 1000]) + describe('db.json -d 1000', () => { + beforeEach((done) => { + child = cli([ dbFile, '-d', 1000 ]) serverReady(PORT, done) }) - it('should delay response', function (done) { - var start = new Date() + it('should delay response', (done) => { + const start = new Date() request.get('/posts').expect(200, function (err) { - var end = new Date() - done(end - start > 1000 ? err : new Error('Request wasn\'t delayed')) + const end = new Date() + done( + end - start > 1000 + ? err + : new Error('Request wasn\'t delayed') + ) }) }) }) - describe('db.json -s fixtures/public -S /some/path/snapshots', function () { - var snapshotsDir = path.join(osTmpdir(), 'snapshots') - var publicDir = 'fixtures/public' + describe('db.json -s fixtures/public -S /some/path/snapshots', () => { + const snapshotsDir = path.join(osTmpdir(), 'snapshots') + const publicDir = 'fixtures/public' - beforeEach(function (done) { + beforeEach((done) => { rimraf.sync(snapshotsDir) mkdirp.sync(snapshotsDir) - child = cli([dbFile, '-s', publicDir, '-S', snapshotsDir]) - serverReady(PORT, function () { + child = cli([ dbFile, '-s', publicDir, '-S', snapshotsDir ]) + serverReady(PORT, () => { child.stdin.write('s\n') setTimeout(done, 100) }) }) - it('should serve fixtures/public', function (done) { + it('should serve fixtures/public', (done) => { request.get('/').expect(/Hello/, done) }) - it('should save a snapshot in snapshots dir', function () { + it('should save a snapshot in snapshots dir', () => { assert.equal(fs.readdirSync(snapshotsDir).length, 1) }) }) - describe('fixtures/seed.json --no-cors=true', function () { - beforeEach(function (done) { - child = cli(['fixtures/seed.js', '--no-cors=true']) + describe('fixtures/seed.json --no-cors=true', () => { + beforeEach((done) => { + child = cli([ 'fixtures/seed.js', '--no-cors=true' ]) serverReady(PORT, done) }) - it('should not send Access-Control-Allow-Origin headers', function (done) { - var origin = 'http://example.com' + it('should not send Access-Control-Allow-Origin headers', (done) => { + const origin = 'http://example.com' request.get('/posts') .set('Origin', origin) .expect(200) - .end(function (err, res) { + .end((err, res) => { if (err) { done(err) } if ('access-control-allow-origin' in res.headers) { @@ -208,13 +215,13 @@ describe('cli', function () { }) }) - describe('fixtures/seed.json --no-gzip=true', function () { - beforeEach(function (done) { - child = cli(['fixtures/seed.js', '--no-gzip=true']) + describe('fixtures/seed.json --no-gzip=true', () => { + beforeEach((done) => { + child = cli([ 'fixtures/seed.js', '--no-gzip=true' ]) serverReady(PORT, done) }) - it('should not set Content-Encoding to gzip', function (done) { + it('should not set Content-Encoding to gzip', (done) => { request.get('/posts') .expect(200) .end(function (err, res) { @@ -229,15 +236,15 @@ describe('cli', function () { }) }) - describe('--watch db.json -r routes.json', function () { - beforeEach(function (done) { - child = cli(['--watch', dbFile, '-r', routesFile]) + describe('--watch db.json -r routes.json', () => { + beforeEach((done) => { + child = cli([ '--watch', dbFile, '-r', routesFile ]) serverReady(PORT, done) }) - it('should watch db file', function (done) { + it('should watch db file', (done) => { fs.writeFileSync(dbFile, JSON.stringify({ foo: [] })) - setTimeout(function () { + setTimeout(() => { request.get('/foo').expect(200, done) }, 1000) }) @@ -246,19 +253,19 @@ describe('cli', function () { // Can be very slow this.timeout(10000) fs.writeFileSync(routesFile, JSON.stringify({ '/api/': '/' })) - setTimeout(function () { + setTimeout(() => { request.get('/api/posts').expect(200, done) }, 9000) }) }) - describe('db.json --config some-config.json', function (done) { - beforeEach(function (done) { - child = cli([dbFile, '--config', 'fixtures/config.json']) + describe('db.json --config some-config.json', (done) => { + beforeEach((done) => { + child = cli([ dbFile, '--config', 'fixtures/config.json' ]) serverReady(PORT, done) }) - it('should apply all middlewares', function (done) { + it('should apply all middlewares', (done) => { request.get('/posts') .expect('X-Hello', 'World') .expect('X-Konnichiwa', 'Sekai', done) diff --git a/test/mocha.opts b/test/mocha.opts new file mode 100644 index 0000000..71a7d7f --- /dev/null +++ b/test/mocha.opts @@ -0,0 +1,2 @@ +--compilers js:babel-register +--reporter spec \ No newline at end of file diff --git a/test/server/mixins.js b/test/server/mixins.js index 3952300..8707fd0 100644 --- a/test/server/mixins.js +++ b/test/server/mixins.js @@ -1,34 +1,52 @@ -var assert = require('assert') -var _ = require('lodash') -var _db = require('underscore-db') -var mixins = require('../../src/server/mixins') +const assert = require('assert') +const _ = require('lodash') +const _db = require('underscore-db') +const mixins = require('../../src/server/mixins') -/* global describe, it */ +describe('mixins', () => { + let db -describe('mixins', function () { - describe('getRemovable', function () { - it('should return removable documents', function () { - var db = { - posts: [ - {id: 1, comment: 1} - ], - comments: [ - {id: 1, postId: 1}, - // Comments below references a post that doesn't exist - {id: 2, postId: 2}, - {id: 3, postId: 2} - ] - } + before(() => { + _.mixin(_db) + _.mixin(mixins) + }) - var expected = [ - {name: 'comments', id: 2}, - {name: 'comments', id: 3} + beforeEach(() => { + db = { + posts: [ + { id: 1, comment: 1 } + ], + comments: [ + { id: 1, postId: 1 }, + // Comments below references a post that doesn't exist + { id: 2, postId: 2 }, + { id: 3, postId: 2 } + ], + photos: [ + { id: '1' }, + { id: '2' } ] + } + }) - _.mixin(_db) - _.mixin(mixins) + describe('getRemovable', () => { + it('should return removable documents', () => { + const expected = [ + { name: 'comments', id: 2 }, + { name: 'comments', id: 3 } + ] assert.deepEqual(_.getRemovable(db), expected) }) }) + + describe('createId', () => { + it('should return a new id', () => { + assert.equal(_.createId(db.comments), 4) + }) + + it('should return a new uuid', () => { + assert.notEqual(_.createId(db.photos), 3) + }) + }) }) diff --git a/test/server/plural.js b/test/server/plural.js index 2ae40c8..20fb59a 100644 --- a/test/server/plural.js +++ b/test/server/plural.js @@ -1,47 +1,46 @@ -var assert = require('assert') -var _ = require('lodash') -var request = require('supertest') -var jsonServer = require('../../src/server') +const assert = require('assert') +const _ = require('lodash') +const request = require('supertest') +const jsonServer = require('../../src/server') -/* global beforeEach, describe, it */ -describe('Server', function () { - var server - var router - var db +describe('Server', () => { + let server + let router + let db - beforeEach(function () { + beforeEach(() => { db = {} db.posts = [ - {id: 1, body: 'foo'}, - {id: 2, body: 'bar'} + { id: 1, body: 'foo' }, + { id: 2, body: 'bar' } ] db.tags = [ - {id: 1, body: 'Technology'}, - {id: 2, body: 'Photography'}, - {id: 3, body: 'photo'} + { id: 1, body: 'Technology' }, + { id: 2, body: 'Photography' }, + { id: 3, body: 'photo' } ] db.users = [ - {id: 1, username: 'Jim', tel: '0123'}, - {id: 2, username: 'George', tel: '123'} + { id: 1, username: 'Jim', tel: '0123' }, + { id: 2, username: 'George', tel: '123' } ] db.comments = [ - {id: 1, body: 'foo', published: true, postId: 1, userId: 1}, - {id: 2, body: 'bar', published: false, postId: 1, userId: 2}, - {id: 3, body: 'baz', published: false, postId: 2, userId: 1}, - {id: 4, body: 'qux', published: true, postId: 2, userId: 2}, - {id: 5, body: 'quux', published: false, postId: 2, userId: 1} + { id: 1, body: 'foo', published: true, postId: 1, userId: 1 }, + { id: 2, body: 'bar', published: false, postId: 1, userId: 2 }, + { id: 3, body: 'baz', published: false, postId: 2, userId: 1 }, + { id: 4, body: 'qux', published: true, postId: 2, userId: 2 }, + { id: 5, body: 'quux', published: false, postId: 2, userId: 1 } ] db.refs = [ - {id: 'abcd-1234', url: 'http://example.com', postId: 1, userId: 1} + { id: 'abcd-1234', url: 'http://example.com', postId: 1, userId: 1 } ] db.stringIds = [ - {id: '1234'} + { id: '1234' } ] db.deep = [ @@ -50,27 +49,27 @@ describe('Server', function () { ] db.nested = [ - {resource: {name: 'dewey'}}, - {resource: {name: 'cheatem'}}, - {resource: {name: 'howe'}} + { resource: {name: 'dewey'} }, + { resource: {name: 'cheatem'} }, + { resource: {name: 'howe'} } ] db.list = [ - {id: 1}, - {id: 2}, - {id: 3}, - {id: 4}, - {id: 5}, - {id: 6}, - {id: 7}, - {id: 8}, - {id: 9}, - {id: 10}, - {id: 11}, - {id: 12}, - {id: 13}, - {id: 14}, - {id: 15} + { id: 1 }, + { id: 2 }, + { id: 3 }, + { id: 4 }, + { id: 5 }, + { id: 6 }, + { id: 7 }, + { id: 8 }, + { id: 9 }, + { id: 10 }, + { id: 11 }, + { id: 12 }, + { id: 13 }, + { id: 14 }, + { id: 15 } ] server = jsonServer.create() @@ -83,8 +82,8 @@ describe('Server', function () { server.use(router) }) - describe('GET /db', function () { - it('should respond with json and full database', function (done) { + describe('GET /db', () => { + it('should respond with json and full database', (done) => { request(server) .get('/db') .expect('Content-Type', /json/) @@ -93,8 +92,8 @@ describe('Server', function () { }) }) - describe('GET /:resource', function () { - it('should respond with json and corresponding resources', function (done) { + describe('GET /:resource', () => { + it('should respond with json and corresponding resources', (done) => { request(server) .get('/posts') .set('Origin', 'http://example.com') @@ -105,47 +104,47 @@ describe('Server', function () { .expect(200, done) }) - it('should respond with 404 if resource is not found', function (done) { + it('should respond with 404 if resource is not found', (done) => { request(server) .get('/undefined') .expect(404, done) }) }) - describe('GET /:resource?attr=&attr=', function () { - it('should respond with json and filter resources', function (done) { + describe('GET /:resource?attr=&attr=', () => { + it('should respond with json and filter resources', (done) => { request(server) .get('/comments?postId=1&published=true') .expect('Content-Type', /json/) - .expect([db.comments[0]]) + .expect([ db.comments[0] ]) .expect(200, done) }) - it('should be strict', function (done) { + it('should be strict', (done) => { request(server) .get('/users?tel=123') .expect('Content-Type', /json/) - .expect([db.users[1]]) + .expect([ db.users[1] ]) .expect(200, done) }) - it('should support multiple filters', function (done) { + it('should support multiple filters', (done) => { request(server) .get('/comments?id=1&id=2') .expect('Content-Type', /json/) - .expect([db.comments[0], db.comments[1]]) + .expect([ db.comments[0], db.comments[1] ]) .expect(200, done) }) - it('should support deep filter', function (done) { + it('should support deep filter', (done) => { request(server) .get('/deep?a.b=1') .expect('Content-Type', /json/) - .expect([db.deep[0]]) + .expect([ db.deep[0] ]) .expect(200, done) }) - it('should ignore JSONP query parameters callback and _ ', function (done) { + it('should ignore JSONP query parameters callback and _ ', (done) => { request(server) .get('/comments?callback=1&_=1') .expect('Content-Type', /text/) @@ -153,7 +152,7 @@ describe('Server', function () { .expect(200, done) }) - it('should ignore unknown query parameters', function (done) { + it('should ignore unknown query parameters', (done) => { request(server) .get('/comments?foo=1&bar=2') .expect('Content-Type', /json/) @@ -162,16 +161,16 @@ describe('Server', function () { }) }) - describe('GET /:resource?q=', function () { - it('should respond with json and make a full-text search', function (done) { + describe('GET /:resource?q=', () => { + it('should respond with json and make a full-text search', (done) => { request(server) .get('/tags?q=pho') .expect('Content-Type', /json/) - .expect([db.tags[1], db.tags[2]]) + .expect([ db.tags[1], db.tags[2] ]) .expect(200, done) }) - it('should respond with json and make a deep full-text search', function (done) { + it('should respond with json and make a deep full-text search', (done) => { request(server) .get('/deep?q=1') .expect('Content-Type', /json/) @@ -179,25 +178,25 @@ describe('Server', function () { .expect(200, done) }) - it('should return an empty array when nothing is matched', function (done) { + it('should return an empty array when nothing is matched', (done) => { request(server) .get('/tags?q=nope') .expect('Content-Type', /json/) - .expect([]) + .expect([ ]) .expect(200, done) }) - it('should support other query parameters', function (done) { + it('should support other query parameters', (done) => { request(server) .get('/comments?q=qu&published=true') .expect('Content-Type', /json/) - .expect([db.comments[3]]) + .expect([ db.comments[3] ]) .expect(200, done) }) }) - describe('GET /:resource?_end=', function () { - it('should respond with a sliced array', function (done) { + describe('GET /:resource?_end=', () => { + it('should respond with a sliced array', (done) => { request(server) .get('/comments?_end=2') .expect('Content-Type', /json/) @@ -208,24 +207,24 @@ describe('Server', function () { }) }) - describe('GET /:resource?_sort=', function () { - it('should respond with json and sort on a field', function (done) { + describe('GET /:resource?_sort=', () => { + it('should respond with json and sort on a field', (done) => { request(server) .get('/tags?_sort=body') .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, done) }) - it('should reverse sorting with _order=DESC', function (done) { + it('should reverse sorting with _order=DESC', (done) => { request(server) .get('/tags?_sort=body&_order=DESC') .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, done) }) - it('should sort on numerical field', function (done) { + it('should sort on numerical field', (done) => { request(server) .get('/posts?_sort=id&_order=DESC') .expect('Content-Type', /json/) @@ -233,54 +232,54 @@ describe('Server', function () { .expect(200, done) }) - it('should sort on nested field', function (done) { + it('should sort on nested field', (done) => { request(server) .get('/nested?_sort=resource.name') .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, done) }) }) - describe('GET /:resource?_start=&_end=', function () { - it('should respond with a sliced array', function (done) { + describe('GET /:resource?_start=&_end=', () => { + it('should respond with a sliced array', (done) => { request(server) .get('/comments?_start=1&_end=2') .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(db.comments.slice(1, 2)) .expect(200, done) }) }) - describe('GET /:resource?_start=&_limit=', function () { - it('should respond with a limited array', function (done) { + describe('GET /:resource?_start=&_limit=', () => { + it('should respond with a limited array', (done) => { request(server) .get('/comments?_start=1&_limit=1') .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(db.comments.slice(1, 2)) .expect(200, done) }) }) - describe('GET /:resource?_page=', function () { - it('should paginate', function (done) { + describe('GET /:resource?_page=', () => { + it('should paginate', (done) => { request(server) .get('/list?_page=2') .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') .expect(db.list.slice(10, 20)) .expect(200, done) }) }) - describe('GET /:resource?_page=&_limit=', function () { - it('should paginate with a custom limit', function (done) { - var link = [ + describe('GET /:resource?_page=&_limit=', () => { + it('should paginate with a custom limit', (done) => { + const link = [ '; rel="first"', '; rel="prev"', '; rel="next"', @@ -298,8 +297,8 @@ describe('Server', function () { }) }) - describe('GET /:resource?attr_gte=&attr_lte=', function () { - it('should respond with a limited array', function (done) { + describe('GET /:resource?attr_gte=&attr_lte=', () => { + it('should respond with a limited array', (done) => { request(server) .get('/comments?id_gte=2&id_lte=3') .expect('Content-Type', /json/) @@ -308,8 +307,8 @@ describe('Server', function () { }) }) - describe('GET /:resource?attr_ne=', function () { - it('should respond with a limited array', function (done) { + describe('GET /:resource?attr_ne=', () => { + it('should respond with a limited array', (done) => { request(server) .get('/comments?id_ne=1') .expect('Content-Type', /json/) @@ -318,8 +317,8 @@ describe('Server', function () { }) }) - describe('GET /:resource?attr_like=', function () { - it('should respond with an array that matches the like operator (case insensitive)', function (done) { + describe('GET /:resource?attr_like=', () => { + it('should respond with an array that matches the like operator (case insensitive)', (done) => { request(server) .get('/tags?body_like=photo') .expect('Content-Type', /json/) @@ -331,8 +330,8 @@ describe('Server', function () { }) }) - describe('GET /:parent/:parentId/:resource', function () { - it('should respond with json and corresponding nested resources', function (done) { + describe('GET /:parent/:parentId/:resource', () => { + it('should respond with json and corresponding nested resources', (done) => { request(server) .get('/posts/1/comments') .expect('Content-Type', /json/) @@ -344,8 +343,8 @@ describe('Server', function () { }) }) - describe('GET /:resource/:id', function () { - it('should respond with json and corresponding resource', function (done) { + describe('GET /:resource/:id', () => { + it('should respond with json and corresponding resource', (done) => { request(server) .get('/posts/1') .expect('Content-Type', /json/) @@ -353,7 +352,7 @@ describe('Server', function () { .expect(200, done) }) - it('should support string id, respond with json and corresponding resource', function (done) { + it('should support string id, respond with json and corresponding resource', (done) => { request(server) .get('/refs/abcd-1234') .expect('Content-Type', /json/) @@ -361,7 +360,7 @@ describe('Server', function () { .expect(200, done) }) - it('should support integer id as string', function (done) { + it('should support integer id as string', (done) => { request(server) .get('/stringIds/1234') .expect('Content-Type', /json/) @@ -369,7 +368,7 @@ describe('Server', function () { .expect(200, done) }) - it('should respond with 404 if resource is not found', function (done) { + it('should respond with 404 if resource is not found', (done) => { request(server) .get('/posts/9001') .expect('Content-Type', /json/) @@ -378,11 +377,11 @@ describe('Server', function () { }) }) - describe('GET /:resource?_embed=', function () { - it('should respond with corresponding resources and embedded resources', function (done) { - var posts = _.cloneDeep(db.posts) - posts[0].comments = [db.comments[0], db.comments[1]] - posts[1].comments = [db.comments[2], db.comments[3], db.comments[4]] + describe('GET /:resource?_embed=', () => { + it('should respond with corresponding resources and embedded resources', (done) => { + const posts = _.cloneDeep(db.posts) + posts[0].comments = [ db.comments[0], db.comments[1] ] + posts[1].comments = [ db.comments[2], db.comments[3], db.comments[4] ] request(server) .get('/posts?_embed=comments') .expect('Content-Type', /json/) @@ -391,12 +390,12 @@ describe('Server', function () { }) }) - describe('GET /:resource?_embed&_embed=', function () { - it('should respond with corresponding resources and embedded resources', function (done) { - var posts = _.cloneDeep(db.posts) - posts[0].comments = [db.comments[0], db.comments[1]] - posts[0].refs = [db.refs[0]] - posts[1].comments = [db.comments[2], db.comments[3], db.comments[4]] + describe('GET /:resource?_embed&_embed=', () => { + it('should respond with corresponding resources and embedded resources', (done) => { + const posts = _.cloneDeep(db.posts) + posts[0].comments = [ db.comments[0], db.comments[1] ] + posts[0].refs = [ db.refs[0] ] + posts[1].comments = [ db.comments[2], db.comments[3], db.comments[4] ] posts[1].refs = [] request(server) .get('/posts?_embed=comments&_embed=refs') @@ -406,10 +405,10 @@ describe('Server', function () { }) }) - describe('GET /:resource/:id?_embed=', function () { - it('should respond with corresponding resources and embedded resources', function (done) { - var post = _.cloneDeep(db.posts[0]) - post.comments = [db.comments[0], db.comments[1]] + describe('GET /:resource/:id?_embed=', () => { + it('should respond with corresponding resources and embedded resources', (done) => { + const post = _.cloneDeep(db.posts[0]) + post.comments = [ db.comments[0], db.comments[1] ] request(server) .get('/posts/1?_embed=comments') .expect('Content-Type', /json/) @@ -418,10 +417,10 @@ describe('Server', function () { }) }) - describe('GET /:resource/:id?_embed=&_embed=', function () { - it('should respond with corresponding resource and embedded resources', function (done) { - var post = _.cloneDeep(db.posts[0]) - post.comments = [db.comments[0], db.comments[1]] + describe('GET /:resource/:id?_embed=&_embed=', () => { + it('should respond with corresponding resource and embedded resources', (done) => { + const post = _.cloneDeep(db.posts[0]) + post.comments = [ db.comments[0], db.comments[1] ] post.refs = [db.refs[0]] request(server) .get('/posts/1?_embed=comments&_embed=refs') @@ -431,9 +430,9 @@ describe('Server', function () { }) }) - describe('GET /:resource?_expand=', function () { - it('should respond with corresponding resource and expanded inner resources', function (done) { - var refs = _.cloneDeep(db.refs) + describe('GET /:resource?_expand=', () => { + it('should respond with corresponding resource and expanded inner resources', (done) => { + const refs = _.cloneDeep(db.refs) refs[0].post = db.posts[0] request(server) .get('/refs?_expand=post') @@ -443,9 +442,9 @@ describe('Server', function () { }) }) - describe('GET /:resource/:id?_expand=', function () { - it('should respond with corresponding resource and expanded inner resources', function (done) { - var comment = _.cloneDeep(db.comments[0]) + describe('GET /:resource/:id?_expand=', () => { + it('should respond with corresponding resource and expanded inner resources', (done) => { + const comment = _.cloneDeep(db.comments[0]) comment.post = db.posts[0] request(server) .get('/comments/1?_expand=post') @@ -455,9 +454,9 @@ describe('Server', function () { }) }) - describe('GET /:resource?_expand=&_expand', function () { - it('should respond with corresponding resource and expanded inner resources', function (done) { - var refs = _.cloneDeep(db.refs) + describe('GET /:resource?_expand=&_expand', () => { + it('should respond with corresponding resource and expanded inner resources', (done) => { + const refs = _.cloneDeep(db.refs) refs[0].post = db.posts[0] refs[0].user = db.users[0] request(server) @@ -468,9 +467,9 @@ describe('Server', function () { }) }) - describe('GET /:resource/:id?_expand=&_expand=', function () { - it('should respond with corresponding resource and expanded inner resources', function (done) { - var comments = db.comments[0] + describe('GET /:resource/:id?_expand=&_expand=', () => { + it('should respond with corresponding resource and expanded inner resources', (done) => { + const comments = db.comments[0] comments.post = db.posts[0] comments.user = db.users[0] request(server) @@ -481,16 +480,16 @@ describe('Server', function () { }) }) - describe('POST /:resource', function () { + describe('POST /:resource', () => { it('should respond with json, create a resource and increment id', - function (done) { + (done) => { request(server) .post('/posts') .send({body: 'foo', booleanValue: true, integerValue: 1}) .expect('Content-Type', /json/) .expect({id: 3, body: 'foo', booleanValue: true, integerValue: 1}) .expect(201) - .end(function (err, res) { + .end((err, res) => { if (err) return done(err) assert.equal(db.posts.length, 3) done() @@ -499,7 +498,7 @@ describe('Server', function () { ) it('should support x-www-form-urlencoded', - function (done) { + (done) => { request(server) .post('/posts') .type('form') @@ -508,7 +507,7 @@ describe('Server', function () { // x-www-form-urlencoded will convert to string .expect({id: 3, body: 'foo', booleanValue: 'true', integerValue: '1'}) .expect(201) - .end(function (err, res) { + .end((err, res) => { if (err) return done(err) assert.equal(db.posts.length, 3) done() @@ -517,13 +516,13 @@ describe('Server', function () { ) it('should respond with json, create a resource and generate string id', - function (done) { + (done) => { request(server) .post('/refs') .send({url: 'http://foo.com', postId: '1'}) .expect('Content-Type', /json/) .expect(201) - .end(function (err, res) { + .end((err, res) => { if (err) return done(err) assert.equal(db.refs.length, 2) done() @@ -531,8 +530,8 @@ describe('Server', function () { }) }) - describe('POST /:parent/:parentId/:resource', function () { - it('should respond with json and set parentId', function (done) { + describe('POST /:parent/:parentId/:resource', () => { + it('should respond with json and set parentId', (done) => { request(server) .post('/posts/1/comments') .send({body: 'foo'}) @@ -542,8 +541,8 @@ describe('Server', function () { }) }) - describe('PUT /:resource/:id', function () { - it('should respond with json and replace resource', function (done) { + describe('PUT /:resource/:id', () => { + it('should respond with json and replace resource', (done) => { var post = {id: 1, booleanValue: true, integerValue: 1} request(server) .put('/posts/1') @@ -552,7 +551,7 @@ describe('Server', function () { .expect('Content-Type', /json/) .expect(post) .expect(200) - .end(function (err, res) { + .end((err, res) => { if (err) return done(err) // assert it was created in database too assert.deepEqual(db.posts[0], post) @@ -560,7 +559,7 @@ describe('Server', function () { }) }) - it('should respond with 404 if resource is not found', function (done) { + it('should respond with 404 if resource is not found', (done) => { request(server) .put('/posts/9001') .send({id: 1, body: 'bar'}) @@ -570,15 +569,15 @@ describe('Server', function () { }) }) - describe('PATCH /:resource/:id', function () { - it('should respond with json and update resource', function (done) { + describe('PATCH /:resource/:id', () => { + it('should respond with json and update resource', (done) => { request(server) .patch('/posts/1') .send({body: 'bar'}) .expect('Content-Type', /json/) .expect({id: 1, body: 'bar'}) .expect(200) - .end(function (err, res) { + .end((err, res) => { if (err) return done(err) // assert it was created in database too assert.deepEqual(db.posts[0], {id: 1, body: 'bar'}) @@ -586,7 +585,7 @@ describe('Server', function () { }) }) - it('should respond with 404 if resource is not found', function (done) { + it('should respond with 404 if resource is not found', (done) => { request(server) .patch('/posts/9001') .send({body: 'bar'}) @@ -596,13 +595,13 @@ describe('Server', function () { }) }) - describe('DELETE /:resource/:id', function () { - it('should respond with empty data, destroy resource and dependent resources', function (done) { + describe('DELETE /:resource/:id', () => { + it('should respond with empty data, destroy resource and dependent resources', (done) => { request(server) .del('/posts/1') .expect({}) .expect(200) - .end(function (err, res) { + .end((err, res) => { if (err) return done(err) assert.equal(db.posts.length, 1) assert.equal(db.comments.length, 3) @@ -610,7 +609,7 @@ describe('Server', function () { }) }) - it('should respond with 404 if resource is not found', function (done) { + it('should respond with 404 if resource is not found', (done) => { request(server) .del('/posts/9001') .expect('Content-Type', /json/) @@ -619,9 +618,9 @@ describe('Server', function () { }) }) - describe('Static routes', function () { - describe('GET /', function () { - it('should respond with html', function (done) { + describe('Static routes', () => { + describe('GET /', () => { + it('should respond with html', (done) => { request(server) .get('/') .expect(/You're successfully running JSON Server/) @@ -629,8 +628,8 @@ describe('Server', function () { }) }) - describe('GET /stylesheets/style.css', function () { - it('should respond with css', function (done) { + describe('GET /stylesheets/style.css', () => { + it('should respond with css', (done) => { request(server) .get('/stylesheets/style.css') .expect('Content-Type', /css/) @@ -639,14 +638,14 @@ describe('Server', function () { }) }) - describe('Database state', function () { - it('should be accessible', function () { + describe('Database state', () => { + it('should be accessible', () => { assert(router.db.getState()) }) }) - describe('Responses', function () { - it('should have no cache headers (for IE)', function (done) { + describe('Responses', () => { + it('should have no cache headers (for IE)', (done) => { request(server) .get('/db') .expect('Cache-Control', 'no-cache') @@ -656,15 +655,15 @@ describe('Server', function () { }) }) - describe('Rewriter', function () { - it('should rewrite using prefix', function (done) { + describe('Rewriter', () => { + it('should rewrite using prefix', (done) => { request(server) .get('/api/posts/1') .expect(db.posts[0]) .end(done) }) - it('should rewrite using params', function (done) { + it('should rewrite using params', (done) => { request(server) .get('/blog/posts/1/show') .expect(db.posts[0]) @@ -672,16 +671,16 @@ describe('Server', function () { }) }) - describe('router.render', function (done) { - beforeEach(function () { - router.render = function (req, res) { + describe('router.render', (done) => { + beforeEach(() => { + router.render = (req, res) => { res.jsonp({ data: res.locals.data }) } }) - it('should be possible to wrap response', function (done) { + it('should be possible to wrap response', (done) => { request(server) .get('/posts/1') .expect('Content-Type', /json/) @@ -690,8 +689,8 @@ describe('Server', function () { }) }) - describe('router.db._.id', function (done) { - beforeEach(function () { + describe('router.db._.id', (done) => { + beforeEach(() => { router.db.setState({ posts: [ { _id: 1 } @@ -701,7 +700,7 @@ describe('Server', function () { router.db._.id = '_id' }) - it('should be possible to GET using a different id property', function (done) { + it('should be possible to GET using a different id property', (done) => { request(server) .get('/posts/1') .expect('Content-Type', /json/) @@ -709,12 +708,12 @@ describe('Server', function () { .expect(200, done) }) - it('should be possible to POST using a different id property', function (done) { + it('should be possible to POST using a different id property', (done) => { request(server) .post('/posts') .send({ body: 'hello' }) .expect('Content-Type', /json/) - .expect({_id: 2, body: 'hello'}) + .expect({ _id: 2, body: 'hello' }) .expect(201, done) }) }) diff --git a/test/server/singular.js b/test/server/singular.js index 617bc37..509a478 100644 --- a/test/server/singular.js +++ b/test/server/singular.js @@ -1,11 +1,10 @@ -var request = require('supertest') -var jsonServer = require('../../src/server') +const request = require('supertest') +const jsonServer = require('../../src/server') -/* global beforeEach, describe, it */ describe('Server', function () { - var server - var router - var db + let server + let router + let db beforeEach(function () { db = {} @@ -32,7 +31,7 @@ describe('Server', function () { describe('POST /:resource', function () { it('should create resource', function (done) { - var user = { name: 'bar' } + const user = { name: 'bar' } request(server) .post('/user') .send(user) @@ -43,7 +42,7 @@ describe('Server', function () { describe('PUT /:resource', function () { it('should update resource', function (done) { - var user = { name: 'bar' } + const user = { name: 'bar' } request(server) .put('/user') .send(user) diff --git a/test/server/utils.js b/test/server/utils.js index 8332a13..a611db2 100644 --- a/test/server/utils.js +++ b/test/server/utils.js @@ -1,12 +1,10 @@ -var assert = require('assert') -var utils = require('../../src/server/utils') - -/* global describe, it */ +const assert = require('assert') +const utils = require('../../src/server/utils') describe('utils', function () { describe('getPage', function () { - var array = [1, 2, 3, 4, 5] - var perPage = 2 + const array = [1, 2, 3, 4, 5] + const perPage = 2 it('should return first page', function () { assert.deepEqual(