Add option to plural routes

This commit is contained in:
typicode
2018-12-25 23:29:08 +01:00
parent aef028779f
commit bbc2011ec3
3 changed files with 132 additions and 21 deletions

View File

@ -0,0 +1,81 @@
const assert = require('assert')
const request = require('supertest')
const jsonServer = require('../../src/server')
describe('Fake server', () => {
let server
let router
let db
beforeEach(() => {
db = {}
db.posts = [{ id: 1, body: 'foo' }, { id: 2, body: 'bar' }]
server = jsonServer.create()
router = jsonServer.router(db, { _isFake: true })
server.use(jsonServer.defaults())
server.use(router)
})
describe('POST /:resource', () => {
test('should respond with json, create a resource and increment id', async () => {
await request(server)
.post('/posts')
.send({ body: 'foo', booleanValue: true, integerValue: 1 })
.expect('Access-Control-Expose-Headers', 'Location')
.expect('Location', /posts\/3$/)
.expect('Content-Type', /json/)
.expect({ id: 3, body: 'foo', booleanValue: true, integerValue: 1 })
.expect(201)
// assert it was not created in database
assert.equal(db.posts.length, 2)
})
})
describe('PUT /:resource/:id', () => {
test('should respond with json and replace resource', async () => {
const post = { id: 1, booleanValue: true, integerValue: 1 }
const res = await request(server)
.put('/posts/1')
.set('Accept', 'application/json')
// body property omitted to test that the resource is replaced
.send(post)
.expect('Content-Type', /json/)
.expect(post)
.expect(200)
// TODO find a "supertest" way to test this
// https://github.com/typicode/json-server/issues/396
assert.deepStrictEqual(res.body, post)
// assert it was not created in database
assert.notDeepStrictEqual(db.posts[0], post)
})
})
describe('PATCH /:resource/:id', () => {
test('should respond with json and update resource', async () => {
const partial = { body: 'bar' }
const post = { id: 1, body: 'bar' }
const res = await request(server)
.patch('/posts/1')
.send(partial)
.expect('Content-Type', /json/)
.expect(post)
.expect(200)
assert.deepStrictEqual(res.body, post)
// assert it was not created in database
assert.notDeepStrictEqual(db.posts[0], post)
})
})
describe('DELETE /:resource/:id', () => {
test('should respond with empty data, destroy resource and dependent resources', async () => {
await request(server)
.del('/posts/1')
.expect({})
.expect(200)
// assert it was not created in database
assert.equal(db.posts.length, 2)
})
})
})

View File

@ -12,7 +12,7 @@ const nested = require('./nested')
const singular = require('./singular') const singular = require('./singular')
const mixins = require('../mixins') const mixins = require('../mixins')
module.exports = (db, opts = { foreignKeySuffix: 'Id' }) => { module.exports = (db, opts = { foreignKeySuffix: 'Id', _isFake: false }) => {
if (typeof db === 'string') { if (typeof db === 'string') {
db = low(new FileSync(db)) db = low(new FileSync(db))
} else if (!_.has(db, '__chain__') || !_.has(db, '__wrapped__')) { } else if (!_.has(db, '__chain__') || !_.has(db, '__wrapped__')) {

View File

@ -255,10 +255,19 @@ module.exports = (db, name, opts) => {
// POST /name // POST /name
function create(req, res, next) { function create(req, res, next) {
const resource = db let resource
.get(name) if (opts._isFake) {
.insert(req.body) const id = db
.value() .get(name)
.createId()
.value()
resource = { ...req.body, id }
} else {
resource = db
.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}`)
@ -273,14 +282,29 @@ module.exports = (db, name, opts) => {
// PATCH /name/:id // PATCH /name/:id
function update(req, res, next) { function update(req, res, next) {
const id = req.params.id const id = req.params.id
let chain = db.get(name) let resource
chain = if (opts._isFake) {
req.method === 'PATCH' resource = db
? chain.updateById(id, req.body) .get(name)
: chain.replaceById(id, req.body) .getById(id)
.value()
const resource = chain.value() if (req.method === 'PATCH') {
resource = { ...resource, ...req.body }
} else {
resource = { ...req.body, id: resource.id }
}
} else {
let chain = db.get(name)
chain =
req.method === 'PATCH'
? chain.updateById(id, req.body)
: chain.replaceById(id, req.body)
resource = chain.value()
}
if (resource) { if (resource) {
res.locals.data = resource res.locals.data = resource
@ -291,18 +315,24 @@ module.exports = (db, name, opts) => {
// DELETE /name/:id // DELETE /name/:id
function destroy(req, res, next) { function destroy(req, res, next) {
const resource = db let resource
.get(name)
.removeById(req.params.id)
.value()
// Remove dependents documents if (opts._isFake) {
const removable = db._.getRemovable(db.getState(), opts) resource = db.get(name).value()
removable.forEach(item => { } else {
db.get(item.name) resource = db
.removeById(item.id) .get(name)
.removeById(req.params.id)
.value() .value()
})
// Remove dependents documents
const removable = db._.getRemovable(db.getState(), opts)
removable.forEach(item => {
db.get(item.name)
.removeById(item.id)
.value()
})
}
if (resource) { if (resource) {
res.locals.data = {} res.locals.data = {}