UNPKG

merest

Version:

Express based REST-full API for Mongoose models

607 lines (567 loc) 18.2 kB
var async = require('async'); var mongoose = require('mongoose'); var request = require("request"); var util = require("util"); var assert = require('assert'); var app = require('../setup/app'); var db = require('../setup/db'); var models = require('../models'); var api = require("../../lib"); var testPort = 30023; var testUrl = 'http://127.0.0.1:' + testPort; describe("Restricting access to documents by filtering (exposing only Poets)", function (done) { beforeEach(function (done) { async.waterfall([ app.init, db.init, db.fixtures.bind(null, { Person: '../fixtures/people' }), function (next) { var modelAPI = new api.ModelAPIExpress(); modelAPI.expose(models.Person, { filter: {isPoet: true}, create: { middlewares: function (req, res, next) { if (req.body.isPoet === false) { return next(new api.ModelAPIError( 422, 'The Person is not a poet' )); } return next(); } } }); app.use('/api/v1/', modelAPI); app.listen(testPort, next); } ], done); }); afterEach(function (done) { async.waterfall([db.close, app.close], done) }); it("POST /api/v1/people 201 -- create a Poet", function (done){ request.post({ url: util.format('%s/api/v1/people', testUrl), json: { firstName: 'John', lastName: 'Johnson', email: "john.johnson@i.ua", isPoet: true } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 201); assert.ok(body._id); assert.equal(body.firstName, 'John'); assert.equal(body.lastName, 'Johnson'); assert.equal(body.email, "john.johnson@i.ua"); models.Person.count(function(err, res) { assert.equal(res, 5); done(); }); }); }); it("POST /api/v1/people 422 -- create not a Poet", function (done){ request.post({ url: util.format('%s/api/v1/people', testUrl), json: { firstName: 'John', lastName: 'Johnson', email: "john.johnson@i.ua", isPoet: false } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 422); assert.equal(body.message, "The Person is not a poet"); done(); }); }); it("GET /api/v1/people 200 -- getting for people (only poets)", function (done){ request.get({ url: util.format('%s/api/v1/people', testUrl) }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 200); if (typeof(body) == "string") { body = JSON.parse(body); } assert.equal(body.length, 2); body.forEach(function(p) { assert.equal(p.isPoet, true); }); done(); }); }); it("GET /api/v1/people/:id 200 -- get a specific Poet", function(done) { models.Person.findOne({isPoet: true}, function (err, p) { assert.ok(!err); assert.ok(p); assert.ok(p._id); request.get({ url: util.format('%s/api/v1/people/%s', testUrl, p._id) }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 200); if (typeof(body) == "string") { body = JSON.parse(body); } assert.equal(body.firstName, p.firstName); assert.equal(body.lastName, p.lastName); assert.equal(body.email, p.email.toLowerCase()); assert.ok(body.isPoet); done(); }); }); }); it("GET /api/v1/people/:id 404 -- get a specific not Poet", function(done) { models.Person.findOne({isPoet: false}, function (err, p) { assert.ok(!err); assert.ok(p); assert.ok(p._id); request.get({ url: util.format('%s/api/v1/people/%s', testUrl, p._id) }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 404); done(); }); }); }); it("POST /api/v1/people/:id 200 -- update a specific Poet", function(done) { models.Person.findOne({isPoet: true}, function (err, p) { assert.ok(!err); assert.ok(p._id); request.post({ url: util.format('%s/api/v1/people/%s', testUrl, p._id), json: { email: "new.mail@server.com" } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 200); if (typeof(body) == "string") { body = JSON.parse(body); } assert.equal(body.firstName, p.firstName); assert.equal(body.lastName, p.lastName); assert.equal(body.email, "new.mail@server.com"); models.Person.findById(p._id, function (err, p1) { assert.ok(!err); assert.equal(p1.firstName, p.firstName); assert.equal(p1.lastName, p.lastName); assert.equal(p1.email, "new.mail@server.com"); done(); }); }); }); }); it("POST /api/v1/people/:id 404 -- update a specific not Poet", function(done) { models.Person.findOne({isPoet: false}, function (err, p) { assert.ok(!err); assert.ok(p._id); request.post({ url: util.format('%s/api/v1/people/%s', testUrl, p._id), json: { email: "new.mail@server.com" } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 404); done(); }); }); }); it("DELETE /api/v1/people/:id 200 -- deleting a Poet", function(done) { models.Person.findOne({isPoet: true}, function (err, p) { assert.ok(!err); assert.ok(p._id); request.post({ url: util.format('%s/api/v1/people/%s', testUrl, p._id), headers: { "X-HTTP-Method-Override": "DELETE" } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 200); if (typeof(body) == "string") { body = JSON.parse(body); } assert.deepEqual(body, {}); models.Person.count(function(err, res) { assert.equal(res, 3); done(); }); }); }); }); it("DELETE /api/v1/people/:id 404 -- deleting not a Poet", function(done) { models.Person.findOne({isPoet: false}, function (err, p) { assert.ok(!err); assert.ok(p._id); request.post({ url: util.format('%s/api/v1/people/%s', testUrl, p._id), headers: { "X-HTTP-Method-Override": "DELETE" } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 404); done(); }); }); }); }); describe("Restricting access to documents by dynamic filtering (exposing only Poets if requires in HTTP-header)", function (done) { beforeEach(function (done) { async.waterfall([ app.init, db.init, db.fixtures.bind(null, { Person: '../fixtures/people' }), function (next) { var modelAPI = new api.ModelAPIExpress(); modelAPI.expose(models.Person, { expose: {Reverse: 'get'}, filter: function(req) { if (req.headers['x-poet-control'] === 'YES') { return {isPoet: true} } return {}; }, create: { middlewares: function (req, res, next) { if (req.body.isPoet === false && req.headers['x-poet-control'] === 'YES') { return next(new api.ModelAPIError( 422, 'The Person is not a poet' )); } return next(); } } }); app.use('/api/v1/', modelAPI); app.listen(testPort, next); } ], done); }); afterEach(function (done) { async.waterfall([db.close, app.close], done) }); it("POST /api/v1/people 201 -- create a Poet", function (done){ request.post({ url: util.format('%s/api/v1/people', testUrl), headers: { "x-poet-control": "YES" }, json: { firstName: 'John', lastName: 'Johnson', email: "john.johnson@i.ua", isPoet: true } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 201); assert.ok(body._id); assert.equal(body.firstName, 'John'); assert.equal(body.lastName, 'Johnson'); assert.equal(body.email, "john.johnson@i.ua"); models.Person.count(function(err, res) { assert.equal(res, 5); done(); }); }); }); it("POST /api/v1/people 422 -- create not a Poet", function (done){ request.post({ url: util.format('%s/api/v1/people', testUrl), headers: { "x-poet-control": "YES" }, json: { firstName: 'John', lastName: 'Johnson', email: "john.johnson@i.ua", isPoet: false } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 422); assert.equal(body.message, "The Person is not a poet"); done(); }); }); it("POST /api/v1/people 200 -- create not a Poet (poet control off)", function (done){ request.post({ url: util.format('%s/api/v1/people', testUrl), headers: { "x-poet-control": "NO" }, json: { firstName: 'John', lastName: 'Johnson', email: "john.johnson@i.ua", isPoet: false } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 201); done(); }); }); it("GET /api/v1/people 200 -- getting for people (only poets)", function (done){ request.get({ url: util.format('%s/api/v1/people', testUrl), headers: { "x-poet-control": "YES" } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 200); if (typeof(body) == "string") { body = JSON.parse(body); } assert.equal(body.length, 2); body.forEach(function(p) { assert.equal(p.isPoet, true); }); done(); }); }); it("GET /api/v1/people 200 -- getting for people (poet control off)", function (done){ request.get({ url: util.format('%s/api/v1/people', testUrl), headers: { "x-poet-control": "NO" } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 200); if (typeof(body) == "string") { body = JSON.parse(body); }; var isPoet = false; var isNotPoet = false; assert.equal(body.length, 4); body.forEach(function(p) { isPoet = isPoet || p.isPoet; isNotPoet = isNotPoet || (p.isPoet === false); }); assert.ok(isPoet); assert.ok(isNotPoet); done(); }); }); it("GET /api/v1/people/:id 200 -- get a specific Poet", function(done) { models.Person.findOne({isPoet: true}, function (err, p) { assert.ok(!err); assert.ok(p); assert.ok(p._id); request.get({ url: util.format('%s/api/v1/people/%s', testUrl, p._id), headers: { "x-poet-control": "YES" } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 200); if (typeof(body) == "string") { body = JSON.parse(body); } assert.equal(body.firstName, p.firstName); assert.equal(body.lastName, p.lastName); assert.equal(body.email, p.email.toLowerCase()); assert.ok(body.isPoet); done(); }); }); }); it("GET /api/v1/people/:id/reverse 200 -- calling instance method of a specific Poet", function(done) { models.Person.findOne({isPoet: true}, function (err, p) { assert.ok(!err); assert.ok(p); assert.ok(p._id); request.get({ url: util.format('%s/api/v1/people/%s/reverse', testUrl, p._id), headers: { "x-poet-control": "YES" } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 200); if (typeof(body) == "string") { body = JSON.parse(body); } assert.equal(body.status, "Ok"); models.Person.findById(p._id, function (err, p1) { assert.ok(!err); assert.equal(p1.firstName, p.firstName.split("").reverse().join("")); assert.equal(p1.lastName, p.lastName.split("").reverse().join("")); done(); }); }); }); }); it("GET /api/v1/people/:id 404 -- get a specific not Poet", function(done) { models.Person.findOne({isPoet: false}, function (err, p) { assert.ok(!err); assert.ok(p); assert.ok(p._id); request.get({ url: util.format('%s/api/v1/people/%s', testUrl, p._id), headers: { "x-poet-control": "YES" } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 404); done(); }); }); }); it("GET /api/v1/people/:id 200 -- get a specific not Poet (poet control off)", function(done) { models.Person.findOne({isPoet: false}, function (err, p) { assert.ok(!err); assert.ok(p); assert.ok(p._id); request.get({ url: util.format('%s/api/v1/people/%s', testUrl, p._id), headers: { "x-poet-control": "NO" } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 200); done(); }); }); }); it("POST /api/v1/people/:id 200 -- update a specific Poet", function(done) { models.Person.findOne({isPoet: true}, function (err, p) { assert.ok(!err); assert.ok(p._id); request.post({ url: util.format('%s/api/v1/people/%s', testUrl, p._id), headers: { "x-poet-control": "YES" }, json: { email: "new.mail@server.com" } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 200); if (typeof(body) == "string") { body = JSON.parse(body); } assert.equal(body.firstName, p.firstName); assert.equal(body.lastName, p.lastName); assert.equal(body.email, "new.mail@server.com"); models.Person.findById(p._id, function (err, p1) { assert.ok(!err); assert.equal(p1.firstName, p.firstName); assert.equal(p1.lastName, p.lastName); assert.equal(p1.email, "new.mail@server.com"); done(); }); }); }); }); it("POST /api/v1/people/:id 404 -- update a specific not Poet", function(done) { models.Person.findOne({isPoet: false}, function (err, p) { assert.ok(!err); assert.ok(p._id); request.post({ url: util.format('%s/api/v1/people/%s', testUrl, p._id), headers: { "x-poet-control": "YES" }, json: { email: "new.mail@server.com" } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 404); done(); }); }); }); it("POST /api/v1/people/:id 200 -- update a specific not Poet (poet control off)", function(done) { models.Person.findOne({isPoet: false}, function (err, p) { assert.ok(!err); assert.ok(p._id); request.post({ url: util.format('%s/api/v1/people/%s', testUrl, p._id), headers: { "x-poet-control": "NO" }, json: { email: "new.mail@server.com" } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 200); done(); }); }); }); it("DELETE /api/v1/people/:id 200 -- deleting a Poet", function(done) { models.Person.findOne({isPoet: true}, function (err, p) { assert.ok(!err); assert.ok(p._id); request.post({ url: util.format('%s/api/v1/people/%s', testUrl, p._id), headers: { "X-HTTP-Method-Override": "DELETE", "x-poet-control": "YES" } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 200); if (typeof(body) == "string") { body = JSON.parse(body); } assert.deepEqual(body, {}); models.Person.count(function(err, res) { assert.equal(res, 3); done(); }); }); }); }); it("DELETE /api/v1/people/:id 404 -- deleting not a Poet", function(done) { models.Person.findOne({isPoet: false}, function (err, p) { assert.ok(!err); assert.ok(p._id); request.post({ url: util.format('%s/api/v1/people/%s', testUrl, p._id), headers: { "X-HTTP-Method-Override": "DELETE", "x-poet-control": "YES" } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 404); done(); }); }); }); it("DELETE /api/v1/people/:id 200 -- deleting not a Poet (poet control off)", function(done) { models.Person.findOne({isPoet: false}, function (err, p) { assert.ok(!err); assert.ok(p._id); request.post({ url: util.format('%s/api/v1/people/%s', testUrl, p._id), headers: { "X-HTTP-Method-Override": "DELETE", "x-poet-control": "NO" } }, function (err, res, body) { assert.ok(!err); assert.equal(res.statusCode, 200); done(); }); }); }); });