diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 998ca5620..26866c21d 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -169,14 +169,14 @@ module.exports = function (grunt) { }, src: [ 'server/**/*.js', - '!server/**/*.spec.js' + '!server/**/*.{spec,e2e}.js' ] }, serverTest: { options: { jshintrc: 'server/.jshintrc-spec' }, - src: ['server/**/*.spec.js'] + src: ['server/**/*.{spec,e2e}.js'] }, all: [ '<%%= yeoman.client %>/{app,components}/**/*.js', @@ -486,9 +486,60 @@ module.exports = function (grunt) { mochaTest: { options: { - reporter: 'spec' + reporter: 'spec', + require: 'mocha.conf.js' }, - src: ['server/**/*.spec.js'] + unit: { + src: ['server/**/*.spec.js'] + }, + e2e: { + src: ['server/**/*.e2e.js'] + } + }, + + mocha_istanbul: { + unit: { + options: { + excludes: [ + '**/*.spec.js', + '**/*.mock.js', + '**/*.e2e.js' + ], + reporter: 'spec', + require: ['mocha.conf.js'], + mask: '**/*.spec.js', + coverageFolder: 'coverage/unit' + }, + src: 'server' + }, + e2e: { + options: { + excludes: [ + '**/*.spec.js', + '**/*.mock.js', + '**/*.e2e.js' + ], + reporter: 'spec', + require: ['mocha.conf.js'], + mask: '**/*.e2e.js', + coverageFolder: 'coverage/e2e' + }, + src: 'server' + } + }, + + istanbul_check_coverage: { + default: { + options: { + coverageFolder: 'coverage/*', + check: { + lines: 80, + statements: 80, + branches: 80, + functions: 80 + } + } + } }, protractor: { @@ -769,7 +820,8 @@ module.exports = function (grunt) { return grunt.task.run([ 'env:all', 'env:test', - 'mochaTest' + 'mochaTest:unit', + 'mochaTest:e2e' ]); } @@ -804,6 +856,41 @@ module.exports = function (grunt) { ]); } + else if (target === 'coverage') { + + if (option === 'unit') { + return grunt.task.run([ + 'env:all', + 'env:test', + 'mocha_istanbul:unit' + ]); + } + + else if (option === 'e2e') { + return grunt.task.run([ + 'env:all', + 'env:test', + 'mocha_istanbul:e2e' + ]); + } + + else if (option === 'check') { + return grunt.task.run([ + 'istanbul_check_coverage' + ]); + } + + else { + return grunt.task.run([ + 'env:all', + 'env:test', + 'mocha_istanbul', + 'istanbul_check_coverage' + ]); + } + + } + else grunt.task.run([ 'test:server', 'test:client' diff --git a/app/templates/_package.json b/app/templates/_package.json index e32849740..9dfdadc5d 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -30,6 +30,7 @@ "socketio-jwt": "^2.0.2"<% } %> }, "devDependencies": { + "chai-as-promised": "^4.1.1", "grunt": "~0.4.4", "grunt-autoprefixer": "~0.7.2", "grunt-wiredep": "~1.8.0", @@ -61,7 +62,8 @@ "grunt-asset-injector": "^0.1.0", "grunt-karma": "~0.8.2", "grunt-build-control": "DaftMonk/grunt-build-control", - "grunt-mocha-test": "~0.10.2",<% if(filters.sass) { %> + "grunt-mocha-test": "~0.10.2", + "grunt-mocha-istanbul": "^2.0.0",<% if(filters.sass) { %> "grunt-contrib-sass": "^0.7.3",<% } %><% if(filters.stylus) { %> "grunt-contrib-stylus": "latest",<% } %> "jit-grunt": "^0.5.0", @@ -85,8 +87,9 @@ "karma-phantomjs-launcher": "~0.1.4", "karma": "~0.12.9", "karma-ng-html2js-preprocessor": "~0.1.0", + "proxyquire": "^1.0.1", "supertest": "~0.11.0", - "should": "~3.3.1" + "sinon-chai": "^2.5.0" }, "engines": { "node": ">=0.10.0" diff --git a/app/templates/mocha.conf.js b/app/templates/mocha.conf.js new file mode 100644 index 000000000..497d43b2c --- /dev/null +++ b/app/templates/mocha.conf.js @@ -0,0 +1,14 @@ +'use strict'; + +var chai = require('chai'); +var sinon = require('sinon'); +var sinonChai = require('sinon-chai'); +var chaiAsPromised = require('chai-as-promised'); + +global.expect = chai.expect; +global.assert = chai.assert; +global.sinon = sinon; + +chai.should(); +chai.use(sinonChai); +chai.use(chaiAsPromised); diff --git a/app/templates/server/.jshintrc-spec b/app/templates/server/.jshintrc-spec index b6b55cbf9..b9390c374 100644 --- a/app/templates/server/.jshintrc-spec +++ b/app/templates/server/.jshintrc-spec @@ -6,6 +6,9 @@ "before": true, "beforeEach": true, "after": true, - "afterEach": true + "afterEach": true, + "expect": true, + "assert": true, + "sinon": true } } diff --git a/app/templates/server/api/thing/index.js b/app/templates/server/api/thing/index.js index 242ed5901..e77e80c5b 100644 --- a/app/templates/server/api/thing/index.js +++ b/app/templates/server/api/thing/index.js @@ -12,4 +12,4 @@ router.put('/:id', controller.update); router.patch('/:id', controller.update); router.delete('/:id', controller.destroy);<% } %> -module.exports = router; \ No newline at end of file +module.exports = router; diff --git a/app/templates/server/api/thing/index.spec.js b/app/templates/server/api/thing/index.spec.js new file mode 100644 index 000000000..0fbfb1029 --- /dev/null +++ b/app/templates/server/api/thing/index.spec.js @@ -0,0 +1,85 @@ +'use strict'; + +var proxyquire = require('proxyquire').noPreserveCache(); + + /* thing.controller stub */ +var thingCtrl = { + index: 'thingCtrl.index'<% if(filters.mongoose) { %>, + show: 'thingCtrl.show', + create: 'thingCtrl.create', + update: 'thingCtrl.update', + destroy: 'thingCtrl.destroy'<% } %> + }, + /* express.Router().router stub */ + router = { + get: sinon.spy()<% if(filters.mongoose) { %>, + put: sinon.spy(), + patch: sinon.spy(), + post: sinon.spy(), + delete: sinon.spy()<% } %> + }, + /* stubbed thing router */ + index = proxyquire('./index.js', { + 'express': { + Router: function() { + return router; + } + }, + './thing.controller': thingCtrl + }); + +describe('Thing API Router:', function() { + + it('should return an express router instance', function() { + index.should.equal(router); + }); + + describe('GET /api/things', function() { + + it('should route to thing.controller.index', function() { + return router.get.withArgs('/', 'thingCtrl.index').should.have.been.calledOnce; + }); + + });<% if(filters.mongoose) { %> + + describe('GET /api/things/:id', function() { + + it('should route to thing.controller.show', function() { + return router.get.withArgs('/:id', 'thingCtrl.show').should.have.been.calledOnce; + }); + + }); + + describe('POST /api/things', function() { + + it('should route to thing.controller.create', function() { + return router.post.withArgs('/', 'thingCtrl.create').should.have.been.calledOnce; + }); + + }); + + describe('PUT /api/things/:id', function() { + + it('should route to thing.controller.update', function() { + return router.put.withArgs('/:id', 'thingCtrl.update').should.have.been.calledOnce; + }); + + }); + + describe('PATCH /api/things/:id', function() { + + it('should route to thing.controller.update', function() { + return router.patch.withArgs('/:id', 'thingCtrl.update').should.have.been.calledOnce; + }); + + }); + + describe('DELETE /api/things/:id', function() { + + it('should route to thing.controller.destroy', function() { + return router.delete.withArgs('/:id', 'thingCtrl.destroy').should.have.been.calledOnce; + }); + + });<% } %> + +}); diff --git a/app/templates/server/api/thing/thing.controller.js b/app/templates/server/api/thing/thing.controller.js index ba84d6fc9..72a678cf4 100644 --- a/app/templates/server/api/thing/thing.controller.js +++ b/app/templates/server/api/thing/thing.controller.js @@ -86,4 +86,4 @@ exports.destroy = function(req, res) { function handleError(res, err) { return res.send(500, err); -}<% } %> \ No newline at end of file +}<% } %> diff --git a/app/templates/server/api/thing/thing.e2e.js b/app/templates/server/api/thing/thing.e2e.js new file mode 100644 index 000000000..1140df7e9 --- /dev/null +++ b/app/templates/server/api/thing/thing.e2e.js @@ -0,0 +1,135 @@ +'use strict'; + +var app = require('../../app'); +var request = require('supertest');<% if(filters.mongoose) { %> + +var newThing;<% } %> + +describe('Thing API:', function() { + + describe('GET /api/things', function() { + var things; + + beforeEach(function(done) { + request(app) + .get('/api/things') + .expect(200) + .expect('Content-Type', /json/) + .end(function(err, res) { + if (err) return done(err); + things = res.body; + done(); + }); + }); + + it('should respond with JSON array', function() { + things.should.be.instanceOf(Array); + }); + + });<% if(filters.mongoose) { %> + + describe('POST /api/things', function() { + beforeEach(function(done) { + request(app) + .post('/api/things') + .send({ + name: 'New Thing', + info: 'This is the brand new thing!!!' + }) + .expect(201) + .expect('Content-Type', /json/) + .end(function(err, res) { + if (err) return done(err); + newThing = res.body; + done(); + }); + }); + + it('should respond with the newly created thing', function() { + newThing.name.should.equal('New Thing'); + newThing.info.should.equal('This is the brand new thing!!!'); + }); + + }); + + describe('GET /api/things/:id', function() { + var thing; + + beforeEach(function(done) { + request(app) + .get('/api/things/' + newThing._id) + .expect(200) + .expect('Content-Type', /json/) + .end(function(err, res) { + if (err) return done(err); + thing = res.body; + done(); + }); + }); + + afterEach(function() { + thing = {}; + }); + + it('should respond with the requested thing', function() { + thing.name.should.equal('New Thing'); + thing.info.should.equal('This is the brand new thing!!!'); + }); + + }); + + describe('PUT /api/things/:id', function() { + var updatedThing + + beforeEach(function(done) { + request(app) + .put('/api/things/' + newThing._id) + .send({ + name: 'Updated Thing', + info: 'This is the updated thing!!!' + }) + .expect(200) + .expect('Content-Type', /json/) + .end(function(err, res) { + if (err) return done(err); + updatedThing = res.body; + done(); + }); + }); + + afterEach(function() { + updatedThing = {}; + }); + + it('should respond with the updated thing', function() { + updatedThing.name.should.equal('Updated Thing'); + updatedThing.info.should.equal('This is the updated thing!!!'); + }); + + }); + + describe('DELETE /api/things/:id', function() { + + it('should respond with 204 on successful removal', function(done) { + request(app) + .delete('/api/things/' + newThing._id) + .expect(204) + .end(function(err, res) { + if (err) return done(err); + done(); + }); + }); + + it('should respond with 404 when thing does not exsist', function(done) { + request(app) + .delete('/api/things/' + newThing._id) + .expect(404) + .end(function(err, res) { + if (err) return done(err); + done(); + }); + }); + + });<% } %> + +}); diff --git a/app/templates/server/api/thing/thing.model(mongoose).js b/app/templates/server/api/thing/thing.model(mongoose).js index ed857cd3b..92a791e70 100644 --- a/app/templates/server/api/thing/thing.model(mongoose).js +++ b/app/templates/server/api/thing/thing.model(mongoose).js @@ -9,4 +9,4 @@ var ThingSchema = new Schema({ active: Boolean }); -module.exports = mongoose.model('Thing', ThingSchema); \ No newline at end of file +module.exports = mongoose.model('Thing', ThingSchema); diff --git a/app/templates/server/api/thing/thing.socket(socketio).js b/app/templates/server/api/thing/thing.socket(socketio).js index 79d327695..dbf3e2fe7 100644 --- a/app/templates/server/api/thing/thing.socket(socketio).js +++ b/app/templates/server/api/thing/thing.socket(socketio).js @@ -21,4 +21,4 @@ function onSave(socket, doc, cb) { function onRemove(socket, doc, cb) { socket.emit('thing:remove', doc); -} \ No newline at end of file +} diff --git a/app/templates/server/api/thing/thing.spec.js b/app/templates/server/api/thing/thing.spec.js deleted file mode 100644 index 17c8c6cd0..000000000 --- a/app/templates/server/api/thing/thing.spec.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; - -var should = require('should'); -var app = require('../../app'); -var request = require('supertest'); - -describe('GET /api/things', function() { - - it('should respond with JSON array', function(done) { - request(app) - .get('/api/things') - .expect(200) - .expect('Content-Type', /json/) - .end(function(err, res) { - if (err) return done(err); - res.body.should.be.instanceof(Array); - done(); - }); - }); -}); diff --git a/app/templates/server/api/user(auth)/index.js b/app/templates/server/api/user(auth)/index.js index 48567e485..be6fd3af3 100644 --- a/app/templates/server/api/user(auth)/index.js +++ b/app/templates/server/api/user(auth)/index.js @@ -2,7 +2,6 @@ var express = require('express'); var controller = require('./user.controller'); -var config = require('../../config/environment'); var auth = require('../../auth/auth.service'); var router = express.Router(); diff --git a/app/templates/server/api/user(auth)/index.spec.js b/app/templates/server/api/user(auth)/index.spec.js new file mode 100644 index 000000000..5bcd4c2c0 --- /dev/null +++ b/app/templates/server/api/user(auth)/index.spec.js @@ -0,0 +1,95 @@ +'use strict'; + +var proxyquire = require('proxyquire').noPreserveCache(); + + /* user.controller stub */ +var userCtrl = { + index: 'userCtrl.index', + destroy: 'userCtrl.destroy', + me: 'userCtrl.me', + changePassword: 'userCtrl.changePassword', + show: 'userCtrl.show', + create: 'userCtrl.create' + }, + /* auth.service stub */ + authService = { + isAuthenticated: function() { + return 'authService.isAuthenticated'; + }, + hasRole: function(role) { + return 'authService.hasRole.' + role; + } + }, + /* express.Router().router stub */ + router = { + get: sinon.spy(), + put: sinon.spy(), + post: sinon.spy(), + delete: sinon.spy() + }, + /* stubbed user router */ + index = proxyquire('./index', { + 'express': { + Router: function() { + return router; + } + }, + './user.controller': userCtrl, + '../../auth/auth.service': authService + }); + +describe('User API Router:', function() { + + it('should return an express router instance', function() { + index.should.equal(router); + }); + + describe('GET /api/users', function() { + + it('should verify admin role and route to user.controller.index', function() { + return router.get.withArgs('/', 'authService.hasRole.admin', 'userCtrl.index').should.have.been.calledOnce; + }); + + }); + + describe('DELETE /api/users/:id', function() { + + it('should verify admin role and route to user.controller.destroy', function() { + return router.delete.withArgs('/:id', 'authService.hasRole.admin', 'userCtrl.destroy').should.have.been.calledOnce; + }); + + }); + + describe('GET /api/users/me', function() { + + it('should be authenticated and route to user.controller.me', function() { + return router.get.withArgs('/me', 'authService.isAuthenticated', 'userCtrl.me').should.have.been.calledOnce; + }); + + }); + + describe('PUT /api/users/:id/password', function() { + + it('should be authenticated and route to user.controller.changePassword', function() { + return router.put.withArgs('/:id/password', 'authService.isAuthenticated', 'userCtrl.changePassword').should.have.been.calledOnce; + }); + + }); + + describe('GET /api/users/:id', function() { + + it('should be authenticated and route to user.controller.show', function() { + return router.get.withArgs('/:id', 'authService.isAuthenticated', 'userCtrl.show').should.have.been.calledOnce; + }); + + }); + + describe('POST /api/users', function() { + + it('should route to user.controller.create', function() { + return router.post.withArgs('/', 'userCtrl.create').should.have.been.calledOnce; + }); + + }); + +}); diff --git a/app/templates/server/api/user(auth)/user.e2e.js b/app/templates/server/api/user(auth)/user.e2e.js new file mode 100644 index 000000000..917acedd9 --- /dev/null +++ b/app/templates/server/api/user(auth)/user.e2e.js @@ -0,0 +1,68 @@ +'use strict'; + +var app = require('../../app'); +var User = require('./user.model'); +var request = require('supertest'); + +describe('User API:', function() { + var user; + + // Clear users before testing + before(function(done) { + User.remove(function() { + user = new User({ + name: 'Fake User', + email: 'test@test.com', + password: 'password' + }); + + user.save(function(err) { + if (err) return done(err); + done(); + }); + }); + }); + + // Clear users after testing + after(function() { + return User.remove().exec(); + }); + + describe('GET /api/users/me', function() { + var token; + + before(function(done) { + request(app) + .post('/auth/local') + .send({ + email: 'test@test.com', + password: 'password' + }) + .expect(200) + .expect('Content-Type', /json/) + .end(function(err, res) { + token = res.body.token; + done(); + }); + }); + + it('should respond with a user profile when authenticated', function(done) { + request(app) + .get('/api/users/me') + .set('authorization', 'Bearer ' + token) + .expect(200) + .expect('Content-Type', /json/) + .end(function(err, res) { + res.body._id.should.equal(user._id.toString()); + done(); + }); + }); + + it('should respond with a 401 when not authenticated', function(done) { + request(app) + .get('/api/users/me') + .expect(401) + .end(done); + }); + }); +}); diff --git a/app/templates/server/api/user(auth)/user.model.spec.js b/app/templates/server/api/user(auth)/user.model.spec.js index 257c95b7c..0df9a2d5b 100644 --- a/app/templates/server/api/user(auth)/user.model.spec.js +++ b/app/templates/server/api/user(auth)/user.model.spec.js @@ -1,6 +1,5 @@ 'use strict'; -var should = require('should'); var app = require('../../app'); var User = require('./user.model'); @@ -11,50 +10,61 @@ var user = new User({ password: 'password' }); -describe('User Model', function() { - before(function(done) { - // Clear users before testing - User.remove().exec().then(function() { - done(); - }); - }); +describe('User Model:', function() { - afterEach(function(done) { - User.remove().exec().then(function() { - done(); - }); + // Clear users before testing + before(function() { + return User.remove().exec(); }); - it('should begin with no users', function(done) { - User.find({}, function(err, users) { - users.should.have.length(0); - done(); + describe('User (schema)', function() { + + it('should begin with no users', function() { + return User.find({}).exec().should.eventually.have.length(0); }); + }); - it('should fail when saving a duplicate user', function(done) { - user.save(function() { - var userDup = new User(user); - userDup.save(function(err) { - should.exist(err); - done(); + describe('user (instance)', function() { + + describe('.save()', function() { + // Clear users after tests + afterEach(function() { + return User.remove().exec(); + }); + + it('should fail when saving a duplicate user', function(done) { + user.save(function() { + var userDup = new User(user); + userDup.save(function(err) { + err.should.be.instanceOf(Error); + done(); + }); + }); + }); + + it('should fail when saving without an email', function(done) { + user.email = ''; + user.save(function(err) { + err.should.be.instanceOf(Error); + done(); + }); }); + }); - }); - it('should fail when saving without an email', function(done) { - user.email = ''; - user.save(function(err) { - should.exist(err); - done(); + describe('.authenticate()', function() { + + it("should authenticate user if password is valid", function() { + return user.authenticate('password').should.be.true; + }); + + it("should not authenticate user if password is invalid", function() { + return user.authenticate('blah').should.not.be.true; + }); + }); - }); - it("should authenticate user if password is valid", function() { - return user.authenticate('password').should.be.true; }); - it("should not authenticate user if password is invalid", function() { - return user.authenticate('blah').should.not.be.true; - }); }); diff --git a/endpoint/templates/index.spec.js b/endpoint/templates/index.spec.js new file mode 100644 index 000000000..62caed5dc --- /dev/null +++ b/endpoint/templates/index.spec.js @@ -0,0 +1,85 @@ +'use strict'; + +var proxyquire = require('proxyquire').noPreserveCache(); + + /* <%= name %>.controller stub */ +var <%= name %>Ctrl = { + index: '<%= name %>Ctrl.index'<% if(filters.mongoose) { %>, + show: '<%= name %>Ctrl.show', + create: '<%= name %>Ctrl.create', + update: '<%= name %>Ctrl.update', + destroy: '<%= name %>Ctrl.destroy'<% } %> + }, + /* express.Router().router stub */ + router = { + get: sinon.spy()<% if(filters.mongoose) { %>, + put: sinon.spy(), + patch: sinon.spy(), + post: sinon.spy(), + delete: sinon.spy()<% } %> + }, + /* stubbed <%= name %> router */ + index = proxyquire('./index.js', { + 'express': { + Router: function() { + return router; + } + }, + './<%= name %>.controller': <%= name %>Ctrl + }); + +describe('<%= classedName %> API Router:', function() { + + it('should return an express router instance', function() { + index.should.equal(router); + }); + + describe('GET <%= route %>', function() { + + it('should route to <%= name %>.controller.index', function() { + return router.get.withArgs('/', '<%= name %>Ctrl.index').should.have.been.calledOnce; + }); + + });<% if(filters.mongoose) { %> + + describe('GET <%= route %>/:id', function() { + + it('should route to <%= name %>.controller.show', function() { + return router.get.withArgs('/:id', '<%= name %>Ctrl.show').should.have.been.calledOnce; + }); + + }); + + describe('POST <%= route %>', function() { + + it('should route to <%= name %>.controller.create', function() { + return router.post.withArgs('/', '<%= name %>Ctrl.create').should.have.been.calledOnce; + }); + + }); + + describe('PUT <%= route %>/:id', function() { + + it('should route to <%= name %>.controller.update', function() { + return router.put.withArgs('/:id', '<%= name %>Ctrl.update').should.have.been.calledOnce; + }); + + }); + + describe('PATCH <%= route %>/:id', function() { + + it('should route to <%= name %>.controller.update', function() { + return router.patch.withArgs('/:id', '<%= name %>Ctrl.update').should.have.been.calledOnce; + }); + + }); + + describe('DELETE <%= route %>/:id', function() { + + it('should route to <%= name %>.controller.destroy', function() { + return router.delete.withArgs('/:id', '<%= name %>Ctrl.destroy').should.have.been.calledOnce; + }); + + });<% } %> + +}); diff --git a/endpoint/templates/name.e2e.js b/endpoint/templates/name.e2e.js new file mode 100644 index 000000000..5960b40a2 --- /dev/null +++ b/endpoint/templates/name.e2e.js @@ -0,0 +1,135 @@ +'use strict'; + +var app = require('../../app'); +var request = require('supertest');<% if(filters.mongoose) { %> + +var new<%= classedName %>;<% } %> + +describe('<%= classedName %> API:', function() { + + describe('GET <%= route %>', function() { + var <%= name %>s; + + beforeEach(function(done) { + request(app) + .get('<%= route %>') + .expect(200) + .expect('Content-Type', /json/) + .end(function(err, res) { + if (err) return done(err); + <%= name %>s = res.body; + done(); + }); + }); + + it('should respond with JSON array', function() { + <%= name %>s.should.be.instanceOf(Array); + }); + + });<% if(filters.mongoose) { %> + + describe('POST <%= route %>', function() { + beforeEach(function(done) { + request(app) + .post('<%= route %>') + .send({ + name: 'New <%= classedName %>', + info: 'This is the brand new <%= name %>!!!' + }) + .expect(201) + .expect('Content-Type', /json/) + .end(function(err, res) { + if (err) return done(err); + new<%= classedName %> = res.body; + done(); + }); + }); + + it('should respond with the newly created <%= name %>', function() { + new<%= classedName %>.name.should.equal('New <%= classedName %>'); + new<%= classedName %>.info.should.equal('This is the brand new <%= name %>!!!'); + }); + + }); + + describe('GET <%= route %>/:id', function() { + var <%= name %>; + + beforeEach(function(done) { + request(app) + .get('<%= route %>/' + new<%= classedName %>._id) + .expect(200) + .expect('Content-Type', /json/) + .end(function(err, res) { + if (err) return done(err); + <%= name %> = res.body; + done(); + }); + }); + + afterEach(function() { + <%= name %> = {}; + }); + + it('should respond with the requested <%= name %>', function() { + <%= name %>.name.should.equal('New <%= classedName %>'); + <%= name %>.info.should.equal('This is the brand new <%= name %>!!!'); + }); + + }); + + describe('PUT <%= route %>/:id', function() { + var updated<%= classedName %> + + beforeEach(function(done) { + request(app) + .put('<%= route %>/' + new<%= classedName %>._id) + .send({ + name: 'Updated <%= classedName %>', + info: 'This is the updated <%= name %>!!!' + }) + .expect(200) + .expect('Content-Type', /json/) + .end(function(err, res) { + if (err) return done(err); + updated<%= classedName %> = res.body; + done(); + }); + }); + + afterEach(function() { + updated<%= classedName %> = {}; + }); + + it('should respond with the updated <%= name %>', function() { + updated<%= classedName %>.name.should.equal('Updated <%= classedName %>'); + updated<%= classedName %>.info.should.equal('This is the updated <%= name %>!!!'); + }); + + }); + + describe('DELETE <%= route %>/:id', function() { + + it('should respond with 204 on successful removal', function(done) { + request(app) + .delete('<%= route %>/' + new<%= classedName %>._id) + .expect(204) + .end(function(err, res) { + if (err) return done(err); + done(); + }); + }); + + it('should respond with 404 when <%= name %> does not exsist', function(done) { + request(app) + .delete('<%= route %>/' + new<%= classedName %>._id) + .expect(404) + .end(function(err, res) { + if (err) return done(err); + done(); + }); + }); + + });<% } %> + +}); diff --git a/endpoint/templates/name.spec.js b/endpoint/templates/name.spec.js deleted file mode 100644 index fcad73ebd..000000000 --- a/endpoint/templates/name.spec.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; - -var should = require('should'); -var app = require('../../app'); -var request = require('supertest'); - -describe('GET <%= route %>', function() { - - it('should respond with JSON array', function(done) { - request(app) - .get('<%= route %>') - .expect(200) - .expect('Content-Type', /json/) - .end(function(err, res) { - if (err) return done(err); - res.body.should.be.instanceof(Array); - done(); - }); - }); -}); \ No newline at end of file diff --git a/test/fixtures/package.json b/test/fixtures/package.json index ce4df22f9..2304c008e 100644 --- a/test/fixtures/package.json +++ b/test/fixtures/package.json @@ -30,6 +30,7 @@ "socketio-jwt": "^2.0.2" }, "devDependencies": { + "chai-as-promised": "^4.1.1", "grunt": "~0.4.4", "grunt-autoprefixer": "~0.7.2", "grunt-wiredep": "~1.8.0", @@ -62,6 +63,7 @@ "grunt-karma": "~0.8.2", "grunt-build-control": "DaftMonk/grunt-build-control", "grunt-mocha-test": "~0.10.2", + "grunt-mocha-istanbul": "^2.0.0", "grunt-contrib-sass": "^0.7.3", "grunt-contrib-stylus": "latest", "jit-grunt": "^0.5.0", @@ -85,8 +87,9 @@ "karma-phantomjs-launcher": "~0.1.4", "karma": "~0.12.9", "karma-ng-html2js-preprocessor": "~0.1.0", + "proxyquire": "^1.0.1", "supertest": "~0.11.0", - "should": "~3.3.1" + "sinon-chai": "^2.5.0" }, "engines": { "node": ">=0.10.0"