From 102078dda98d2db9aacb9eb67d5d45ed0dbb1af9 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Mon, 25 Aug 2014 01:06:36 -0600 Subject: [PATCH 0001/1357] use more restrictive matching for serve-favicon version --- app/templates/_package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 36256461c..e32849740 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -7,7 +7,7 @@ "morgan": "~1.0.0", "body-parser": "~1.5.0", "method-override": "~1.0.0", - "serve-favicon": "^2.0.1", + "serve-favicon": "~2.0.1", "cookie-parser": "~1.0.1", "express-session": "~1.0.2", "errorhandler": "~1.0.0", From 6aecdf7fc8929fe4853280d0e8ac878f3e2a20fd Mon Sep 17 00:00:00 2001 From: Patrick Baker Date: Tue, 26 Aug 2014 18:01:38 -0400 Subject: [PATCH 0002/1357] feat(auth): make crypto async - Update tests and add new test for changed password - User.authenticate() User.makeSalt() and User.encryptPassword() public API remains same - User.authenticate() User.makeSalt() and User.encryptPassword() callbacks are optional - Change User schema from hashedPassword to password - Remove unnecessary virtual attribute User.password, getters and setters are not async --- app/templates/server/.jshintrc | 1 + .../server/api/user(auth)/user.controller.js | 26 +++-- .../server/api/user(auth)/user.model.js | 104 +++++++++++++----- .../server/api/user(auth)/user.model.spec.js | 49 +++++++-- .../server/auth(auth)/local/passport.js | 14 ++- 5 files changed, 141 insertions(+), 53 deletions(-) diff --git a/app/templates/server/.jshintrc b/app/templates/server/.jshintrc index d7b958e7c..42fea558a 100644 --- a/app/templates/server/.jshintrc +++ b/app/templates/server/.jshintrc @@ -1,4 +1,5 @@ { + "expr": true, "node": true, "esnext": true, "bitwise": true, diff --git a/app/templates/server/api/user(auth)/user.controller.js b/app/templates/server/api/user(auth)/user.controller.js index f4cd10c29..17e6e0e04 100644 --- a/app/templates/server/api/user(auth)/user.controller.js +++ b/app/templates/server/api/user(auth)/user.controller.js @@ -14,7 +14,7 @@ var validationError = function(res, err) { * restriction: 'admin' */ exports.index = function(req, res) { - User.find({}, '-salt -hashedPassword', function (err, users) { + User.find({}, '-salt -password', function (err, users) { if(err) return res.send(500, err); res.json(200, users); }); @@ -67,15 +67,19 @@ exports.changePassword = function(req, res, next) { var newPass = String(req.body.newPassword); User.findById(userId, function (err, user) { - if(user.authenticate(oldPass)) { - user.password = newPass; - user.save(function(err) { - if (err) return validationError(res, err); - res.send(200); - }); - } else { - res.send(403); - } + user.authenticate(oldPass, function(authErr, authenticated) { + if (authErr) res.send(403); + + if (authenticated) { + user.password = newPass; + user.save(function(err) { + if (err) return validationError(res, err); + res.send(200); + }); + } else { + res.send(403); + } + }); }); }; @@ -86,7 +90,7 @@ exports.me = function(req, res, next) { var userId = req.user._id; User.findOne({ _id: userId - }, '-salt -hashedPassword', function(err, user) { // don't ever give out the password or salt + }, '-salt -password', function(err, user) { // don't ever give out the password or salt if (err) return next(err); if (!user) return res.json(401); res.json(user); diff --git a/app/templates/server/api/user(auth)/user.model.js b/app/templates/server/api/user(auth)/user.model.js index cc8d59263..b3497f859 100644 --- a/app/templates/server/api/user(auth)/user.model.js +++ b/app/templates/server/api/user(auth)/user.model.js @@ -12,7 +12,7 @@ var UserSchema = new Schema({ type: String, default: 'user' }, - hashedPassword: String, + password: String, provider: String, salt: String<% if (filters.oauth) { %>,<% if (filters.facebookAuth) { %> facebook: {},<% } %><% if (filters.twitterAuth) { %> @@ -24,16 +24,6 @@ var UserSchema = new Schema({ /** * Virtuals */ -UserSchema - .virtual('password') - .set(function(password) { - this._password = password; - this.salt = this.makeSalt(); - this.hashedPassword = this.encryptPassword(password); - }) - .get(function() { - return this._password; - }); // Public profile information UserSchema @@ -69,10 +59,10 @@ UserSchema // Validate empty password UserSchema - .path('hashedPassword') - .validate(function(hashedPassword) {<% if (filters.oauth) { %> + .path('password') + .validate(function(password) {<% if (filters.oauth) { %> if (authTypes.indexOf(this.provider) !== -1) return true;<% } %> - return hashedPassword.length; + return password.length; }, 'Password cannot be blank'); // Validate email is not taken @@ -99,12 +89,26 @@ var validatePresenceOf = function(value) { */ UserSchema .pre('save', function(next) { - if (!this.isNew) return next(); - - if (!validatePresenceOf(this.hashedPassword)<% if (filters.oauth) { %> && authTypes.indexOf(this.provider) === -1<% } %>) - next(new Error('Invalid password')); - else + // Handle new/update passwords + if (this.password) { + if (!validatePresenceOf(this.password)<% if (filters.oauth) { %> && authTypes.indexOf(this.provider) === -1<% } %>) + next(new Error('Invalid password')); + + // Make salt with a callback + var _this = this; + this.makeSalt(function(saltErr, salt) { + if (saltErr) next(saltErr); + _this.salt = salt; + // Async hash + _this.encryptPassword(_this.password, function(encryptErr, hashedPassword) { + if (encryptErr) next(encryptErr); + _this.password = hashedPassword; + next(); + }); + }); + } else { next(); + } }); /** @@ -115,34 +119,82 @@ UserSchema.methods = { * Authenticate - check if the passwords are the same * * @param {String} plainText + * @callback {callback} Optional callback * @return {Boolean} * @api public */ - authenticate: function(plainText) { - return this.encryptPassword(plainText) === this.hashedPassword; + authenticate: function(password, callback) { + if (!callback) + return this.password === this.encryptPassword(password); + + var _this = this; + this.encryptPassword(password, function(err, pwdGen) { + if (err) callback(err); + + if (_this.password === pwdGen) { + callback(null, true); + } else { + callback(null, false); + } + }); }, /** * Make salt * + * @param {Number} byteSize Optional salt byte size, default to 16 + * @callback {callback} Optional callback * @return {String} * @api public */ - makeSalt: function() { - return crypto.randomBytes(16).toString('base64'); + makeSalt: function(byteSize, callback) { + var defaultByteSize = 16; + + if (typeof arguments[0] === 'function') { + callback = arguments[0]; + byteSize = defaultByteSize; + } else if (typeof arguments[1] === 'function') { + callback = arguments[1]; + } + + if (!byteSize) { + byteSize = defaultByteSize; + } + + if (!callback) { + return crypto.randomBytes(byteSize).toString('base64'); + } + + return crypto.randomBytes(byteSize, function(err, salt) { + if (err) callback(err); + return callback(null, salt.toString('base64')); + }); }, /** * Encrypt password * * @param {String} password + * @callback {callback} Optional callback * @return {String} * @api public */ - encryptPassword: function(password) { - if (!password || !this.salt) return ''; + encryptPassword: function(password, callback) { + if (!password || !this.salt) { + return null; + } + + var defaultIterations = 10000; + var defaultKeyLength = 64; var salt = new Buffer(this.salt, 'base64'); - return crypto.pbkdf2Sync(password, salt, 10000, 64).toString('base64'); + + if (!callback) + return crypto.pbkdf2Sync(password, salt, defaultIterations, defaultKeyLength).toString('base64'); + + return crypto.pbkdf2(password, salt, defaultIterations, defaultKeyLength, function(err, key) { + if (err) callback(err); + return callback(null, key.toString('base64')); + }); } }; 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..95e8bfbd8 100644 --- a/app/templates/server/api/user(auth)/user.model.spec.js +++ b/app/templates/server/api/user(auth)/user.model.spec.js @@ -4,14 +4,9 @@ var should = require('should'); var app = require('../../app'); var User = require('./user.model'); -var user = new User({ - provider: 'local', - name: 'Fake User', - email: 'test@test.com', - password: 'password' -}); - describe('User Model', function() { + var user; + before(function(done) { // Clear users before testing User.remove().exec().then(function() { @@ -20,6 +15,15 @@ describe('User Model', function() { }); afterEach(function(done) { + // Start from scratch + user = new User({ + provider: 'local', + name: 'Fake User', + email: 'test@test.com', + password: 'password' + }); + + // Clear all users User.remove().exec().then(function() { done(); }); @@ -50,11 +54,34 @@ describe('User Model', function() { }); }); - it("should authenticate user if password is valid", function() { - return user.authenticate('password').should.be.true; + it("should authenticate user if password is valid", function(done) { + user.save(function(err, newUser) { + newUser.authenticate('password', function(authErr, authenticated) { + authenticated.should.be.true; + done(); + }); + }); + }); + + it("should not authenticate user if password is invalid", function(done) { + user.save(function(err, newUser) { + newUser.authenticate('invalidPassword', function(authErr, authenticated) { + authenticated.should.not.be.true; + done(); + }); + }); }); - it("should not authenticate user if password is invalid", function() { - return user.authenticate('blah').should.not.be.true; + it("should authenticate after updating password", function(done) { + user.save(function(err, newUser) { + newUser.password = 'newPassword'; + newUser.save(function() { + newUser.authenticate('newPassword', function(authErr, authenticated) { + authenticated.should.be.true; + done(); + }); + }); + }); }); + }); diff --git a/app/templates/server/auth(auth)/local/passport.js b/app/templates/server/auth(auth)/local/passport.js index ac82b42a2..4221f8786 100644 --- a/app/templates/server/auth(auth)/local/passport.js +++ b/app/templates/server/auth(auth)/local/passport.js @@ -15,11 +15,15 @@ exports.setup = function (User, config) { if (!user) { return done(null, false, { message: 'This email is not registered.' }); } - if (!user.authenticate(password)) { - return done(null, false, { message: 'This password is not correct.' }); - } - return done(null, user); + user.authenticate(password, function(authError, authenticated) { + if (authError) return done(authError); + if (!authenticated) { + return done(null, false, { message: 'This password is not correct.' }); + } else { + return done(null, user); + } + }); }); } )); -}; \ No newline at end of file +}; From de5c36ca3003ea9ef149eb26ca8393d6ab2d8a4a Mon Sep 17 00:00:00 2001 From: kingcody Date: Fri, 29 Aug 2014 11:05:05 -0400 Subject: [PATCH 0003/1357] refactor(server-tests): use sinon-chai and `mocha.conf.js` Changes: - add `mocha.conf.js` and use it as a `require` in `mochaTest` task - switch `should.js` for `mocha-chai` - change server-side test assertions to user chai assertions Breaking Changes: - should.js is no longer included, chai assertions should be used instead. --- app/templates/Gruntfile.js | 3 ++- app/templates/_package.json | 3 ++- app/templates/mocha.conf.js | 12 +++++++++++ app/templates/server/api/thing/thing.spec.js | 3 +-- .../server/api/user(auth)/user.model.spec.js | 20 ++++++++----------- endpoint/templates/name.spec.js | 5 ++--- test/fixtures/package.json | 3 ++- 7 files changed, 29 insertions(+), 20 deletions(-) create mode 100644 app/templates/mocha.conf.js diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 998ca5620..d98992888 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -486,7 +486,8 @@ module.exports = function (grunt) { mochaTest: { options: { - reporter: 'spec' + reporter: 'spec', + require: 'mocha.conf.js' }, src: ['server/**/*.spec.js'] }, diff --git a/app/templates/_package.json b/app/templates/_package.json index e32849740..7b2cf48d5 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", @@ -86,7 +87,7 @@ "karma": "~0.12.9", "karma-ng-html2js-preprocessor": "~0.1.0", "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..7bfaa573f --- /dev/null +++ b/app/templates/mocha.conf.js @@ -0,0 +1,12 @@ +'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; +chai.should(); +chai.use(sinonChai); +chai.use(chaiAsPromised); diff --git a/app/templates/server/api/thing/thing.spec.js b/app/templates/server/api/thing/thing.spec.js index 17c8c6cd0..3f135445b 100644 --- a/app/templates/server/api/thing/thing.spec.js +++ b/app/templates/server/api/thing/thing.spec.js @@ -1,6 +1,5 @@ 'use strict'; -var should = require('should'); var app = require('../../app'); var request = require('supertest'); @@ -13,7 +12,7 @@ describe('GET /api/things', function() { .expect('Content-Type', /json/) .end(function(err, res) { if (err) return done(err); - res.body.should.be.instanceof(Array); + res.body.should.be.instanceOf(Array); 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..8960ca859 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'); @@ -12,17 +11,14 @@ var user = new User({ }); describe('User Model', function() { - before(function(done) { - // Clear users before testing - User.remove().exec().then(function() { - done(); - }); + + // Clear users before testing + before(function() { + return User.remove().exec(); }); - afterEach(function(done) { - User.remove().exec().then(function() { - done(); - }); + afterEach(function() { + return User.remove().exec(); }); it('should begin with no users', function(done) { @@ -36,7 +32,7 @@ describe('User Model', function() { user.save(function() { var userDup = new User(user); userDup.save(function(err) { - should.exist(err); + err.should.be.instanceOf(Error); done(); }); }); @@ -45,7 +41,7 @@ describe('User Model', function() { it('should fail when saving without an email', function(done) { user.email = ''; user.save(function(err) { - should.exist(err); + err.should.be.instanceOf(Error); done(); }); }); diff --git a/endpoint/templates/name.spec.js b/endpoint/templates/name.spec.js index fcad73ebd..d287bafe5 100644 --- a/endpoint/templates/name.spec.js +++ b/endpoint/templates/name.spec.js @@ -1,6 +1,5 @@ 'use strict'; -var should = require('should'); var app = require('../../app'); var request = require('supertest'); @@ -13,8 +12,8 @@ describe('GET <%= route %>', function() { .expect('Content-Type', /json/) .end(function(err, res) { if (err) return done(err); - res.body.should.be.instanceof(Array); + 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..9bdfd30ff 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", @@ -86,7 +87,7 @@ "karma": "~0.12.9", "karma-ng-html2js-preprocessor": "~0.1.0", "supertest": "~0.11.0", - "should": "~3.3.1" + "sinon-chai": "^2.5.0" }, "engines": { "node": ">=0.10.0" From dbbaa20b47629be60de8ce5f31a7c91abf9bdaef Mon Sep 17 00:00:00 2001 From: kingcody Date: Sat, 30 Aug 2014 07:53:03 -0400 Subject: [PATCH 0004/1357] feat(server-tests): code coverage and e2e Changes: - split server tests into `unit` and `e2e` type test - adjust `mochaTest` and `test:server` tasks to reflect the two types of tests - implement `grunt-mocha-istanbul` task for server-side code coverage - add `test:coverage` task - improve `mocha.conf.js` - add sinon, expect, and assert as globals to `server/.jshintrc-spec` - add `proxyquire` to the app for better stubbing in unit tests - improve test to reflect recent changes and to lay ground work for more coverage Grunt Task `test`: The grunt 'test' task now has a 'coverage' target. Used like so `grunt test:coverage`. This task will run istanbul for the server unit tests and e2e test separately. The resulting coverage reports will be placed in `coverage/(unit|e2e)`. There is also an option for the `test:coverage` task, possibilities for option are: - `unit` - `e2e` - `check` `test:coverage:check` will check the coverage reports for both `unit` and `e2e` and report whether or not they meet the required coverage. --- app/templates/Gruntfile.js | 94 +++++++++++- app/templates/_package.json | 4 +- app/templates/mocha.conf.js | 2 + app/templates/server/.jshintrc-spec | 5 +- app/templates/server/api/thing/index.js | 2 +- app/templates/server/api/thing/index.spec.js | 85 +++++++++++ .../server/api/thing/thing.controller.js | 2 +- app/templates/server/api/thing/thing.e2e.js | 135 ++++++++++++++++++ .../server/api/thing/thing.model(mongoose).js | 2 +- .../api/thing/thing.socket(socketio).js | 2 +- app/templates/server/api/thing/thing.spec.js | 19 --- app/templates/server/api/user(auth)/index.js | 1 - .../server/api/user(auth)/index.spec.js | 95 ++++++++++++ .../server/api/user(auth)/user.e2e.js | 68 +++++++++ .../server/api/user(auth)/user.model.spec.js | 66 +++++---- endpoint/templates/index.spec.js | 85 +++++++++++ endpoint/templates/name.e2e.js | 135 ++++++++++++++++++ endpoint/templates/name.spec.js | 19 --- test/fixtures/package.json | 2 + 19 files changed, 748 insertions(+), 75 deletions(-) create mode 100644 app/templates/server/api/thing/index.spec.js create mode 100644 app/templates/server/api/thing/thing.e2e.js delete mode 100644 app/templates/server/api/thing/thing.spec.js create mode 100644 app/templates/server/api/user(auth)/index.spec.js create mode 100644 app/templates/server/api/user(auth)/user.e2e.js create mode 100644 endpoint/templates/index.spec.js create mode 100644 endpoint/templates/name.e2e.js delete mode 100644 endpoint/templates/name.spec.js diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index d98992888..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', @@ -489,7 +489,57 @@ module.exports = function (grunt) { 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: { @@ -770,7 +820,8 @@ module.exports = function (grunt) { return grunt.task.run([ 'env:all', 'env:test', - 'mochaTest' + 'mochaTest:unit', + 'mochaTest:e2e' ]); } @@ -805,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 7b2cf48d5..9dfdadc5d 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -62,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", @@ -86,6 +87,7 @@ "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", "sinon-chai": "^2.5.0" }, diff --git a/app/templates/mocha.conf.js b/app/templates/mocha.conf.js index 7bfaa573f..497d43b2c 100644 --- a/app/templates/mocha.conf.js +++ b/app/templates/mocha.conf.js @@ -7,6 +7,8 @@ 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 3f135445b..000000000 --- a/app/templates/server/api/thing/thing.spec.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict'; - -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 8960ca859..0df9a2d5b 100644 --- a/app/templates/server/api/user(auth)/user.model.spec.js +++ b/app/templates/server/api/user(auth)/user.model.spec.js @@ -10,47 +10,61 @@ var user = new User({ password: 'password' }); -describe('User Model', function() { +describe('User Model:', function() { // Clear users before testing before(function() { return User.remove().exec(); }); - afterEach(function() { - return User.remove().exec(); - }); + describe('User (schema)', function() { - it('should begin with no users', function(done) { - User.find({}, function(err, users) { - users.should.have.length(0); - done(); + 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) { - err.should.be.instanceOf(Error); - 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) { - err.should.be.instanceOf(Error); - 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 d287bafe5..000000000 --- a/endpoint/templates/name.spec.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict'; - -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(); - }); - }); -}); diff --git a/test/fixtures/package.json b/test/fixtures/package.json index 9bdfd30ff..2304c008e 100644 --- a/test/fixtures/package.json +++ b/test/fixtures/package.json @@ -63,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", @@ -86,6 +87,7 @@ "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", "sinon-chai": "^2.5.0" }, From 5198685150001a138230c888691d52fcec3e7a6c Mon Sep 17 00:00:00 2001 From: kingcody Date: Sat, 30 Aug 2014 15:26:37 -0400 Subject: [PATCH 0005/1357] fix(server-tests): `test:coverage` task Changes: - add missing `option` argument from `test` task - define `istanbul_check_coverage` with `jit-grunt` - place server coverage reports in their own folder: `coverage/server` --- app/templates/Gruntfile.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 26866c21d..a72f42dae 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -17,7 +17,8 @@ module.exports = function (grunt) { cdnify: 'grunt-google-cdn', protractor: 'grunt-protractor-runner', injector: 'grunt-asset-injector', - buildcontrol: 'grunt-build-control' + buildcontrol: 'grunt-build-control', + istanbul_check_coverage: 'grunt-mocha-istanbul' }); // Time how long tasks take. Can help when optimizing build times @@ -508,7 +509,7 @@ module.exports = function (grunt) { reporter: 'spec', require: ['mocha.conf.js'], mask: '**/*.spec.js', - coverageFolder: 'coverage/unit' + coverageFolder: 'coverage/server/unit' }, src: 'server' }, @@ -522,7 +523,7 @@ module.exports = function (grunt) { reporter: 'spec', require: ['mocha.conf.js'], mask: '**/*.e2e.js', - coverageFolder: 'coverage/e2e' + coverageFolder: 'coverage/server/e2e' }, src: 'server' } @@ -531,7 +532,7 @@ module.exports = function (grunt) { istanbul_check_coverage: { default: { options: { - coverageFolder: 'coverage/*', + coverageFolder: 'coverage/**', check: { lines: 80, statements: 80, @@ -815,7 +816,7 @@ module.exports = function (grunt) { grunt.task.run(['serve']); }); - grunt.registerTask('test', function(target) { + grunt.registerTask('test', function(target, option) { if (target === 'server') { return grunt.task.run([ 'env:all', From c0b0c6f41672986c66a4c9e729b97f1ceae9121c Mon Sep 17 00:00:00 2001 From: kingcody Date: Sat, 30 Aug 2014 14:49:38 -0400 Subject: [PATCH 0006/1357] docs(server-tests): update readme.md for new `test:coverage` task Changes: - add documentation for `grunt test:coverage` --- readme.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/readme.md b/readme.md index da6a851d1..a9997f528 100644 --- a/readme.md +++ b/readme.md @@ -338,6 +338,19 @@ To setup protractor e2e tests, you must first run Use `grunt test:e2e` to have protractor go through tests located in the `e2e` folder. +**Code Coverage** + +Use `grunt test:coverage` to run mocha-istanbul and generate code coverage reports. + +`coverage/server` will be populated with `e2e` and `unit` folders containing the `lcov` reports. + +The coverage taget has 3 available options: +- `test:coverage:unit` generate server unit test coverage +- `test:coverage:e2e` generate server e2e test coverage +- `test:coverage:check` combine the coverage reports and check against predefined thresholds + +* *when no option is given `test:coverage` runs all options in the above order* + ## Environment Variables Keeping your app secrets and other sensitive information in source control isn't a good idea. To have grunt launch your app with specific environment variables, add them to the git ignored environment config file: `server/config/local.env.js`. From 7045907c849427a16c3aacaf5fd70d14430be09d Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sun, 31 Aug 2014 20:48:46 -0600 Subject: [PATCH 0007/1357] fix user model test --- app/templates/server/api/user(auth)/user.model.spec.js | 7 ------- 1 file changed, 7 deletions(-) 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 952fc5461..afe8af882 100644 --- a/app/templates/server/api/user(auth)/user.model.spec.js +++ b/app/templates/server/api/user(auth)/user.model.spec.js @@ -64,12 +64,5 @@ describe('User Model:', 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; }); }); From 1ca7448fc05c369180c667077918cc2156c308a9 Mon Sep 17 00:00:00 2001 From: Rafael Almeida Date: Mon, 25 Aug 2014 17:40:12 +1200 Subject: [PATCH 0008/1357] feat (mongoose): use mongoose-bird to promisify the mongoose API --- app/templates/_package.json | 6 +- app/templates/server/api/thing/index.spec.js | 12 +- .../server/api/thing/thing.controller.js | 114 ++++++++++++------ .../server/api/thing/thing.model(mongoose).js | 2 +- .../server/api/user(auth)/index.spec.js | 12 +- .../server/api/user(auth)/user.controller.js | 95 +++++++++------ .../server/api/user(auth)/user.model.js | 31 +++-- .../server/api/user(auth)/user.model.spec.js | 68 ++++------- app/templates/server/app.js | 4 +- .../server/auth(auth)/auth.service.js | 30 +++-- app/templates/server/config/express.js | 4 +- app/templates/server/config/seed(mongoose).js | 83 +++++++------ endpoint/templates/index.spec.js | 12 +- endpoint/templates/name.controller.js | 114 ++++++++++++------ endpoint/templates/name.model(mongoose).js | 4 +- 15 files changed, 342 insertions(+), 249 deletions(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 9dfdadc5d..2d8337b71 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -15,7 +15,9 @@ "lodash": "~2.4.1",<% if(filters.jade) { %> "jade": "~1.2.0",<% } %><% if(filters.html) { %> "ejs": "~0.8.4",<% } %><% if(filters.mongoose) { %> - "mongoose": "~3.8.8",<% } %><% if(filters.auth) { %> + "mongoose": "~3.8.8", + "mongoose-bird": "~0.0.1", + <% } %><% if(filters.auth) { %> "jsonwebtoken": "^0.3.0", "express-jwt": "^0.1.3", "passport": "~0.2.0", @@ -46,7 +48,7 @@ "grunt-contrib-watch": "~0.6.1",<% if(filters.coffee) { %> "grunt-contrib-coffee": "^0.10.1",<% } %><% if(filters.jade) { %> "grunt-contrib-jade": "^0.11.0",<% } %><% if(filters.less) { %> - "grunt-contrib-less": "^0.11.0",<% } %> + "grunt-contrib-less": "^0.11.4",<% } %> "grunt-google-cdn": "~0.4.0", "grunt-newer": "~0.7.0", "grunt-ng-annotate": "^0.2.3", diff --git a/app/templates/server/api/thing/index.spec.js b/app/templates/server/api/thing/index.spec.js index 0fbfb1029..e62feff60 100644 --- a/app/templates/server/api/thing/index.spec.js +++ b/app/templates/server/api/thing/index.spec.js @@ -37,7 +37,7 @@ describe('Thing API Router:', function() { describe('GET /api/things', function() { it('should route to thing.controller.index', function() { - return router.get.withArgs('/', 'thingCtrl.index').should.have.been.calledOnce; + router.get.withArgs('/', 'thingCtrl.index').should.have.been.calledOnce; }); });<% if(filters.mongoose) { %> @@ -45,7 +45,7 @@ describe('Thing API Router:', function() { 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; + router.get.withArgs('/:id', 'thingCtrl.show').should.have.been.calledOnce; }); }); @@ -53,7 +53,7 @@ describe('Thing API Router:', function() { describe('POST /api/things', function() { it('should route to thing.controller.create', function() { - return router.post.withArgs('/', 'thingCtrl.create').should.have.been.calledOnce; + router.post.withArgs('/', 'thingCtrl.create').should.have.been.calledOnce; }); }); @@ -61,7 +61,7 @@ describe('Thing API Router:', function() { 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; + router.put.withArgs('/:id', 'thingCtrl.update').should.have.been.calledOnce; }); }); @@ -69,7 +69,7 @@ describe('Thing API Router:', function() { 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; + router.patch.withArgs('/:id', 'thingCtrl.update').should.have.been.calledOnce; }); }); @@ -77,7 +77,7 @@ describe('Thing API Router:', function() { 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; + 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 72a678cf4..4d5abca05 100644 --- a/app/templates/server/api/thing/thing.controller.js +++ b/app/templates/server/api/thing/thing.controller.js @@ -7,10 +7,57 @@ * DELETE /things/:id -> destroy */ -'use strict'; +'use strict';<% if (filters.mongoose) { %> -var _ = require('lodash');<% if (filters.mongoose) { %> -var Thing = require('./thing.model');<% } %> +var _ = require('lodash'); +var Thing = require('./thing.model'); + +function handleError(res, statusCode){ + statusCode = statusCode || 500; + return function(err){ + res.send(statusCode, err); + }; +} + +function responseWithResult(res, statusCode){ + statusCode = statusCode || 200; + return function(entity){ + if(entity){ + return res.json(statusCode, entity); + } + }; +} + +function handleEntityNotFound(res){ + return function(entity){ + if(!entity){ + res.send(404); + return null; + } + return entity; + }; +} + +function saveUpdates(updates){ + return function(entity){ + var updated = _.merge(entity, updates); + return updated.saveAsync() + .then(function () { + return updated; + }); + }; +} + +function removeEntity(res){ + return function (entity) { + if(entity){ + return entity.removeAsync() + .then(function() { + return res.send(204); + }); + } + }; +}<% } %> // Get list of things exports.index = function(req, res) {<% if (!filters.mongoose) { %> @@ -34,56 +81,43 @@ exports.index = function(req, res) {<% if (!filters.mongoose) { %> name : 'Deployment Ready', info : 'Easily deploy your app to Heroku or Openshift with the heroku and openshift subgenerators' } - ]);<% } %><% if (filters.mongoose) { %> - Thing.find(function (err, things) { - if(err) { return handleError(res, err); } - return res.json(200, things); - });<% } %> + ]);<% } if (filters.mongoose) { %> + Thing.findAsync() + .then(responseWithResult(res)) + .catch(handleError(res));<% } %> };<% if (filters.mongoose) { %> // Get a single thing exports.show = function(req, res) { - Thing.findById(req.params.id, function (err, thing) { - if(err) { return handleError(res, err); } - if(!thing) { return res.send(404); } - return res.json(thing); - }); + Thing.findByIdAsync(req.params.id) + .then(handleEntityNotFound(res)) + .then(responseWithResult(res)) + .catch(handleError(res)); }; // Creates a new thing in the DB. exports.create = function(req, res) { - Thing.create(req.body, function(err, thing) { - if(err) { return handleError(res, err); } - return res.json(201, thing); - }); + Thing.createAsync(req.body) + .then(responseWithResult(res, 201)) + .catch(handleError(res)); }; // Updates an existing thing in the DB. exports.update = function(req, res) { - if(req.body._id) { delete req.body._id; } - Thing.findById(req.params.id, function (err, thing) { - if (err) { return handleError(res, err); } - if(!thing) { return res.send(404); } - var updated = _.merge(thing, req.body); - updated.save(function (err) { - if (err) { return handleError(res, err); } - return res.json(200, thing); - }); - }); + if(req.body._id) { + delete req.body._id; + } + Thing.findByIdAsync(req.params.id) + .then(handleEntityNotFound(res)) + .then(saveUpdates(req.body)) + .then(responseWithResult(res)) + .catch(handleError(res)); }; // Deletes a thing from the DB. exports.destroy = function(req, res) { - Thing.findById(req.params.id, function (err, thing) { - if(err) { return handleError(res, err); } - if(!thing) { return res.send(404); } - thing.remove(function(err) { - if(err) { return handleError(res, err); } - return res.send(204); - }); - }); -}; - -function handleError(res, err) { - return res.send(500, err); -}<% } %> + Thing.findByIdAsync(req.params.id) + .then(handleEntityNotFound(res)) + .then(removeEntity(res)) + .catch(handleError(res)); +};<% } %> diff --git a/app/templates/server/api/thing/thing.model(mongoose).js b/app/templates/server/api/thing/thing.model(mongoose).js index 92a791e70..a44bc710e 100644 --- a/app/templates/server/api/thing/thing.model(mongoose).js +++ b/app/templates/server/api/thing/thing.model(mongoose).js @@ -1,6 +1,6 @@ 'use strict'; -var mongoose = require('mongoose'), +var mongoose = require('mongoose-bird')(), Schema = mongoose.Schema; var ThingSchema = new Schema({ diff --git a/app/templates/server/api/user(auth)/index.spec.js b/app/templates/server/api/user(auth)/index.spec.js index 5bcd4c2c0..30b786fb3 100644 --- a/app/templates/server/api/user(auth)/index.spec.js +++ b/app/templates/server/api/user(auth)/index.spec.js @@ -47,7 +47,7 @@ describe('User API Router:', function() { 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; + router.get.withArgs('/', 'authService.hasRole.admin', 'userCtrl.index').should.have.been.calledOnce; }); }); @@ -55,7 +55,7 @@ describe('User API Router:', function() { 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; + router.delete.withArgs('/:id', 'authService.hasRole.admin', 'userCtrl.destroy').should.have.been.calledOnce; }); }); @@ -63,7 +63,7 @@ describe('User API Router:', function() { 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; + router.get.withArgs('/me', 'authService.isAuthenticated', 'userCtrl.me').should.have.been.calledOnce; }); }); @@ -71,7 +71,7 @@ describe('User API Router:', function() { 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; + router.put.withArgs('/:id/password', 'authService.isAuthenticated', 'userCtrl.changePassword').should.have.been.calledOnce; }); }); @@ -79,7 +79,7 @@ describe('User API Router:', function() { 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; + router.get.withArgs('/:id', 'authService.isAuthenticated', 'userCtrl.show').should.have.been.calledOnce; }); }); @@ -87,7 +87,7 @@ describe('User API Router:', function() { describe('POST /api/users', function() { it('should route to user.controller.create', function() { - return router.post.withArgs('/', 'userCtrl.create').should.have.been.calledOnce; + router.post.withArgs('/', 'userCtrl.create').should.have.been.calledOnce; }); }); diff --git a/app/templates/server/api/user(auth)/user.controller.js b/app/templates/server/api/user(auth)/user.controller.js index 17e6e0e04..28e30199a 100644 --- a/app/templates/server/api/user(auth)/user.controller.js +++ b/app/templates/server/api/user(auth)/user.controller.js @@ -5,19 +5,37 @@ var passport = require('passport'); var config = require('../../config/environment'); var jwt = require('jsonwebtoken'); -var validationError = function(res, err) { - return res.json(422, err); +var validationError = function(res, statusCode) { + statusCode = statusCode || 422; + return function(err){ + res.json(statusCode, err); + }; }; +function handleError(res, statusCode){ + statusCode = statusCode || 500; + return function(err){ + res.send(statusCode, err); + }; +} + +function respondWith(res, statusCode){ + statusCode = statusCode || 200; + return function(){ + res.send(statusCode); + }; +} + /** * Get list of users * restriction: 'admin' */ exports.index = function(req, res) { - User.find({}, '-salt -password', function (err, users) { - if(err) return res.send(500, err); - res.json(200, users); - }); + User.findAsync({}, '-salt -hashedPassword') + .then(function (users) { + res.json(200, users); + }) + .catch(handleError(res)); }; /** @@ -27,11 +45,12 @@ exports.create = function (req, res, next) { var newUser = new User(req.body); newUser.provider = 'local'; newUser.role = 'user'; - newUser.save(function(err, user) { - if (err) return validationError(res, err); - var token = jwt.sign({_id: user._id }, config.secrets.session, { expiresInMinutes: 60*5 }); - res.json({ token: token }); - }); + newUser.saveAsync() + .then(function(user) { + var token = jwt.sign({_id: user._id }, config.secrets.session, { expiresInMinutes: 60*5 }); + res.json({ token: token }); + }) + .catch(validationError(res)); }; /** @@ -40,11 +59,16 @@ exports.create = function (req, res, next) { exports.show = function (req, res, next) { var userId = req.params.id; - User.findById(userId, function (err, user) { - if (err) return next(err); - if (!user) return res.send(401); - res.json(user.profile); - }); + User.findByIdAsync(userId) + .then(function (user) { + if(!user) { + return res.send(401); + } + res.json(user.profile); + }) + .catch(function(err){ + return next(err); + }); }; /** @@ -52,10 +76,9 @@ exports.show = function (req, res, next) { * restriction: 'admin' */ exports.destroy = function(req, res) { - User.findByIdAndRemove(req.params.id, function(err, user) { - if(err) return res.send(500, err); - return res.send(204); - }); + User.findByIdAndRemoveAsync(req.params.id) + .then(respondWith(res, 204)) + .catch(handleError(res)); }; /** @@ -66,21 +89,17 @@ exports.changePassword = function(req, res, next) { var oldPass = String(req.body.oldPassword); var newPass = String(req.body.newPassword); - User.findById(userId, function (err, user) { - user.authenticate(oldPass, function(authErr, authenticated) { - if (authErr) res.send(403); - - if (authenticated) { + User.findByIdAsync(userId) + .then(function(user) { + if(user.authenticate(oldPass)) { user.password = newPass; - user.save(function(err) { - if (err) return validationError(res, err); - res.send(200); - }); + return user.saveAsync() + .then(respondWith(res, 200)) + .catch(validationError(res)); } else { - res.send(403); + return res.send(403); } }); - }); }; /** @@ -88,13 +107,13 @@ exports.changePassword = function(req, res, next) { */ exports.me = function(req, res, next) { var userId = req.user._id; - User.findOne({ - _id: userId - }, '-salt -password', function(err, user) { // don't ever give out the password or salt - if (err) return next(err); - if (!user) return res.json(401); - res.json(user); - }); + + User.findOneAsync({ _id: userId }, '-salt -hashedPassword') + .then(function(user) { // don't ever give out the password or salt + if (!user) { return res.json(401); } + res.json(user); + }) + .catch(function(err){ return next(err); }); }; /** diff --git a/app/templates/server/api/user(auth)/user.model.js b/app/templates/server/api/user(auth)/user.model.js index b3497f859..b90386886 100644 --- a/app/templates/server/api/user(auth)/user.model.js +++ b/app/templates/server/api/user(auth)/user.model.js @@ -1,6 +1,6 @@ 'use strict'; -var mongoose = require('mongoose'); +var mongoose = require('mongoose-bird')(); var Schema = mongoose.Schema; var crypto = require('crypto');<% if(filters.oauth) { %> var authTypes = ['github', 'twitter', 'facebook', 'google'];<% } %> @@ -53,7 +53,9 @@ UserSchema UserSchema .path('email') .validate(function(email) {<% if (filters.oauth) { %> - if (authTypes.indexOf(this.provider) !== -1) return true;<% } %> + if (authTypes.indexOf(this.provider) !== -1){ + return true; + } <% } %> return email.length; }, 'Email cannot be blank'); @@ -61,7 +63,9 @@ UserSchema UserSchema .path('password') .validate(function(password) {<% if (filters.oauth) { %> - if (authTypes.indexOf(this.provider) !== -1) return true;<% } %> + if (authTypes.indexOf(this.provider) !== -1){ + return true; + } <% } %> return password.length; }, 'Password cannot be blank'); @@ -70,14 +74,19 @@ UserSchema .path('email') .validate(function(value, respond) { var self = this; - this.constructor.findOne({email: value}, function(err, user) { - if(err) throw err; - if(user) { - if(self.id === user.id) return respond(true); - return respond(false); - } - respond(true); - }); + return this.constructor.findOneAsync({email: value}) + .then(function(user) { + if(user) { + if(self.id === user.id) { + return respond(true); + } + return respond(false); + } + return respond(true); + }) + .catch(function(err){ + throw err; + }); }, 'The specified email address is already in use.'); var validatePresenceOf = function(value) { 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 afe8af882..fe51ea2ea 100644 --- a/app/templates/server/api/user(auth)/user.model.spec.js +++ b/app/templates/server/api/user(auth)/user.model.spec.js @@ -10,59 +10,39 @@ var user = new User({ password: 'password' }); -describe('User Model:', function() { - - // Clear users before testing +describe('User Model', function() { before(function() { + // Clear users before testing return User.remove().exec(); }); - describe('User (schema)', function() { - - it('should begin with no users', function() { - return User.find({}).exec().should.eventually.have.length(0); - }); - + afterEach(function() { + return User.remove().exec(); }); - 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 begin with no users', function() { + return User.findAsync({}) + .should.eventually.have.length(0); + }); - describe('.authenticate()', function() { + it('should fail when saving a duplicate user', function() { + return user.saveAsync() + .then(function() { + var userDup = new User(user); + return userDup.saveAsync(); + }).should.be.rejected; + }); - it("should authenticate user if password is valid", function() { - return user.authenticate('password').should.be.true; - }); + it('should fail when saving without an email', function() { + user.email = ''; + return user.saveAsync().should.be.rejected; + }); - 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() { + user.authenticate('password').should.be.true; + }); - }); + it("should not authenticate user if password is invalid", function() { + user.authenticate('blah').should.not.be.true; }); }); diff --git a/app/templates/server/app.js b/app/templates/server/app.js index 08b942f43..5369e94ef 100644 --- a/app/templates/server/app.js +++ b/app/templates/server/app.js @@ -8,7 +8,7 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'development'; var express = require('express');<% if (filters.mongoose) { %> -var mongoose = require('mongoose');<% } %> +var mongoose = require('mongoose-bird')();<% } %> var config = require('./config/environment'); <% if (filters.mongoose) { %> // Connect to database @@ -34,4 +34,4 @@ server.listen(config.port, config.ip, function () { }); // Expose app -exports = module.exports = app; \ No newline at end of file +exports = module.exports = app; diff --git a/app/templates/server/auth(auth)/auth.service.js b/app/templates/server/auth(auth)/auth.service.js index 38ec34302..101dcc5c5 100644 --- a/app/templates/server/auth(auth)/auth.service.js +++ b/app/templates/server/auth(auth)/auth.service.js @@ -1,6 +1,6 @@ 'use strict'; -var mongoose = require('mongoose'); +var mongoose = require('mongoose-bird')(); var passport = require('passport'); var config = require('../config/environment'); var jwt = require('jsonwebtoken'); @@ -25,13 +25,17 @@ function isAuthenticated() { }) // Attach user to request .use(function(req, res, next) { - User.findById(req.user._id, function (err, user) { - if (err) return next(err); - if (!user) return res.send(401); - - req.user = user; - next(); - }); + User.findByIdAsync(req.user._id) + .then(function (user) { + if (!user) { + return res.send(401); + } + req.user = user; + next(); + }) + .catch(function(err){ + return next(err); + }); }); } @@ -39,7 +43,9 @@ function isAuthenticated() { * Checks if the user role meets the minimum requirements of the route */ function hasRole(roleRequired) { - if (!roleRequired) throw new Error('Required role needs to be set'); + if (!roleRequired) { + throw new Error('Required role needs to be set'); + } return compose() .use(isAuthenticated()) @@ -64,7 +70,9 @@ function signToken(id) { * Set token cookie directly for oAuth strategies */ function setTokenCookie(req, res) { - if (!req.user) return res.json(404, { message: 'Something went wrong, please try again.'}); + if (!req.user) { + return res.json(404, { message: 'Something went wrong, please try again.'}); + } var token = signToken(req.user._id, req.user.role); res.cookie('token', JSON.stringify(token)); res.redirect('/'); @@ -73,4 +81,4 @@ function setTokenCookie(req, res) { exports.isAuthenticated = isAuthenticated; exports.hasRole = hasRole; exports.signToken = signToken; -exports.setTokenCookie = setTokenCookie; \ No newline at end of file +exports.setTokenCookie = setTokenCookie; diff --git a/app/templates/server/config/express.js b/app/templates/server/config/express.js index 2243a7779..2403780f1 100644 --- a/app/templates/server/config/express.js +++ b/app/templates/server/config/express.js @@ -17,7 +17,7 @@ var config = require('./environment');<% if (filters.auth) { %> var passport = require('passport');<% } %><% if (filters.twitterAuth) { %> var session = require('express-session'); var mongoStore = require('connect-mongo')(session); -var mongoose = require('mongoose');<% } %> +var mongoose = require('mongoose-bird')();<% } %> module.exports = function(app) { var env = app.get('env'); @@ -57,4 +57,4 @@ module.exports = function(app) { app.use(morgan('dev')); app.use(errorHandler()); // Error handler - has to be last } -}; \ No newline at end of file +}; diff --git a/app/templates/server/config/seed(mongoose).js b/app/templates/server/config/seed(mongoose).js index 27ab19417..6d56010b6 100644 --- a/app/templates/server/config/seed(mongoose).js +++ b/app/templates/server/config/seed(mongoose).js @@ -6,44 +6,51 @@ 'use strict'; var Thing = require('../api/thing/thing.model'); -<% if (filters.auth) { %>var User = require('../api/user/user.model');<% } %> +<% if (filters.auth) { %> +var User = require('../api/user/user.model'); +<% } %> -Thing.find({}).remove(function() { - Thing.create({ - name : 'Development Tools', - info : 'Integration with popular tools such as Bower, Grunt, Karma, Mocha, JSHint, Node Inspector, Livereload, Protractor, Jade, Stylus, Sass, CoffeeScript, and Less.' - }, { - name : 'Server and Client integration', - info : 'Built with a powerful and fun stack: MongoDB, Express, AngularJS, and Node.' - }, { - name : 'Smart Build System', - info : 'Build system ignores `spec` files, allowing you to keep tests alongside code. Automatic injection of scripts and styles into your index.html' - }, { - name : 'Modular Structure', - info : 'Best practice client and server structures allow for more code reusability and maximum scalability' - }, { - name : 'Optimized Build', - info : 'Build process packs up your templates as a single JavaScript payload, minifies your scripts/css/images, and rewrites asset names for caching.' - },{ - name : 'Deployment Ready', - info : 'Easily deploy your app to Heroku or Openshift with the heroku and openshift subgenerators' +Thing.find({}).removeAsync() + .then(function() { + Thing.create({ + name : 'Development Tools', + info : 'Integration with popular tools such as Bower, Grunt, Karma, Mocha, JSHint, Node Inspector, Livereload, Protractor, Jade, Stylus, Sass, CoffeeScript, and Less.' + }, { + name : 'Server and Client integration', + info : 'Built with a powerful and fun stack: MongoDB, Express, AngularJS, and Node.' + }, { + name : 'Smart Build System', + info : 'Build system ignores `spec` files, allowing you to keep tests alongside code. Automatic injection of scripts and styles into your index.html' + }, { + name : 'Modular Structure', + info : 'Best practice client and server structures allow for more code reusability and maximum scalability' + }, { + name : 'Optimized Build', + info : 'Build process packs up your templates as a single JavaScript payload, minifies your scripts/css/images, and rewrites asset names for caching.' + },{ + name : 'Deployment Ready', + info : 'Easily deploy your app to Heroku or Openshift with the heroku and openshift subgenerators' + }); }); -});<% if (filters.auth) { %> -User.find({}).remove(function() { - User.create({ - provider: 'local', - name: 'Test User', - email: 'test@test.com', - password: 'test' - }, { - provider: 'local', - role: 'admin', - name: 'Admin', - email: 'admin@admin.com', - password: 'admin' - }, function() { - console.log('finished populating users'); - } - ); -});<% } %> \ No newline at end of file +<% if (filters.auth) { %> + +User.find({}).removeAsync() + .then(function() { + User.create({ + provider: 'local', + name: 'Test User', + email: 'test@test.com', + password: 'test' + }, { + provider: 'local', + role: 'admin', + name: 'Admin', + email: 'admin@admin.com', + password: 'admin' + }, function() { + console.log('finished populating users'); + } + ); + }); +<% } %> diff --git a/endpoint/templates/index.spec.js b/endpoint/templates/index.spec.js index 62caed5dc..b5bfb3a41 100644 --- a/endpoint/templates/index.spec.js +++ b/endpoint/templates/index.spec.js @@ -37,7 +37,7 @@ describe('<%= classedName %> API Router:', function() { describe('GET <%= route %>', function() { it('should route to <%= name %>.controller.index', function() { - return router.get.withArgs('/', '<%= name %>Ctrl.index').should.have.been.calledOnce; + router.get.withArgs('/', '<%= name %>Ctrl.index').should.have.been.calledOnce; }); });<% if(filters.mongoose) { %> @@ -45,7 +45,7 @@ describe('<%= classedName %> API Router:', function() { 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; + router.get.withArgs('/:id', '<%= name %>Ctrl.show').should.have.been.calledOnce; }); }); @@ -53,7 +53,7 @@ describe('<%= classedName %> API Router:', function() { describe('POST <%= route %>', function() { it('should route to <%= name %>.controller.create', function() { - return router.post.withArgs('/', '<%= name %>Ctrl.create').should.have.been.calledOnce; + router.post.withArgs('/', '<%= name %>Ctrl.create').should.have.been.calledOnce; }); }); @@ -61,7 +61,7 @@ describe('<%= classedName %> API Router:', function() { 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; + router.put.withArgs('/:id', '<%= name %>Ctrl.update').should.have.been.calledOnce; }); }); @@ -69,7 +69,7 @@ describe('<%= classedName %> API Router:', function() { 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; + router.patch.withArgs('/:id', '<%= name %>Ctrl.update').should.have.been.calledOnce; }); }); @@ -77,7 +77,7 @@ describe('<%= classedName %> API Router:', function() { 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; + router.delete.withArgs('/:id', '<%= name %>Ctrl.destroy').should.have.been.calledOnce; }); });<% } %> diff --git a/endpoint/templates/name.controller.js b/endpoint/templates/name.controller.js index 1d9da544e..5851a1338 100644 --- a/endpoint/templates/name.controller.js +++ b/endpoint/templates/name.controller.js @@ -1,60 +1,94 @@ -'use strict'; +'use strict';<% if (filters.mongoose) { %> -var _ = require('lodash');<% if (filters.mongoose) { %> -var <%= classedName %> = require('./<%= name %>.model');<% } %> +var _ = require('lodash'); +var <%= classedName %> = require('./<%= name %>.model'); + +function handleError(res, statusCode){ + statusCode = statusCode || 500; + return function(err){ + res.send(statusCode, err); + }; +} + +function responseWithResult(res, statusCode){ + statusCode = statusCode || 200; + return function(entity){ + if(entity){ + return res.json(statusCode, entity); + } + }; +} + +function handleEntityNotFound(res){ + return function(entity){ + if(!entity){ + res.send(404); + return null; + } + return entity; + }; +} + +function saveUpdates(updates){ + return function(entity){ + var updated = _.merge(entity, updates); + return updated.saveAsync() + .then(function () { + return updated; + }); + }; +} + +function removeEntity(res){ + return function (entity) { + if(entity){ + return entity.removeAsync() + .then(function() { + return res.send(204); + }); + } + }; +}<% } %> // Get list of <%= name %>s exports.index = function(req, res) {<% if (!filters.mongoose) { %> - res.json([]);<% } %><% if (filters.mongoose) { %> - <%= classedName %>.find(function (err, <%= name %>s) { - if(err) { return handleError(res, err); } - return res.json(200, <%= name %>s); - });<% } %> + res.json([]);<% } if (filters.mongoose) { %> + <%= classedName %>.findAsync() + .then(responseWithResult(res)) + .catch(handleError(res));<% } %> };<% if (filters.mongoose) { %> // Get a single <%= name %> exports.show = function(req, res) { - <%= classedName %>.findById(req.params.id, function (err, <%= name %>) { - if(err) { return handleError(res, err); } - if(!<%= name %>) { return res.send(404); } - return res.json(<%= name %>); - }); + <%= classedName %>.findByIdAsync(req.params.id) + .then(handleEntityNotFound(res)) + .then(responseWithResult(res)) + .catch(handleError(res)); }; // Creates a new <%= name %> in the DB. exports.create = function(req, res) { - <%= classedName %>.create(req.body, function(err, <%= name %>) { - if(err) { return handleError(res, err); } - return res.json(201, <%= name %>); - }); + <%= classedName %>.createAsync(req.body) + .then(responseWithResult(res, 201)) + .catch(handleError(res)); }; // Updates an existing <%= name %> in the DB. exports.update = function(req, res) { - if(req.body._id) { delete req.body._id; } - <%= classedName %>.findById(req.params.id, function (err, <%= name %>) { - if (err) { return handleError(res, err); } - if(!<%= name %>) { return res.send(404); } - var updated = _.merge(<%= name %>, req.body); - updated.save(function (err) { - if (err) { return handleError(res, err); } - return res.json(200, <%= name %>); - }); - }); + if(req.body._id) { + delete req.body._id; + } + <%= classedName %>.findByIdAsync(req.params.id) + .then(handleEntityNotFound(res)) + .then(saveUpdates(req.body)) + .then(responseWithResult(res)) + .catch(handleError(res)); }; // Deletes a <%= name %> from the DB. exports.destroy = function(req, res) { - <%= classedName %>.findById(req.params.id, function (err, <%= name %>) { - if(err) { return handleError(res, err); } - if(!<%= name %>) { return res.send(404); } - <%= name %>.remove(function(err) { - if(err) { return handleError(res, err); } - return res.send(204); - }); - }); -}; - -function handleError(res, err) { - return res.send(500, err); -}<% } %> \ No newline at end of file + <%= classedName %>.findByIdAsync(req.params.id) + .then(handleEntityNotFound(res)) + .then(removeEntity(res)) + .catch(handleError(res)); +};<% } %> diff --git a/endpoint/templates/name.model(mongoose).js b/endpoint/templates/name.model(mongoose).js index 89e0dfaa7..9b23d9d41 100644 --- a/endpoint/templates/name.model(mongoose).js +++ b/endpoint/templates/name.model(mongoose).js @@ -1,6 +1,6 @@ 'use strict'; -var mongoose = require('mongoose'), +var mongoose = require('mongoose-bird')(), Schema = mongoose.Schema; var <%= classedName %>Schema = new Schema({ @@ -9,4 +9,4 @@ var <%= classedName %>Schema = new Schema({ active: Boolean }); -module.exports = mongoose.model('<%= classedName %>', <%= classedName %>Schema); \ No newline at end of file +module.exports = mongoose.model('<%= classedName %>', <%= classedName %>Schema); From 49d5bbdf5c8a59812e8f72ad5b95309894bea5ca Mon Sep 17 00:00:00 2001 From: kingcody Date: Sat, 6 Sep 2014 22:11:53 -0400 Subject: [PATCH 0009/1357] fix(gen): filter `client/components/socket` js files Changes: - add `(js)` filter to the js files in `client/components/socket` Closes #530 --- .../socket(socketio)/{socket.mock.js => socket.mock(js).js} | 0 .../socket(socketio)/{socket.service.js => socket.service(js).js} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename app/templates/client/components/socket(socketio)/{socket.mock.js => socket.mock(js).js} (100%) rename app/templates/client/components/socket(socketio)/{socket.service.js => socket.service(js).js} (100%) diff --git a/app/templates/client/components/socket(socketio)/socket.mock.js b/app/templates/client/components/socket(socketio)/socket.mock(js).js similarity index 100% rename from app/templates/client/components/socket(socketio)/socket.mock.js rename to app/templates/client/components/socket(socketio)/socket.mock(js).js diff --git a/app/templates/client/components/socket(socketio)/socket.service.js b/app/templates/client/components/socket(socketio)/socket.service(js).js similarity index 100% rename from app/templates/client/components/socket(socketio)/socket.service.js rename to app/templates/client/components/socket(socketio)/socket.service(js).js From c2ab8ae922ec0f2e377e560e937d09091e596b07 Mon Sep 17 00:00:00 2001 From: kingcody Date: Sat, 6 Sep 2014 21:53:07 -0400 Subject: [PATCH 0010/1357] test(gen): make tests more strict and DRY Changes: - `genFiles(ops)` creates an array of expected files based on options given - test for generated files on every set of tests - test for unexpected files - use testExec to be more DRY Exposes a bug with `client/components/socket`: `socket.service.js` and `socket.mock.js` are not filtered. See #530 --- package.json | 1 + test/test-file-creation.js | 416 +++++++++++++++++++++++++------------ 2 files changed, 287 insertions(+), 130 deletions(-) diff --git a/package.json b/package.json index cab669526..394f5e6d1 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "marked": "~0.2.8", "mocha": "~1.21.0", "q": "^1.0.1", + "recursive-readdir": "^1.2.0", "semver": "~2.2.1", "shelljs": "^0.3.0", "underscore.string": "^2.3.3" diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 2dc0ee548..2ea172b2e 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -1,11 +1,12 @@ /*global describe, beforeEach, it */ 'use strict'; var path = require('path'); +var fs = require('fs-extra'); +var exec = require('child_process').exec; var helpers = require('yeoman-generator').test; var chai = require('chai'); var expect = chai.expect; -var fs = require('fs-extra'); -var exec = require('child_process').exec; +var recursiveReadDir = require('recursive-readdir'); describe('angular-fullstack generator', function () { var gen, defaultOptions = { @@ -32,6 +33,201 @@ describe('angular-fullstack generator', function () { }); } + function assertOnlyFiles(expectedFiles, done, path, skip) { + path = path || './'; + skip = skip || ['e2e', 'node_modules', 'client/bower_components']; + + recursiveReadDir(path, skip, function(err, files) { + if (err) { return done(err); } + + for (var i = 0, expectedFilesLength = expectedFiles.length; i < expectedFilesLength; i++) { + var index = files.indexOf(expectedFiles[i]); + files.splice(index, 1); + } + + if (files.length !== 0) { + err = new Error('unexpected files found'); + err.expected = ''; + err.actual = files.join('\n'); + return done(err); + } + + done(); + }); + } + + function runTest(type, self, cb, timeout) { + self.timeout(timeout || 60000); + gen.run({}, function() { + exec(type, function(error, stdout, stderr) { + switch(type) { + case 'grunt test:client': + expect(stdout, 'Client tests failed \n' + stdout ).to.contain('Executed 1 of 1\u001b[32m SUCCESS\u001b'); + break; + case 'grunt jshint': + expect(stdout).to.contain('Done, without errors.'); + break; + case 'grunt test:server': + expect(stdout, 'Server tests failed (do you have mongoDB running?) \n' + stdout).to.contain('Done, without errors.'); + break; + default: + expect(stderr).to.be.empty; + } + + cb(); + }); + }); + } + + function genFiles(ops) { + var mapping = { + stylesheet: { + sass: 'scss', + stylus: 'styl', + less: 'less', + css: 'css' + }, + markup: { + jade: 'jade', + html: 'html' + }, + script: { + js: 'js', + coffee: 'coffee' + } + }, + files = []; + + var oauthFiles = function(type) { + return [ + 'server/auth/' + type + '/index.js', + 'server/auth/' + type + '/passport.js', + ]; + }; + + + var script = mapping.script[ops.script], + markup = mapping.markup[ops.markup], + stylesheet = mapping.stylesheet[ops.stylesheet]; + + files = files.concat([ + 'client/.htaccess', + 'client/.jshintrc', + 'client/favicon.ico', + 'client/robots.txt', + 'client/index.html', + 'client/app/app.' + script, + 'client/app/app.' + stylesheet, + 'client/app/main/main.' + script, + 'client/app/main/main.' + markup, + 'client/app/main/main.' + stylesheet, + 'client/app/main/main.controller.' + script, + 'client/app/main/main.controller.spec.' + script, + 'client/assets/images/yeoman.png', + 'client/components/navbar/navbar.' + markup, + 'client/components/navbar/navbar.controller.' + script, + 'server/.jshintrc', + 'server/.jshintrc-spec', + 'server/app.js', + 'server/routes.js', + 'server/api/thing/index.js', + 'server/api/thing/index.spec.js', + 'server/api/thing/thing.controller.js', + 'server/api/thing/thing.e2e.js', + 'server/components/errors/index.js', + 'server/config/local.env.js', + 'server/config/local.env.sample.js', + 'server/config/express.js', + 'server/config/environment/index.js', + 'server/config/environment/development.js', + 'server/config/environment/production.js', + 'server/config/environment/test.js', + 'server/views/404.' + markup, + '.bowerrc', + '.buildignore', + '.editorconfig', + '.gitattributes', + '.gitignore', + '.travis.yml', + '.yo-rc.json', + 'Gruntfile.js', + 'package.json', + 'bower.json', + 'karma.conf.js', + 'mocha.conf.js', + 'protractor.conf.js' + ]); + + if (ops.uibootstrap) { + files = files.concat([ + 'client/components/modal/modal.' + markup, + 'client/components/modal/modal.' + stylesheet, + 'client/components/modal/modal.service.' + script, + ]); + } + + if (ops.mongoose) { + files = files.concat([ + 'server/api/thing/thing.model.js', + 'server/config/seed.js' + ]); + } + + if (ops.auth) { + files = files.concat([ + 'client/app/account/account.' + script, + 'client/app/account/login/login.' + markup, + 'client/app/account/login/login.' + stylesheet, + 'client/app/account/login/login.controller.' + script, + 'client/app/account/settings/settings.' + markup, + 'client/app/account/settings/settings.controller.' + script, + 'client/app/account/signup/signup.' + markup, + 'client/app/account/signup/signup.controller.' + script, + 'client/app/admin/admin.' + markup, + 'client/app/admin/admin.' + stylesheet, + 'client/app/admin/admin.' + script, + 'client/app/admin/admin.controller.' + script, + 'client/components/auth/auth.service.' + script, + 'client/components/auth/user.service.' + script, + 'client/components/mongoose-error/mongoose-error.directive.' + script, + 'server/api/user/index.js', + 'server/api/user/index.spec.js', + 'server/api/user/user.controller.js', + 'server/api/user/user.e2e.js', + 'server/api/user/user.model.js', + 'server/api/user/user.model.spec.js', + 'server/auth/index.js', + 'server/auth/auth.service.js', + 'server/auth/local/index.js', + 'server/auth/local/passport.js' + ]); + } + + if (ops.oauth) { + var oauth = ops.oauth; + for (var i = 0, oauthLength = oauth.length; i < oauthLength; i++) { + files = files.concat(oauthFiles(oauth[i].replace('Auth', ''))); + } + } + + if (ops.socketio) { + files = files.concat([ + 'client/components/socket/socket.service.' + script, + 'client/components/socket/socket.mock.' + script, + 'server/api/thing/thing.socket.js', + 'server/config/socketio.js' + ]); + } + + return files; + } + + function everyFile(files, ops) { + ops = ops || { + skip: ['node_modules', 'client/bower_components', 'e2e'] + } + } + beforeEach(function (done) { this.timeout(10000); var deps = [ @@ -68,33 +264,15 @@ describe('angular-fullstack generator', function () { }); it('should run client tests successfully', function(done) { - this.timeout(60000); - gen.run({}, function () { - exec('grunt test:client', function (error, stdout, stderr) { - expect(stdout, 'Client tests failed \n' + stdout ).to.contain('Executed 1 of 1\u001b[32m SUCCESS\u001b'); - done(); - }); - }); + runTest('grunt test:client', this, done); }); it('should pass jshint', function(done) { - this.timeout(60000); - gen.run({}, function () { - exec('grunt jshint', function (error, stdout, stderr) { - expect(stdout).to.contain('Done, without errors.'); - done(); - }); - }); + runTest('grunt jshint', this, done); }); it('should run server tests successfully', function(done) { - this.timeout(60000); - gen.run({}, function () { - exec('grunt test:server', function (error, stdout, stderr) { - expect(stdout, 'Server tests failed (do you have mongoDB running?) \n' + stdout).to.contain('Done, without errors.'); - done(); - }); - }); + runTest('grunt test:server', this, done); }); it('should run server tests successfully with generated endpoint', function(done) { @@ -130,6 +308,19 @@ describe('angular-fullstack generator', function () { }); }); + it('should generate expected files', function (done) { + gen.run({}, function () { + helpers.assertFile(genFiles(defaultOptions)); + done(); + }); + }); + + it('should not generate unexpected files', function (done) { + gen.run({}, function () { + assertOnlyFiles(genFiles(defaultOptions), done); + }); + }); + // it('should run e2e tests successfully', function(done) { // this.timeout(80000); // gen.run({}, function () { @@ -144,166 +335,131 @@ describe('angular-fullstack generator', function () { }); describe('with other preprocessors and oauth', function() { + var testOptions = { + script: 'coffee', + markup: 'jade', + stylesheet: 'less', + router: 'uirouter', + mongoose: true, + auth: true, + oauth: ['twitterAuth', 'facebookAuth', 'googleAuth'], + socketio: true + }; + beforeEach(function() { - helpers.mockPrompt(gen, { - script: 'coffee', - markup: 'jade', - stylesheet: 'less', - router: 'uirouter', - mongoose: true, - auth: true, - oauth: ['twitterAuth', 'facebookAuth', 'googleAuth'], - socketio: true - }); + helpers.mockPrompt(gen, testOptions); }); it('should run client tests successfully', function(done) { - this.timeout(60000); - gen.run({}, function () { - exec('grunt test:client', function (error, stdout, stderr) { - expect(stdout, 'Client tests failed \n' + stdout ).to.contain('Executed 1 of 1\u001b[32m SUCCESS\u001b'); - done(); - }); - }); + runTest('grunt test:client', this, done); }); it('should pass jshint', function(done) { - this.timeout(60000); + runTest('grunt jshint', this, done); + }); + + it('should run server tests successfully', function(done) { + runTest('grunt test:server', this, done); + }); + + it('should generate expected files', function (done) { gen.run({}, function () { - exec('grunt jshint', function (error, stdout, stderr) { - expect(stdout).to.contain('Done, without errors.'); - done(); - }); + helpers.assertFile(genFiles(testOptions)); + done(); }); }); - it('should run server tests successfully', function(done) { - this.timeout(60000); + it('should not generate unexpected files', function (done) { gen.run({}, function () { - exec('grunt test:server', function (error, stdout, stderr) { - expect(stdout, 'Server tests failed (do you have mongoDB running?) \n' + stdout).to.contain('Done, without errors.'); - done(); - }); + assertOnlyFiles(genFiles(testOptions), done); }); }); }); describe('with other preprocessors and no server options', function() { + var testOptions = { + script: 'coffee', + markup: 'jade', + stylesheet: 'stylus', + router: 'ngroute', + mongoose: false, + auth: false, + oauth: [], + socketio: false + }; + beforeEach(function(done) { - helpers.mockPrompt(gen, { - script: 'coffee', - markup: 'jade', - stylesheet: 'stylus', - router: 'ngroute', - mongoose: false, - auth: false, - oauth: [], - socketio: false - }); + helpers.mockPrompt(gen, testOptions); done(); }); it('should run client tests successfully', function(done) { - this.timeout(60000); - gen.run({}, function () { - exec('grunt test:client', function (error, stdout, stderr) { - expect(stdout, 'Client tests failed \n' + stdout ).to.contain('Executed 1 of 1\u001b[32m SUCCESS\u001b'); - done(); - }); - }); + runTest('grunt test:client', this, done); }); it('should pass jshint', function(done) { - this.timeout(60000); + runTest('grunt jshint', this, done); + }); + + it('should run server tests successfully', function(done) { + runTest('grunt test:server', this, done); + }); + + it('should generate expected files', function (done) { gen.run({}, function () { - exec('grunt jshint', function (error, stdout, stderr) { - expect(stdout).to.contain('Done, without errors.'); - done(); - }); + helpers.assertFile(genFiles(testOptions)); + done(); }); }); - it('should run server tests successfully', function(done) { - this.timeout(60000); + it('should not generate unexpected files', function (done) { gen.run({}, function () { - exec('grunt test:server', function (error, stdout, stderr) { - expect(stdout, 'Server tests failed (do you have mongoDB running?) \n' + stdout).to.contain('Done, without errors.'); - done(); - }); + assertOnlyFiles(genFiles(testOptions), done); }); }); }); describe('with no preprocessors and no server options', function() { + var testOptions = { + script: 'js', + markup: 'html', + stylesheet: 'css', + router: 'ngroute', + mongoose: false, + auth: false, + oauth: [], + socketio: false + }; + beforeEach(function(done) { - helpers.mockPrompt(gen, { - script: 'js', - markup: 'html', - stylesheet: 'css', - router: 'ngroute', - mongoose: false, - auth: false, - oauth: [], - socketio: false - }); + helpers.mockPrompt(gen, testOptions); done(); }); it('should run client tests successfully', function(done) { - this.timeout(60000); - gen.run({}, function () { - exec('grunt test:client', function (error, stdout, stderr) { - expect(stdout, 'Client tests failed \n' + stdout ).to.contain('Executed 1 of 1\u001b[32m SUCCESS\u001b'); - done(); - }); - }); + runTest('grunt test:client', this, done); }); it('should pass jshint', function(done) { - this.timeout(60000); - gen.run({}, function () { - exec('grunt jshint', function (error, stdout, stderr) { - expect(stdout).to.contain('Done, without errors.'); - done(); - }); - }); + runTest('grunt jshint', this, done); }); it('should run server tests successfully', function(done) { - this.timeout(60000); - gen.run({}, function () { - exec('grunt test:server', function (error, stdout, stderr) { - expect(stdout, 'Server tests failed (do you have mongoDB running?) \n' + stdout).to.contain('Done, without errors.'); - done(); - }); - }); + runTest('grunt test:server', this, done); }); it('should generate expected files', function (done) { - helpers.mockPrompt(gen, defaultOptions); - gen.run({}, function () { - helpers.assertFile([ - 'client/.htaccess', - 'client/favicon.ico', - 'client/robots.txt', - 'client/app/main/main.scss', - 'client/app/main/main.html', - 'client/index.html', - 'client/.jshintrc', - 'client/assets/images/yeoman.png', - '.bowerrc', - '.editorconfig', - '.gitignore', - 'Gruntfile.js', - 'package.json', - 'bower.json', - 'server/app.js', - 'server/config/express.js', - 'server/api/thing/index.js']); + helpers.assertFile(genFiles(testOptions)); done(); }); }); + + it('should not generate unexpected files', function (done) { + gen.run({}, function () { + assertOnlyFiles(genFiles(testOptions), done); + }); + }); }); }); }); From 3536b4577821734dff86cf6d8c47e501abb28da4 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Tue, 9 Sep 2014 22:33:21 -0600 Subject: [PATCH 0011/1357] fix unexpected files created in tests --- test/test-file-creation.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test/test-file-creation.js b/test/test-file-creation.js index c8d26917b..f5a753375 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -345,7 +345,9 @@ describe('angular-fullstack generator', function () { mongoose: true, auth: true, oauth: ['twitterAuth', 'facebookAuth', 'googleAuth'], - socketio: true + socketio: true, + bootstrap: true, + uibootstrap: true }; beforeEach(function() { @@ -387,7 +389,9 @@ describe('angular-fullstack generator', function () { mongoose: false, auth: false, oauth: [], - socketio: false + socketio: false, + bootstrap: false, + uibootstrap: false }; beforeEach(function(done) { @@ -430,7 +434,9 @@ describe('angular-fullstack generator', function () { mongoose: false, auth: false, oauth: [], - socketio: false + socketio: false, + bootstrap: true, + uibootstrap: true }; beforeEach(function(done) { From cf6ae006f5dfd318f8234910365fa13c69336509 Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 10 Sep 2014 08:52:09 -0400 Subject: [PATCH 0012/1357] test(gen): clean up code and test more endpoint combinations Changes: - remove unneeded code - use runTest for endpoints as well - test endpoints with different options - test endpoints with various cased named Exposes Bug: See #540 --- test/test-file-creation.js | 94 ++++++++++++++++++++++++++------------ 1 file changed, 64 insertions(+), 30 deletions(-) diff --git a/test/test-file-creation.js b/test/test-file-creation.js index f5a753375..b6171fabd 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -39,13 +39,16 @@ describe('angular-fullstack generator', function () { path = path || './'; skip = skip || ['e2e', 'node_modules', 'client/bower_components']; - recursiveReadDir(path, skip, function(err, files) { + recursiveReadDir(path, skip, function(err, actualFiles) { if (err) { return done(err); } + var files = actualFiles.concat(); - for (var i = 0, expectedFilesLength = expectedFiles.length; i < expectedFilesLength; i++) { - var index = files.indexOf(expectedFiles[i]); - files.splice(index, 1); - } + expectedFiles.forEach(function(file, i) { + var index = files.indexOf(file); + if (index >= 0) { + files.splice(index, 1); + } + }); if (files.length !== 0) { err = new Error('unexpected files found'); @@ -58,11 +61,16 @@ describe('angular-fullstack generator', function () { }); } - function runTest(type, self, cb, timeout) { + function runTest(cmd, self, cb) { + var args = Array.prototype.slice.call(arguments), + endpoint = (args[3] && typeof args[3] === 'string') ? args.splice(3, 1)[0] : null, + timeout = (args[3] && typeof args[3] === 'number') ? args.splice(3, 1)[0] : null; + self.timeout(timeout || 60000); - gen.run({}, function() { - exec(type, function(error, stdout, stderr) { - switch(type) { + + var execFn = function() { + exec(cmd, function(error, stdout, stderr) { + switch(cmd) { case 'grunt test:client': expect(stdout, 'Client tests failed \n' + stdout ).to.contain('Executed 1 of 1\u001b[32m SUCCESS\u001b'); break; @@ -78,7 +86,13 @@ describe('angular-fullstack generator', function () { cb(); }); - }); + }; + + if (endpoint) { + generatorTest('endpoint', endpoint, {}, execFn); + } else { + gen.run({}, execFn); + } } function genFiles(ops) { @@ -206,10 +220,9 @@ describe('angular-fullstack generator', function () { } if (ops.oauth) { - var oauth = ops.oauth; - for (var i = 0, oauthLength = oauth.length; i < oauthLength; i++) { - files = files.concat(oauthFiles(oauth[i].replace('Auth', ''))); - } + ops.oauth.forEach(function(type, i) { + files = files.concat(oauthFiles(type.replace('Auth', ''))); + }); } if (ops.socketio) { @@ -224,11 +237,10 @@ describe('angular-fullstack generator', function () { return files; } - function everyFile(files, ops) { - ops = ops || { - skip: ['node_modules', 'client/bower_components', 'e2e'] - } - } + + /** + * Generator tests + */ beforeEach(function (done) { this.timeout(10000); @@ -269,7 +281,7 @@ describe('angular-fullstack generator', function () { runTest('grunt test:client', this, done); }); - it('should pass jshint', function(done) { + it('should pass lint', function(done) { runTest('grunt jshint', this, done); }); @@ -277,14 +289,20 @@ describe('angular-fullstack generator', function () { runTest('grunt test:server', this, done); }); + it('should pass lint with generated endpoint', function(done) { + runTest('grunt jshint', this, done, 'foo'); + }); + it('should run server tests successfully with generated endpoint', function(done) { - this.timeout(60000); - generatorTest('endpoint', 'foo', {}, function() { - exec('grunt test:server', function (error, stdout, stderr) { - expect(stdout, 'Server tests failed (do you have mongoDB running?) \n' + stdout).to.contain('Done, without errors.'); - done(); - }); - }); + runTest('grunt test:server', this, done, 'foo'); + }); + + it('should pass lint with generated capitalized endpoint', function(done) { + runTest('grunt jshint', this, done, 'Foo'); + }); + + it('should run server tests successfully with generated capitalized endpoint', function(done) { + runTest('grunt test:server', this, done, 'Foo'); }); it('should use existing config if available', function(done) { @@ -358,7 +376,7 @@ describe('angular-fullstack generator', function () { runTest('grunt test:client', this, done); }); - it('should pass jshint', function(done) { + it('should pass lint', function(done) { runTest('grunt jshint', this, done); }); @@ -366,6 +384,14 @@ describe('angular-fullstack generator', function () { runTest('grunt test:server', this, done); }); + it('should pass lint with generated snake-case endpoint', function(done) { + runTest('grunt jshint', this, done, 'foo-bar'); + }); + + it('should run server tests successfully with generated snake-case endpoint', function(done) { + runTest('grunt test:server', this, done, 'foo-bar'); + }); + it('should generate expected files', function (done) { gen.run({}, function () { helpers.assertFile(genFiles(testOptions)); @@ -403,7 +429,7 @@ describe('angular-fullstack generator', function () { runTest('grunt test:client', this, done); }); - it('should pass jshint', function(done) { + it('should pass lint', function(done) { runTest('grunt jshint', this, done); }); @@ -411,6 +437,14 @@ describe('angular-fullstack generator', function () { runTest('grunt test:server', this, done); }); + it('should pass lint with generated endpoint', function(done) { + runTest('grunt jshint', this, done, 'foo'); + }); + + it('should run server tests successfully with generated endpoint', function(done) { + runTest('grunt test:server', this, done, 'foo'); + }); + it('should generate expected files', function (done) { gen.run({}, function () { helpers.assertFile(genFiles(testOptions)); @@ -448,7 +482,7 @@ describe('angular-fullstack generator', function () { runTest('grunt test:client', this, done); }); - it('should pass jshint', function(done) { + it('should pass lint', function(done) { runTest('grunt jshint', this, done); }); From 73620809a83c2a7ab5c3d6a81f67f8bb56f8fdb7 Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 10 Sep 2014 09:32:07 -0400 Subject: [PATCH 0013/1357] fix(gen): camelCase endpoint name when used in variable name Closes #540 --- endpoint/templates/index.spec.js | 4 ++-- endpoint/templates/name.controller.js | 30 +++++++++++++-------------- endpoint/templates/name.e2e.js | 16 +++++++------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/endpoint/templates/index.spec.js b/endpoint/templates/index.spec.js index 62caed5dc..74c17d539 100644 --- a/endpoint/templates/index.spec.js +++ b/endpoint/templates/index.spec.js @@ -3,7 +3,7 @@ var proxyquire = require('proxyquire').noPreserveCache(); /* <%= name %>.controller stub */ -var <%= name %>Ctrl = { +var <%= cameledName %>Ctrl = { index: '<%= name %>Ctrl.index'<% if(filters.mongoose) { %>, show: '<%= name %>Ctrl.show', create: '<%= name %>Ctrl.create', @@ -25,7 +25,7 @@ var <%= name %>Ctrl = { return router; } }, - './<%= name %>.controller': <%= name %>Ctrl + './<%= name %>.controller': <%= cameledName %>Ctrl }); describe('<%= classedName %> API Router:', function() { diff --git a/endpoint/templates/name.controller.js b/endpoint/templates/name.controller.js index 1d9da544e..3b2bbc918 100644 --- a/endpoint/templates/name.controller.js +++ b/endpoint/templates/name.controller.js @@ -6,49 +6,49 @@ var <%= classedName %> = require('./<%= name %>.model');<% } %> // Get list of <%= name %>s exports.index = function(req, res) {<% if (!filters.mongoose) { %> res.json([]);<% } %><% if (filters.mongoose) { %> - <%= classedName %>.find(function (err, <%= name %>s) { + <%= classedName %>.find(function (err, <%= cameledName %>s) { if(err) { return handleError(res, err); } - return res.json(200, <%= name %>s); + return res.json(200, <%= cameledName %>s); });<% } %> };<% if (filters.mongoose) { %> // Get a single <%= name %> exports.show = function(req, res) { - <%= classedName %>.findById(req.params.id, function (err, <%= name %>) { + <%= classedName %>.findById(req.params.id, function (err, <%= cameledName %>) { if(err) { return handleError(res, err); } - if(!<%= name %>) { return res.send(404); } - return res.json(<%= name %>); + if(!<%= cameledName %>) { return res.send(404); } + return res.json(<%= cameledName %>); }); }; // Creates a new <%= name %> in the DB. exports.create = function(req, res) { - <%= classedName %>.create(req.body, function(err, <%= name %>) { + <%= classedName %>.create(req.body, function(err, <%= cameledName %>) { if(err) { return handleError(res, err); } - return res.json(201, <%= name %>); + return res.json(201, <%= cameledName %>); }); }; // Updates an existing <%= name %> in the DB. exports.update = function(req, res) { if(req.body._id) { delete req.body._id; } - <%= classedName %>.findById(req.params.id, function (err, <%= name %>) { + <%= classedName %>.findById(req.params.id, function (err, <%= cameledName %>) { if (err) { return handleError(res, err); } - if(!<%= name %>) { return res.send(404); } - var updated = _.merge(<%= name %>, req.body); + if(!<%= cameledName %>) { return res.send(404); } + var updated = _.merge(<%= cameledName %>, req.body); updated.save(function (err) { if (err) { return handleError(res, err); } - return res.json(200, <%= name %>); + return res.json(200, <%= cameledName %>); }); }); }; // Deletes a <%= name %> from the DB. exports.destroy = function(req, res) { - <%= classedName %>.findById(req.params.id, function (err, <%= name %>) { + <%= classedName %>.findById(req.params.id, function (err, <%= cameledName %>) { if(err) { return handleError(res, err); } - if(!<%= name %>) { return res.send(404); } - <%= name %>.remove(function(err) { + if(!<%= cameledName %>) { return res.send(404); } + <%= cameledName %>.remove(function(err) { if(err) { return handleError(res, err); } return res.send(204); }); @@ -57,4 +57,4 @@ exports.destroy = function(req, res) { function handleError(res, err) { return res.send(500, err); -}<% } %> \ No newline at end of file +}<% } %> diff --git a/endpoint/templates/name.e2e.js b/endpoint/templates/name.e2e.js index 5960b40a2..f168f1ca9 100644 --- a/endpoint/templates/name.e2e.js +++ b/endpoint/templates/name.e2e.js @@ -8,7 +8,7 @@ var new<%= classedName %>;<% } %> describe('<%= classedName %> API:', function() { describe('GET <%= route %>', function() { - var <%= name %>s; + var <%= cameledName %>s; beforeEach(function(done) { request(app) @@ -17,13 +17,13 @@ describe('<%= classedName %> API:', function() { .expect('Content-Type', /json/) .end(function(err, res) { if (err) return done(err); - <%= name %>s = res.body; + <%= cameledName %>s = res.body; done(); }); }); it('should respond with JSON array', function() { - <%= name %>s.should.be.instanceOf(Array); + <%= cameledName %>s.should.be.instanceOf(Array); }); });<% if(filters.mongoose) { %> @@ -53,7 +53,7 @@ describe('<%= classedName %> API:', function() { }); describe('GET <%= route %>/:id', function() { - var <%= name %>; + var <%= cameledName %>; beforeEach(function(done) { request(app) @@ -62,18 +62,18 @@ describe('<%= classedName %> API:', function() { .expect('Content-Type', /json/) .end(function(err, res) { if (err) return done(err); - <%= name %> = res.body; + <%= cameledName %> = res.body; done(); }); }); afterEach(function() { - <%= name %> = {}; + <%= cameledName %> = {}; }); it('should respond with the requested <%= name %>', function() { - <%= name %>.name.should.equal('New <%= classedName %>'); - <%= name %>.info.should.equal('This is the brand new <%= name %>!!!'); + <%= cameledName %>.name.should.equal('New <%= classedName %>'); + <%= cameledName %>.info.should.equal('This is the brand new <%= name %>!!!'); }); }); From ac8f335922bd77aa0781ebd4281b8b1b9186f18d Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sun, 14 Sep 2014 18:23:01 -0600 Subject: [PATCH 0014/1357] style(package): remove unneeded line break --- app/templates/_package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 2d8337b71..1912903fa 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -16,8 +16,7 @@ "jade": "~1.2.0",<% } %><% if(filters.html) { %> "ejs": "~0.8.4",<% } %><% if(filters.mongoose) { %> "mongoose": "~3.8.8", - "mongoose-bird": "~0.0.1", - <% } %><% if(filters.auth) { %> + "mongoose-bird": "~0.0.1",<% } %><% if(filters.auth) { %> "jsonwebtoken": "^0.3.0", "express-jwt": "^0.1.3", "passport": "~0.2.0", From 502be54d092ff1312a7d065da47dbe3d5ec3490e Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sun, 14 Sep 2014 18:25:38 -0600 Subject: [PATCH 0015/1357] remove fixtures that should not be git ignored --- .gitignore | 4 ++-- test/fixtures/package.json | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 9e436b36f..78a6835b7 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,5 @@ demo .idea .DS_Store release.txt -fixtures/bower.json -fixtures/package.json \ No newline at end of file +test/fixtures/bower.json +test/fixtures/package.json \ No newline at end of file diff --git a/test/fixtures/package.json b/test/fixtures/package.json index 2304c008e..48d48607e 100644 --- a/test/fixtures/package.json +++ b/test/fixtures/package.json @@ -16,6 +16,7 @@ "jade": "~1.2.0", "ejs": "~0.8.4", "mongoose": "~3.8.8", + "mongoose-bird": "~0.0.1", "jsonwebtoken": "^0.3.0", "express-jwt": "^0.1.3", "passport": "~0.2.0", @@ -46,7 +47,7 @@ "grunt-contrib-watch": "~0.6.1", "grunt-contrib-coffee": "^0.10.1", "grunt-contrib-jade": "^0.11.0", - "grunt-contrib-less": "^0.11.0", + "grunt-contrib-less": "^0.11.4", "grunt-google-cdn": "~0.4.0", "grunt-newer": "~0.7.0", "grunt-ng-annotate": "^0.2.3", From 65d03fc8a39590e09ef36740707fdc883739e135 Mon Sep 17 00:00:00 2001 From: kingcody Date: Sun, 17 Aug 2014 03:48:29 -0400 Subject: [PATCH 0016/1357] feat(app-auth): Improve client-side Auth service Changes: - getCurrentUser, isLoggedIn, and isAdmin are now sync if no arg and async with an arg - Use Error first callback signature where applicable - Remove unused arguments from Auth service - Remove isLoggedInAsync - Switch use of isLoggedInAsync to isLoggedIn - Add/Improve comments - Fix client/app/account(auth)/settings/settings.controller(js).js Breaking Changes: - Callbacks that return Errors, use 'Error first' signature Closes #456 --- app/templates/client/app/app(coffee).coffee | 4 +- app/templates/client/app/app(js).js | 4 +- .../auth(auth)/auth.service(coffee).coffee | 93 +++++++----- .../components/auth(auth)/auth.service(js).js | 140 ++++++++++-------- 4 files changed, 136 insertions(+), 105 deletions(-) diff --git a/app/templates/client/app/app(coffee).coffee b/app/templates/client/app/app(coffee).coffee index ea9ae3c95..9c0a87a0e 100644 --- a/app/templates/client/app/app(coffee).coffee +++ b/app/templates/client/app/app(coffee).coffee @@ -34,6 +34,6 @@ angular.module '<%= scriptAppName %>', [<%= angularModules %>] .run ($rootScope, $location, Auth) -> # Redirect to login if route requires auth and you're not logged in $rootScope.$on <% if(filters.ngroute) { %>'$routeChangeStart'<% } %><% if(filters.uirouter) { %>'$stateChangeStart'<% } %>, (event, next) -> - Auth.isLoggedInAsync (loggedIn) -> + Auth.isLoggedIn (loggedIn) -> $location.path "/login" if next.authenticate and not loggedIn -<% } %> \ No newline at end of file +<% } %> diff --git a/app/templates/client/app/app(js).js b/app/templates/client/app/app(js).js index eef485d7c..4e6adea0c 100644 --- a/app/templates/client/app/app(js).js +++ b/app/templates/client/app/app(js).js @@ -46,10 +46,10 @@ angular.module('<%= scriptAppName %>', [<%= angularModules %>]) .run(function ($rootScope, $location, Auth) { // Redirect to login if route requires auth and you're not logged in $rootScope.$on(<% if(filters.ngroute) { %>'$routeChangeStart'<% } %><% if(filters.uirouter) { %>'$stateChangeStart'<% } %>, function (event, next) { - Auth.isLoggedInAsync(function(loggedIn) { + Auth.isLoggedIn(function(loggedIn) { if (next.authenticate && !loggedIn) { $location.path('/login'); } }); }); - })<% } %>; \ No newline at end of file + })<% } %>; diff --git a/app/templates/client/components/auth(auth)/auth.service(coffee).coffee b/app/templates/client/components/auth(auth)/auth.service(coffee).coffee index ac503ed0b..4131efe53 100644 --- a/app/templates/client/components/auth(auth)/auth.service(coffee).coffee +++ b/app/templates/client/components/auth(auth)/auth.service(coffee).coffee @@ -1,40 +1,35 @@ 'use strict' angular.module '<%= scriptAppName %>' -.factory 'Auth', ($location, $rootScope, $http, User, $cookieStore, $q) -> +.factory 'Auth', ($http, User, $cookieStore, $q) -> currentUser = if $cookieStore.get 'token' then User.get() else {} ### Authenticate user and save token @param {Object} user - login info - @param {Function} callback - optional + @param {Function} callback - optional, function(error) @return {Promise} ### login: (user, callback) -> - deferred = $q.defer() $http.post '/auth/local', email: user.email password: user.password - .success (data) -> - $cookieStore.put 'token', data.token + .then (res) -> + $cookieStore.put 'token', res.data.token currentUser = User.get() - deferred.resolve data callback?() + res.data - .error (err) => + , (err) => @logout() - deferred.reject err - callback? err - - deferred.promise + callback? err.data + $q.reject err.data ### Delete access token and user info - - @param {Function} ### logout: -> $cookieStore.remove 'token' @@ -46,7 +41,7 @@ angular.module '<%= scriptAppName %>' Create a new user @param {Object} user - user info - @param {Function} callback - optional + @param {Function} callback - optional, function(error, user) @return {Promise} ### createUser: (user, callback) -> @@ -54,7 +49,7 @@ angular.module '<%= scriptAppName %>' (data) -> $cookieStore.put 'token', data.token currentUser = User.get() - callback? user + callback? null, user , (err) => @logout() @@ -68,7 +63,7 @@ angular.module '<%= scriptAppName %>' @param {String} oldPassword @param {String} newPassword - @param {Function} callback - optional + @param {Function} callback - optional, function(error, user) @return {Promise} ### changePassword: (oldPassword, newPassword, callback) -> @@ -79,7 +74,7 @@ angular.module '<%= scriptAppName %>' newPassword: newPassword , (user) -> - callback? user + callback? null, user , (err) -> callback? err @@ -88,45 +83,61 @@ angular.module '<%= scriptAppName %>' ### - Gets all available info on authenticated user + Gets all available info on a user + (synchronous|asynchronous) - @return {Object} user + @param {Function|*} callback - optional, funciton(user) + @return {Object|Promise} ### - getCurrentUser: -> - currentUser + getCurrentUser: (callback) -> + return currentUser if arguments.length is 0 + value = if (currentUser.hasOwnProperty("$promise")) then currentUser.$promise else currentUser + $q.when value - ### - Check if a user is logged in synchronously + .then (user) -> + callback? user + user - @return {Boolean} - ### - isLoggedIn: -> - currentUser.hasOwnProperty 'role' + , -> + callback? {} + {} ### - Waits for currentUser to resolve before checking if user is logged in + Check if a user is logged in + (synchronous|asynchronous) + + @param {Function|*} callback - optional, function(is) + @return {Bool|Promise} ### - isLoggedInAsync: (callback) -> - if currentUser.hasOwnProperty '$promise' - currentUser.$promise.then -> - callback? true - return - .catch -> - callback? false - return + isLoggedIn: (callback) -> + return currentUser.hasOwnProperty("role") if arguments.length is 0 + + @getCurrentUser null + + .then (user) -> + is_ = user.hasOwnProperty("role") + callback? is_ + is_ - else - callback? currentUser.hasOwnProperty 'role' ### Check if a user is an admin + (synchronous|asynchronous) - @return {Boolean} + @param {Function|*} callback - optional, function(is) + @return {Bool|Promise} ### - isAdmin: -> - currentUser.role is 'admin' + isAdmin: (callback) -> + return currentUser.role is "admin" if arguments_.length is 0 + + @getCurrentUser null + + .then (user) -> + is_ = user.role is "admin" + callback? is_ + is_ ### diff --git a/app/templates/client/components/auth(auth)/auth.service(js).js b/app/templates/client/components/auth(auth)/auth.service(js).js index 9afb12da9..5baf0e0b4 100644 --- a/app/templates/client/components/auth(auth)/auth.service(js).js +++ b/app/templates/client/components/auth(auth)/auth.service(js).js @@ -1,9 +1,20 @@ 'use strict'; angular.module('<%= scriptAppName %>') - .factory('Auth', function Auth($location, $rootScope, $http, User, $cookieStore, $q) { - var currentUser = {}; - if($cookieStore.get('token')) { + .factory('Auth', function Auth($http, User, $cookieStore, $q) { + /** + * Return a callback or noop function + * + * @param {Function|*} cb - a 'potential' function + * @return {Function} + */ + var safeCb = function(cb) { + return (angular.isFunction(cb)) ? cb : angular.noop; + }, + + currentUser = {}; + + if ($cookieStore.get('token')) { currentUser = User.get(); } @@ -13,36 +24,28 @@ angular.module('<%= scriptAppName %>') * Authenticate user and save token * * @param {Object} user - login info - * @param {Function} callback - optional + * @param {Function} callback - optional, function(error) * @return {Promise} */ login: function(user, callback) { - var cb = callback || angular.noop; - var deferred = $q.defer(); - - $http.post('/auth/local', { + return $http.post('/auth/local', { email: user.email, password: user.password - }). - success(function(data) { - $cookieStore.put('token', data.token); + }) + .then(function(res) { + $cookieStore.put('token', res.data.token); currentUser = User.get(); - deferred.resolve(data); - return cb(); - }). - error(function(err) { + safeCb(callback)(); + return res.data; + }, function(err) { this.logout(); - deferred.reject(err); - return cb(err); + safeCb(callback)(err.data); + return $q.reject(err.data); }.bind(this)); - - return deferred.promise; }, /** * Delete access token and user info - * - * @param {Function} */ logout: function() { $cookieStore.remove('token'); @@ -53,21 +56,19 @@ angular.module('<%= scriptAppName %>') * Create a new user * * @param {Object} user - user info - * @param {Function} callback - optional + * @param {Function} callback - optional, function(error, user) * @return {Promise} */ createUser: function(user, callback) { - var cb = callback || angular.noop; - return User.save(user, function(data) { $cookieStore.put('token', data.token); currentUser = User.get(); - return cb(user); + return safeCb(callback)(null, user); }, function(err) { this.logout(); - return cb(err); + return safeCb(callback)(err); }.bind(this)).$promise; }, @@ -76,68 +77,87 @@ angular.module('<%= scriptAppName %>') * * @param {String} oldPassword * @param {String} newPassword - * @param {Function} callback - optional + * @param {Function} callback - optional, function(error, user) * @return {Promise} */ changePassword: function(oldPassword, newPassword, callback) { - var cb = callback || angular.noop; - return User.changePassword({ id: currentUser._id }, { oldPassword: oldPassword, newPassword: newPassword }, function(user) { - return cb(user); + return safeCb(callback)(null, user); }, function(err) { - return cb(err); + return safeCb(callback)(err); }).$promise; }, /** - * Gets all available info on authenticated user + * Gets all available info on a user + * (synchronous|asynchronous) * - * @return {Object} user + * @param {Function|*} callback - optional, funciton(user) + * @return {Object|Promise} */ - getCurrentUser: function() { - return currentUser; + getCurrentUser: function(callback) { + if (arguments.length === 0) { + return currentUser; + } + + var value = (currentUser.hasOwnProperty('$promise')) ? currentUser.$promise : currentUser; + return $q.when(value) + .then(function(user) { + safeCb(callback)(user); + return user; + }, function() { + safeCb(callback)({}); + return {}; + }); }, /** * Check if a user is logged in + * (synchronous|asynchronous) * - * @return {Boolean} + * @param {Function|*} callback - optional, function(is) + * @return {Bool|Promise} */ - isLoggedIn: function() { - return currentUser.hasOwnProperty('role'); - }, + isLoggedIn: function(callback) { + if (arguments.length === 0) { + return currentUser.hasOwnProperty('role'); + } - /** - * Waits for currentUser to resolve before checking if user is logged in - */ - isLoggedInAsync: function(cb) { - if(currentUser.hasOwnProperty('$promise')) { - currentUser.$promise.then(function() { - cb(true); - }).catch(function() { - cb(false); + return this.getCurrentUser(null) + .then(function(user) { + var is = user.hasOwnProperty('role'); + safeCb(callback)(is); + return is; }); - } else if(currentUser.hasOwnProperty('role')) { - cb(true); - } else { - cb(false); - } }, - /** - * Check if a user is an admin - * - * @return {Boolean} - */ - isAdmin: function() { - return currentUser.role === 'admin'; + /** + * Check if a user is an admin + * (synchronous|asynchronous) + * + * @param {Function|*} callback - optional, function(is) + * @return {Bool|Promise} + */ + isAdmin: function(callback) { + if (arguments.length === 0) { + return currentUser.role === 'admin'; + } + + return this.getCurrentUser(null) + .then(function(user) { + var is = user.role === 'admin'; + safeCb(callback)(is); + return is; + }); }, /** * Get auth token + * + * @return {String} - a token string used for authenticating */ getToken: function() { return $cookieStore.get('token'); From 2aaff12d3559770ee2e9bdd8a856ef808e713010 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Tue, 16 Sep 2014 23:41:46 -0600 Subject: [PATCH 0017/1357] fix typo --- .../client/components/auth(auth)/auth.service(coffee).coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/client/components/auth(auth)/auth.service(coffee).coffee b/app/templates/client/components/auth(auth)/auth.service(coffee).coffee index 4131efe53..1d4b29544 100644 --- a/app/templates/client/components/auth(auth)/auth.service(coffee).coffee +++ b/app/templates/client/components/auth(auth)/auth.service(coffee).coffee @@ -130,7 +130,7 @@ angular.module '<%= scriptAppName %>' @return {Bool|Promise} ### isAdmin: (callback) -> - return currentUser.role is "admin" if arguments_.length is 0 + return currentUser.role is "admin" if arguments.length is 0 @getCurrentUser null From 6aadee6d956cefb9a787eb0851d287654dfca111 Mon Sep 17 00:00:00 2001 From: kingcody Date: Fri, 15 Aug 2014 02:50:09 -0400 Subject: [PATCH 0018/1357] feat(app-routing): improve app routing Changes: - Use `ui-sref` instead of `href` or `ng-href` when ui-router is chosen - Use `ui-sref-active` instead of `ng-class='{active: isActive()}'` when ui-router is chosen - Use `$state.go()` where applicable, when ui-router is chosen - Use `$scope.menu[n].state` instead of `$scope.menu[n].link` when ui-router is chosen (attempt to remove possible confusion) - Omit `$scope.isActive` when ui-router is chosen - Simplify `navbar(jade).jade` templating (remove extra `<% if (filters.auth) %>` tag) - Add `/logout` route for both ng-route and ui-router - Use `$routeChangeStart` or `$stateChangeStart` to pass refering route or state to `/logout` - Add `stateMock` for testing `$state` transitions - Use `stateMock` in main.controller for expecting template requests from state transistions Closes #331 --- .../app/account(auth)/account(coffee).coffee | 26 ++++++++++++- .../client/app/account(auth)/account(js).js | 38 ++++++++++++++++++- .../app/account(auth)/login/login(html).html | 2 +- .../app/account(auth)/login/login(jade).jade | 2 +- .../login/login.controller(coffee).coffee | 4 +- .../login/login.controller(js).js | 4 +- .../account(auth)/signup/signup(html).html | 2 +- .../account(auth)/signup/signup(jade).jade | 2 +- .../signup/signup.controller(coffee).coffee | 4 +- .../signup/signup.controller(js).js | 4 +- app/templates/client/app/app(coffee).coffee | 11 +++--- app/templates/client/app/app(js).js | 15 ++++---- .../main/main.controller.spec(coffee).coffee | 13 ++++--- .../app/main/main.controller.spec(js).js | 11 ++++-- .../components/navbar/navbar(html).html | 14 +++---- .../components/navbar/navbar(jade).jade | 24 ++++++------ .../navbar/navbar.controller(coffee).coffee | 12 ++---- .../navbar/navbar.controller(js).js | 15 +++----- .../ui-router.mock(coffee).coffee | 26 +++++++++++++ .../ui-router(uirouter)/ui-router.mock(js).js | 34 +++++++++++++++++ 20 files changed, 191 insertions(+), 72 deletions(-) create mode 100644 app/templates/client/components/ui-router(uirouter)/ui-router.mock(coffee).coffee create mode 100644 app/templates/client/components/ui-router(uirouter)/ui-router.mock(js).js diff --git a/app/templates/client/app/account(auth)/account(coffee).coffee b/app/templates/client/app/account(auth)/account(coffee).coffee index 2b7b8b23b..088fb6840 100644 --- a/app/templates/client/app/account(auth)/account(coffee).coffee +++ b/app/templates/client/app/account(auth)/account(coffee).coffee @@ -7,6 +7,14 @@ angular.module '<%= scriptAppName %>' templateUrl: 'app/account/login/login.html' controller: 'LoginCtrl' + .when '/logout', + name: 'logout' + referrer: '/' + controller: ($location, $route, Auth) -> + referrer = $route.current.params.referrer or $route.current.referrer or "/" + Auth.logout() + $location.path referrer + .when '/signup', templateUrl: 'app/account/signup/signup.html' controller: 'SignupCtrl' @@ -15,6 +23,10 @@ angular.module '<%= scriptAppName %>' templateUrl: 'app/account/settings/settings.html' controller: 'SettingsCtrl' authenticate: true + +.run ($rootScope) -> + $rootScope.$on '$routeChangeStart', (event, next, current) -> + next.referrer = current.originalPath if next.name is "logout" and current and current.originalPath and not current.authenticate <% } %><% if(filters.uirouter) { %>.config ($stateProvider) -> $stateProvider .state 'login', @@ -22,6 +34,14 @@ angular.module '<%= scriptAppName %>' templateUrl: 'app/account/login/login.html' controller: 'LoginCtrl' + .state 'logout', + url: '/logout?referrer' + referrer: 'main' + controller: ($state, Auth) -> + referrer = $state.params.referrer or $state.current.referrer or "main" + Auth.logout() + $state.go referrer + .state 'signup', url: '/signup' templateUrl: 'app/account/signup/signup.html' @@ -32,4 +52,8 @@ angular.module '<%= scriptAppName %>' templateUrl: 'app/account/settings/settings.html' controller: 'SettingsCtrl' authenticate: true -<% } %> \ No newline at end of file + +.run ($rootScope) -> + $rootScope.$on '$stateChangeStart', (event, next, nextParams, current) -> + next.referrer = current.name if next.name is "logout" and current and current.name and not current.authenticate +<% } %> diff --git a/app/templates/client/app/account(auth)/account(js).js b/app/templates/client/app/account(auth)/account(js).js index 0e30543a5..d31ff19d2 100644 --- a/app/templates/client/app/account(auth)/account(js).js +++ b/app/templates/client/app/account(auth)/account(js).js @@ -7,6 +7,17 @@ angular.module('<%= scriptAppName %>') templateUrl: 'app/account/login/login.html', controller: 'LoginCtrl' }) + .when('/logout', { + name: 'logout', + referrer: '/', + controller: function($location, $route, Auth) { + var referrer = $route.current.params.referrer || + $route.current.referrer || + '/'; + Auth.logout(); + $location.path(referrer); + } + }) .when('/signup', { templateUrl: 'app/account/signup/signup.html', controller: 'SignupCtrl' @@ -16,6 +27,13 @@ angular.module('<%= scriptAppName %>') controller: 'SettingsCtrl', authenticate: true }); + }) + .run(function($rootScope) { + $rootScope.$on('$routeChangeStart', function(event, next, current) { + if (next.name === 'logout' && current && current.originalPath && !current.authenticate) { + next.referrer = current.originalPath; + } + }); });<% } %><% if(filters.uirouter) { %>.config(function ($stateProvider) { $stateProvider .state('login', { @@ -23,6 +41,17 @@ angular.module('<%= scriptAppName %>') templateUrl: 'app/account/login/login.html', controller: 'LoginCtrl' }) + .state('logout', { + url: '/logout?referrer', + referrer: 'main', + controller: function($state, Auth) { + var referrer = $state.params.referrer || + $state.current.referrer || + 'main'; + Auth.logout(); + $state.go(referrer); + } + }) .state('signup', { url: '/signup', templateUrl: 'app/account/signup/signup.html', @@ -34,4 +63,11 @@ angular.module('<%= scriptAppName %>') controller: 'SettingsCtrl', authenticate: true }); - });<% } %> \ No newline at end of file + }) + .run(function($rootScope) { + $rootScope.$on('$stateChangeStart', function(event, next, nextParams, current) { + if (next.name === 'logout' && current && current.name && !current.authenticate) { + next.referrer = current.name; + } + }); + });<% } %> diff --git a/app/templates/client/app/account(auth)/login/login(html).html b/app/templates/client/app/account(auth)/login/login(html).html index 572f2e144..49a81b55d 100644 --- a/app/templates/client/app/account(auth)/login/login(html).html +++ b/app/templates/client/app/account(auth)/login/login(html).html @@ -37,7 +37,7 @@

Login

- + ui-sref="signup"<% } else { %>href="http://github.com/signup"<% } %>> Register diff --git a/app/templates/client/app/account(auth)/login/login(jade).jade b/app/templates/client/app/account(auth)/login/login(jade).jade index 4b13c0b13..686b1769e 100644 --- a/app/templates/client/app/account(auth)/login/login(jade).jade +++ b/app/templates/client/app/account(auth)/login/login(jade).jade @@ -34,7 +34,7 @@ div(ng-include='"components/navbar/navbar.html"') button.btn.btn-inverse.btn-lg.btn-login(type='submit') | Login = ' ' - a.btn.btn-default.btn-lg.btn-register(href='http://github.com/signup') + a.btn.btn-default.btn-lg.btn-register(<% if(filters.uirouter) { %>ui-sref='signup'<% } else { %>href='http://github.com/signup'<% } %>) | Register <% if(filters.oauth) {%> hr diff --git a/app/templates/client/app/account(auth)/login/login.controller(coffee).coffee b/app/templates/client/app/account(auth)/login/login.controller(coffee).coffee index 3f90c25d7..036191f93 100644 --- a/app/templates/client/app/account(auth)/login/login.controller(coffee).coffee +++ b/app/templates/client/app/account(auth)/login/login.controller(coffee).coffee @@ -1,7 +1,7 @@ 'use strict' angular.module '<%= scriptAppName %>' -.controller 'LoginCtrl', ($scope, Auth, $location<% if(filters.oauth) {%>, $window<% } %>) -> +.controller 'LoginCtrl', ($scope, Auth<% if(filters.ngroute) { %>, $location<% } %><% if(filters.uirouter) { %>, $state<% } %><% if(filters.oauth) {%>, $window<% } %>) -> $scope.user = {} $scope.errors = {} $scope.login = (form) -> @@ -14,7 +14,7 @@ angular.module '<%= scriptAppName %>' password: $scope.user.password .then -> - $location.path '/' + <% if(filters.ngroute) { %>$location.path '/'<% } %><% if(filters.uirouter) { %>$state.go 'main'<% } %> .catch (err) -> $scope.errors.other = err.message diff --git a/app/templates/client/app/account(auth)/login/login.controller(js).js b/app/templates/client/app/account(auth)/login/login.controller(js).js index 7b13da384..e2c5dcaa4 100644 --- a/app/templates/client/app/account(auth)/login/login.controller(js).js +++ b/app/templates/client/app/account(auth)/login/login.controller(js).js @@ -1,7 +1,7 @@ 'use strict'; angular.module('<%= scriptAppName %>') - .controller('LoginCtrl', function ($scope, Auth, $location<% if (filters.oauth) { %>, $window<% } %>) { + .controller('LoginCtrl', function ($scope, Auth<% if(filters.ngroute) { %>, $location<% } %><% if(filters.uirouter) { %>, $state<% } %><% if (filters.oauth) { %>, $window<% } %>) { $scope.user = {}; $scope.errors = {}; @@ -15,7 +15,7 @@ angular.module('<%= scriptAppName %>') }) .then( function() { // Logged in, redirect to home - $location.path('/'); + <% if(filters.ngroute) { %>$location.path('/');<% } %><% if(filters.uirouter) { %>$state.go('main');<% } %> }) .catch( function(err) { $scope.errors.other = err.message; diff --git a/app/templates/client/app/account(auth)/signup/signup(html).html b/app/templates/client/app/account(auth)/signup/signup(html).html index 59faed568..28d6c39ab 100644 --- a/app/templates/client/app/account(auth)/signup/signup(html).html +++ b/app/templates/client/app/account(auth)/signup/signup(html).html @@ -58,7 +58,7 @@

Sign up

- + ui-sref="login"<% } else { %>href="http://github.com/login"<% } %>> Login diff --git a/app/templates/client/app/account(auth)/signup/signup(jade).jade b/app/templates/client/app/account(auth)/signup/signup(jade).jade index 43815a21c..7e21b101c 100644 --- a/app/templates/client/app/account(auth)/signup/signup(jade).jade +++ b/app/templates/client/app/account(auth)/signup/signup(jade).jade @@ -36,7 +36,7 @@ div(ng-include='"components/navbar/navbar.html"') button.btn.btn-inverse.btn-lg.btn-login(type='submit') | Sign up = ' ' - a.btn.btn-default.btn-lg.btn-register(href='http://github.com/login') + a.btn.btn-default.btn-lg.btn-register(<% if(filters.uirouter) { %>ui-sref='login'<% } else { %>href='http://github.com/login'<% } %>) | Login <% if(filters.oauth) {%> diff --git a/app/templates/client/app/account(auth)/signup/signup.controller(coffee).coffee b/app/templates/client/app/account(auth)/signup/signup.controller(coffee).coffee index 1b9c9696f..ac240faa8 100644 --- a/app/templates/client/app/account(auth)/signup/signup.controller(coffee).coffee +++ b/app/templates/client/app/account(auth)/signup/signup.controller(coffee).coffee @@ -1,7 +1,7 @@ 'use strict' angular.module '<%= scriptAppName %>' -.controller 'SignupCtrl', ($scope, Auth, $location<% if(filters.oauth) {%>, $window<% } %>) -> +.controller 'SignupCtrl', ($scope, Auth<% if(filters.ngroute) { %>, $location<% } %><% if(filters.uirouter) { %>, $state<% } %><% if(filters.oauth) {%>, $window<% } %>) -> $scope.user = {} $scope.errors = {} $scope.register = (form) -> @@ -15,7 +15,7 @@ angular.module '<%= scriptAppName %>' password: $scope.user.password .then -> - $location.path '/' + <% if(filters.ngroute) { %>$location.path '/'<% } %><% if(filters.uirouter) { %>$state.go 'main'<% } %> .catch (err) -> err = err.data diff --git a/app/templates/client/app/account(auth)/signup/signup.controller(js).js b/app/templates/client/app/account(auth)/signup/signup.controller(js).js index 7d6ba3d38..10685079d 100644 --- a/app/templates/client/app/account(auth)/signup/signup.controller(js).js +++ b/app/templates/client/app/account(auth)/signup/signup.controller(js).js @@ -1,7 +1,7 @@ 'use strict'; angular.module('<%= scriptAppName %>') - .controller('SignupCtrl', function ($scope, Auth, $location<% if (filters.oauth) { %>, $window<% } %>) { + .controller('SignupCtrl', function ($scope, Auth<% if(filters.ngroute) { %>, $location<% } %><% if(filters.uirouter) { %>, $state<% } %><% if (filters.oauth) { %>, $window<% } %>) { $scope.user = {}; $scope.errors = {}; @@ -16,7 +16,7 @@ angular.module('<%= scriptAppName %>') }) .then( function() { // Account created, redirect to home - $location.path('/'); + <% if(filters.ngroute) { %>$location.path('/');<% } %><% if(filters.uirouter) { %>$state.go('main');<% } %> }) .catch( function(err) { err = err.data; diff --git a/app/templates/client/app/app(coffee).coffee b/app/templates/client/app/app(coffee).coffee index 9c0a87a0e..cb6d0c5b1 100644 --- a/app/templates/client/app/app(coffee).coffee +++ b/app/templates/client/app/app(coffee).coffee @@ -15,8 +15,9 @@ angular.module '<%= scriptAppName %>', [<%= angularModules %>] $locationProvider.html5Mode true<% if(filters.auth) { %> $httpProvider.interceptors.push 'authInterceptor'<% } %> <% } %><% if(filters.auth) { %> -.factory 'authInterceptor', ($rootScope, $q, $cookieStore, $location) -> - # Add authorization token to headers +.factory 'authInterceptor', ($rootScope, $q, $cookieStore<% if(filters.ngroute) { %>, $location<% } if(filters.uirouter) { %>, $injector<% } %>) -> + <% if(filters.uirouter) { %>state = null + <% } %># Add authorization token to headers request: (config) -> config.headers = config.headers or {} config.headers.Authorization = 'Bearer ' + $cookieStore.get 'token' if $cookieStore.get 'token' @@ -25,15 +26,15 @@ angular.module '<%= scriptAppName %>', [<%= angularModules %>] # Intercept 401s and redirect you to login responseError: (response) -> if response.status is 401 - $location.path '/login' + <% if(filters.ngroute) { %>$location.path '/login'<% } if(filters.uirouter) { %>(state || state = $injector.get '$state').go 'login'<% } %> # remove any stale tokens $cookieStore.remove 'token' $q.reject response -.run ($rootScope, $location, Auth) -> +.run ($rootScope<% if(filters.ngroute) { %>, $location<% } %><% if(filters.uirouter) { %>, $state<% } %>, Auth) -> # Redirect to login if route requires auth and you're not logged in $rootScope.$on <% if(filters.ngroute) { %>'$routeChangeStart'<% } %><% if(filters.uirouter) { %>'$stateChangeStart'<% } %>, (event, next) -> Auth.isLoggedIn (loggedIn) -> - $location.path "/login" if next.authenticate and not loggedIn + <% if(filters.ngroute) { %>$location.path '/login'<% } %><% if(filters.uirouter) { %>$state.go 'login'<% } %> if next.authenticate and not loggedIn <% } %> diff --git a/app/templates/client/app/app(js).js b/app/templates/client/app/app(js).js index 4e6adea0c..35b8ad327 100644 --- a/app/templates/client/app/app(js).js +++ b/app/templates/client/app/app(js).js @@ -9,16 +9,17 @@ angular.module('<%= scriptAppName %>', [<%= angularModules %>]) $locationProvider.html5Mode(true);<% if(filters.auth) { %> $httpProvider.interceptors.push('authInterceptor');<% } %> - })<% } %><% if(filters.uirouter) { %>.config(function ($stateProvider, $urlRouterProvider, $locationProvider<% if(filters.auth) { %>, $httpProvider<% } %>) { + })<% } if(filters.uirouter) { %>.config(function ($stateProvider, $urlRouterProvider, $locationProvider<% if(filters.auth) { %>, $httpProvider<% } %>) { $urlRouterProvider .otherwise('/'); $locationProvider.html5Mode(true);<% if(filters.auth) { %> $httpProvider.interceptors.push('authInterceptor');<% } %> - })<% } %><% if(filters.auth) { %> + })<% } if(filters.auth) { %> - .factory('authInterceptor', function ($rootScope, $q, $cookieStore, $location) { - return { + .factory('authInterceptor', function ($rootScope, $q, $cookieStore<% if(filters.ngroute) { %>, $location<% } if(filters.uirouter) { %>, $injector<% } %>) { + <% if(filters.uirouter) { %>var state; + <% } %>return { // Add authorization token to headers request: function (config) { config.headers = config.headers || {}; @@ -31,7 +32,7 @@ angular.module('<%= scriptAppName %>', [<%= angularModules %>]) // Intercept 401s and redirect you to login responseError: function(response) { if(response.status === 401) { - $location.path('/login'); + <% if(filters.ngroute) { %>$location.path('/login');<% } if(filters.uirouter) { %>(state || (state = $injector.get('$state'))).go('login');<% } %> // remove any stale tokens $cookieStore.remove('token'); return $q.reject(response); @@ -43,12 +44,12 @@ angular.module('<%= scriptAppName %>', [<%= angularModules %>]) }; }) - .run(function ($rootScope, $location, Auth) { + .run(function ($rootScope<% if(filters.ngroute) { %>, $location<% } if(filters.uirouter) { %>, $state<% } %>, Auth) { // Redirect to login if route requires auth and you're not logged in $rootScope.$on(<% if(filters.ngroute) { %>'$routeChangeStart'<% } %><% if(filters.uirouter) { %>'$stateChangeStart'<% } %>, function (event, next) { Auth.isLoggedIn(function(loggedIn) { if (next.authenticate && !loggedIn) { - $location.path('/login'); + <% if(filters.ngroute) { %>$location.path('/login');<% } if(filters.uirouter) { %>$state.go('login');<% } %> } }); }); diff --git a/app/templates/client/app/main/main.controller.spec(coffee).coffee b/app/templates/client/app/main/main.controller.spec(coffee).coffee index efe9b39a6..f974a081d 100644 --- a/app/templates/client/app/main/main.controller.spec(coffee).coffee +++ b/app/templates/client/app/main/main.controller.spec(coffee).coffee @@ -3,15 +3,17 @@ describe 'Controller: MainCtrl', -> # load the controller's module - beforeEach module '<%= scriptAppName %>' <% if(filters.socketio) {%> + beforeEach module '<%= scriptAppName %>' <% if(filters.uirouter) {%> + beforeEach module 'stateMock' <% } %><% if(filters.socketio) {%> beforeEach module 'socketMock' <% } %> MainCtrl = undefined - scope = undefined + scope = undefined<% if(filters.uirouter) {%> + state = undefined<% } %> $httpBackend = undefined # Initialize the controller and a mock scope - beforeEach inject (_$httpBackend_, $controller, $rootScope) -> + beforeEach inject (_$httpBackend_, $controller, $rootScope<% if(filters.uirouter) {%>, $state<% } %>) -> $httpBackend = _$httpBackend_ $httpBackend.expectGET('/api/things').respond [ 'HTML5 Boilerplate' @@ -19,10 +21,11 @@ describe 'Controller: MainCtrl', -> 'Karma' 'Express' ] - scope = $rootScope.$new() + scope = $rootScope.$new()<% if(filters.uirouter) {%> + state = $state<% } %> MainCtrl = $controller 'MainCtrl', $scope: scope it 'should attach a list of things to the scope', -> $httpBackend.flush() - expect(scope.awesomeThings.length).toBe 4 \ No newline at end of file + expect(scope.awesomeThings.length).toBe 4 diff --git a/app/templates/client/app/main/main.controller.spec(js).js b/app/templates/client/app/main/main.controller.spec(js).js index 373e9db08..21b8aba70 100644 --- a/app/templates/client/app/main/main.controller.spec(js).js +++ b/app/templates/client/app/main/main.controller.spec(js).js @@ -3,20 +3,23 @@ describe('Controller: MainCtrl', function () { // load the controller's module - beforeEach(module('<%= scriptAppName %>'));<% if(filters.socketio) {%> + beforeEach(module('<%= scriptAppName %>'));<% if(filters.uirouter) {%> + beforeEach(module('stateMock'));<% } %><% if(filters.socketio) {%> beforeEach(module('socketMock'));<% } %> var MainCtrl, - scope, + scope,<% if(filters.uirouter) {%> + state,<% } %> $httpBackend; // Initialize the controller and a mock scope - beforeEach(inject(function (_$httpBackend_, $controller, $rootScope) { + beforeEach(inject(function (_$httpBackend_, $controller, $rootScope<% if(filters.uirouter) {%>, $state<% } %>) { $httpBackend = _$httpBackend_; $httpBackend.expectGET('/api/things') .respond(['HTML5 Boilerplate', 'AngularJS', 'Karma', 'Express']); - scope = $rootScope.$new(); + scope = $rootScope.$new();<% if(filters.uirouter) {%> + state = $state;<% } %> MainCtrl = $controller('MainCtrl', { $scope: scope }); diff --git a/app/templates/client/components/navbar/navbar(html).html b/app/templates/client/components/navbar/navbar(html).html index 71f8606dd..a93839562 100644 --- a/app/templates/client/components/navbar/navbar(html).html +++ b/app/templates/client/components/navbar/navbar(html).html @@ -11,18 +11,18 @@ diff --git a/app/templates/client/components/navbar/navbar(jade).jade b/app/templates/client/components/navbar/navbar(jade).jade index 2b17f29c3..7863f4e0a 100644 --- a/app/templates/client/components/navbar/navbar(jade).jade +++ b/app/templates/client/components/navbar/navbar(jade).jade @@ -10,25 +10,25 @@ div.navbar.navbar-default.navbar-static-top(ng-controller='NavbarCtrl') div#navbar-main.navbar-collapse.collapse(collapse='isCollapsed') ul.nav.navbar-nav - li(ng-repeat='item in menu', ng-class='{active: isActive(item.link)}') - a(ng-href='http://github.com/%7B%7Bitem.link%7D%7D') {{item.title}}<% if(filters.auth) { %> + li(ng-repeat='item in menu', <% if(filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: isActive(item.link)}'<% } %>) + a(<% if(filters.uirouter) { %>ui-sref='{{item.state}}'<% } else { %>ng-href='http://github.com/%7B%7Bitem.link%7D%7D'<% } %>) {{item.title}}<% if(filters.auth) { %> - li(ng-show='isAdmin()', ng-class='{active: isActive("/admin")}') - a(href='http://github.com/admin') Admin<% } %><% if(filters.auth) { %> + li(ng-show='isAdmin()', <% if(filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: isActive("/admin")}'<% } %>) + a(<% if(filters.uirouter) { %>ui-sref='admin'<% } else { %>href='http://github.com/admin'<% } %>) Admin ul.nav.navbar-nav.navbar-right - li(ng-hide='isLoggedIn()', ng-class='{active: isActive("/signup")}') - a(href='http://github.com/signup') Sign up + li(ng-hide='isLoggedIn()', <% if(filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: isActive("/signup")}'<% } %>) + a(<% if(filters.uirouter) { %>ui-sref='signup'<% } else { %>href='http://github.com/signup'<% } %>) Sign up - li(ng-hide='isLoggedIn()', ng-class='{active: isActive("/login")}') - a(href='http://github.com/login') Login + li(ng-hide='isLoggedIn()', <% if(filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: isActive("/login")}'<% } %>) + a(<% if(filters.uirouter) { %>ui-sref='login'<% } else { %>href='http://github.com/login'<% } %>) Login li(ng-show='isLoggedIn()') p.navbar-text Hello {{ getCurrentUser().name }} - li(ng-show='isLoggedIn()', ng-class='{active: isActive("/settings")}') - a(href='http://github.com/settings') + li(ng-show='isLoggedIn()', <% if(filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: isActive("/settings")}'<% } %>) + a(<% if(filters.uirouter) { %>ui-sref='settings'<% } else { %>href='http://github.com/settings'<% } %>) span.glyphicon.glyphicon-cog - li(ng-show='isLoggedIn()', ng-class='{active: isActive("/logout")}') - a(href='', ng-click='logout()') Logout<% } %> \ No newline at end of file + li(ng-show='isLoggedIn()') + a(<% if(filters.uirouter) { %>ui-sref='logout'<% } else { %>href='http://github.com/logout'<% } %>) Logout<% } %> \ No newline at end of file diff --git a/app/templates/client/components/navbar/navbar.controller(coffee).coffee b/app/templates/client/components/navbar/navbar.controller(coffee).coffee index d3804c5eb..121437cf1 100644 --- a/app/templates/client/components/navbar/navbar.controller(coffee).coffee +++ b/app/templates/client/components/navbar/navbar.controller(coffee).coffee @@ -1,19 +1,15 @@ 'use strict' angular.module '<%= scriptAppName %>' -.controller 'NavbarCtrl', ($scope, $location<% if(filters.auth) {%>, Auth<% } %>) -> +.controller 'NavbarCtrl', ($scope<% if(!filters.uirouter) { %>, $location<% } %><% if(filters.auth) {%>, Auth<% } %>) -> $scope.menu = [ title: 'Home' - link: '/' + <% if(filters.uirouter) { %>state: 'main'<% } else { %>link: '/'<% } %> ] $scope.isCollapsed = true<% if(filters.auth) {%> $scope.isLoggedIn = Auth.isLoggedIn $scope.isAdmin = Auth.isAdmin - $scope.getCurrentUser = Auth.getCurrentUser - - $scope.logout = -> - Auth.logout() - $location.path '/login'<% } %> + $scope.getCurrentUser = Auth.getCurrentUser<% } %><% if(!filters.uirouter) { %> $scope.isActive = (route) -> - route is $location.path() \ No newline at end of file + route is $location.path()<% } %> \ No newline at end of file diff --git a/app/templates/client/components/navbar/navbar.controller(js).js b/app/templates/client/components/navbar/navbar.controller(js).js index 4ce9dbcb5..2428ac15b 100644 --- a/app/templates/client/components/navbar/navbar.controller(js).js +++ b/app/templates/client/components/navbar/navbar.controller(js).js @@ -1,23 +1,18 @@ 'use strict'; angular.module('<%= scriptAppName %>') - .controller('NavbarCtrl', function ($scope, $location<% if(filters.auth) {%>, Auth<% } %>) { + .controller('NavbarCtrl', function ($scope<% if(!filters.uirouter) { %>, $location<% } %><% if(filters.auth) {%>, Auth<% } %>) { $scope.menu = [{ 'title': 'Home', - 'link': '/' + <% if(filters.uirouter) { %>'state': 'main'<% } else { %>'link': '/'<% } %> }]; $scope.isCollapsed = true;<% if(filters.auth) {%> $scope.isLoggedIn = Auth.isLoggedIn; $scope.isAdmin = Auth.isAdmin; - $scope.getCurrentUser = Auth.getCurrentUser; - - $scope.logout = function() { - Auth.logout(); - $location.path('/login'); - };<% } %> + $scope.getCurrentUser = Auth.getCurrentUser;<% } %><% if(!filters.uirouter) { %> $scope.isActive = function(route) { return route === $location.path(); - }; - }); \ No newline at end of file + };<% } %> + }); diff --git a/app/templates/client/components/ui-router(uirouter)/ui-router.mock(coffee).coffee b/app/templates/client/components/ui-router(uirouter)/ui-router.mock(coffee).coffee new file mode 100644 index 000000000..ff3937c35 --- /dev/null +++ b/app/templates/client/components/ui-router(uirouter)/ui-router.mock(coffee).coffee @@ -0,0 +1,26 @@ +'use strict' + +angular.module 'stateMock', [] +angular.module('stateMock').service '$state', ($q) -> + @expectedTransitions = [] + + @transitionTo = (stateName) -> + if @expectedTransitions.length > 0 + expectedState = @expectedTransitions.shift() + throw Error('Expected transition to state: ' + expectedState + ' but transitioned to ' + stateName) if expectedState isnt stateName + else + throw Error('No more transitions were expected! Tried to transition to ' + stateName) + console.log 'Mock transition to: ' + stateName + deferred = $q.defer() + promise = deferred.promise + deferred.resolve() + promise + + @go = @transitionTo + + @expectTransitionTo = (stateName) -> + @expectedTransitions.push stateName + + @ensureAllTransitionsHappened = -> + throw Error('Not all transitions happened!') if @expectedTransitions.length > 0 + @ diff --git a/app/templates/client/components/ui-router(uirouter)/ui-router.mock(js).js b/app/templates/client/components/ui-router(uirouter)/ui-router.mock(js).js new file mode 100644 index 000000000..a5a1bf413 --- /dev/null +++ b/app/templates/client/components/ui-router(uirouter)/ui-router.mock(js).js @@ -0,0 +1,34 @@ +'use strict'; + +angular.module('stateMock', []); +angular.module('stateMock').service('$state', function($q) { + this.expectedTransitions = []; + + this.transitionTo = function(stateName) { + if (this.expectedTransitions.length > 0) { + var expectedState = this.expectedTransitions.shift(); + if (expectedState !== stateName) { + throw Error('Expected transition to state: ' + expectedState + ' but transitioned to ' + stateName); + } + } else { + throw Error('No more transitions were expected! Tried to transition to ' + stateName); + } + console.log('Mock transition to: ' + stateName); + var deferred = $q.defer(); + var promise = deferred.promise; + deferred.resolve(); + return promise; + }; + + this.go = this.transitionTo; + + this.expectTransitionTo = function(stateName) { + this.expectedTransitions.push(stateName); + }; + + this.ensureAllTransitionsHappened = function() { + if (this.expectedTransitions.length > 0) { + throw Error('Not all transitions happened!'); + } + }; +}); From fb28c28daf8ac777f15644bc2cde2fd149f90788 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Tue, 16 Sep 2014 23:22:45 -0600 Subject: [PATCH 0019/1357] expect uirouter mocks in tests --- test/test-file-creation.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/test-file-creation.js b/test/test-file-creation.js index b6171fabd..05e83c77f 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -174,11 +174,17 @@ describe('angular-fullstack generator', function () { 'protractor.conf.js' ]); + if (ops.router === 'uirouter') { + files = files.concat([ + 'client/components/ui-router/ui-router.mock.' + script + ]); + } + if (ops.uibootstrap) { files = files.concat([ 'client/components/modal/modal.' + markup, 'client/components/modal/modal.' + stylesheet, - 'client/components/modal/modal.service.' + script, + 'client/components/modal/modal.service.' + script ]); } From f0e568a9b427b9fc67eef4f8a2ec752a10bdead3 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sat, 20 Sep 2014 19:31:16 -0600 Subject: [PATCH 0020/1357] rename server side e2e tests to integration tests --- app/templates/Gruntfile.js | 24 +++++++++---------- .../{thing.e2e.js => thing.integration.js} | 0 .../{user.e2e.js => user.integration.js} | 0 .../{name.e2e.js => name.integration.js} | 0 4 files changed, 12 insertions(+), 12 deletions(-) rename app/templates/server/api/thing/{thing.e2e.js => thing.integration.js} (100%) rename app/templates/server/api/user(auth)/{user.e2e.js => user.integration.js} (100%) rename endpoint/templates/{name.e2e.js => name.integration.js} (100%) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index a72f42dae..6cd422daa 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -170,14 +170,14 @@ module.exports = function (grunt) { }, src: [ 'server/**/*.js', - '!server/**/*.{spec,e2e}.js' + '!server/**/*.{spec,integration}.js' ] }, serverTest: { options: { jshintrc: 'server/.jshintrc-spec' }, - src: ['server/**/*.{spec,e2e}.js'] + src: ['server/**/*.{spec,integration}.js'] }, all: [ '<%%= yeoman.client %>/{app,components}/**/*.js', @@ -493,8 +493,8 @@ module.exports = function (grunt) { unit: { src: ['server/**/*.spec.js'] }, - e2e: { - src: ['server/**/*.e2e.js'] + integration: { + src: ['server/**/*.integration.js'] } }, @@ -504,7 +504,7 @@ module.exports = function (grunt) { excludes: [ '**/*.spec.js', '**/*.mock.js', - '**/*.e2e.js' + '**/*.integration.js' ], reporter: 'spec', require: ['mocha.conf.js'], @@ -513,17 +513,17 @@ module.exports = function (grunt) { }, src: 'server' }, - e2e: { + integration: { options: { excludes: [ '**/*.spec.js', '**/*.mock.js', - '**/*.e2e.js' + '**/*.integration.js' ], reporter: 'spec', require: ['mocha.conf.js'], - mask: '**/*.e2e.js', - coverageFolder: 'coverage/server/e2e' + mask: '**/*.integration.js', + coverageFolder: 'coverage/server/integration' }, src: 'server' } @@ -822,7 +822,7 @@ module.exports = function (grunt) { 'env:all', 'env:test', 'mochaTest:unit', - 'mochaTest:e2e' + 'mochaTest:integration' ]); } @@ -867,11 +867,11 @@ module.exports = function (grunt) { ]); } - else if (option === 'e2e') { + else if (option === 'integration') { return grunt.task.run([ 'env:all', 'env:test', - 'mocha_istanbul:e2e' + 'mocha_istanbul:integration' ]); } diff --git a/app/templates/server/api/thing/thing.e2e.js b/app/templates/server/api/thing/thing.integration.js similarity index 100% rename from app/templates/server/api/thing/thing.e2e.js rename to app/templates/server/api/thing/thing.integration.js diff --git a/app/templates/server/api/user(auth)/user.e2e.js b/app/templates/server/api/user(auth)/user.integration.js similarity index 100% rename from app/templates/server/api/user(auth)/user.e2e.js rename to app/templates/server/api/user(auth)/user.integration.js diff --git a/endpoint/templates/name.e2e.js b/endpoint/templates/name.integration.js similarity index 100% rename from endpoint/templates/name.e2e.js rename to endpoint/templates/name.integration.js From f1b5b9a101f600dae3289960942c290169e280e4 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sat, 20 Sep 2014 20:53:10 -0600 Subject: [PATCH 0021/1357] style(tests): use consistent code style for route tests, clarify names --- app/templates/server/api/thing/index.spec.js | 64 +++++++------- .../server/api/user(auth)/index.spec.js | 84 +++++++++---------- endpoint/templates/index.spec.js | 64 +++++++------- 3 files changed, 106 insertions(+), 106 deletions(-) diff --git a/app/templates/server/api/thing/index.spec.js b/app/templates/server/api/thing/index.spec.js index e62feff60..3c6c71fc2 100644 --- a/app/templates/server/api/thing/index.spec.js +++ b/app/templates/server/api/thing/index.spec.js @@ -2,42 +2,42 @@ 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 - }); +var thingCtrlStub = { + index: 'thingCtrl.index'<% if(filters.mongoose) { %>, + show: 'thingCtrl.show', + create: 'thingCtrl.create', + update: 'thingCtrl.update', + destroy: 'thingCtrl.destroy'<% } %> +}; + +var routerStub = { + get: sinon.spy()<% if(filters.mongoose) { %>, + put: sinon.spy(), + patch: sinon.spy(), + post: sinon.spy(), + delete: sinon.spy()<% } %> +}; + +// require the index with our stubbed out modules +var thingIndex = proxyquire('./index.js', { + 'express': { + Router: function() { + return routerStub; + } + }, + './thing.controller': thingCtrlStub +}); describe('Thing API Router:', function() { it('should return an express router instance', function() { - index.should.equal(router); + thingIndex.should.equal(routerStub); }); describe('GET /api/things', function() { it('should route to thing.controller.index', function() { - router.get.withArgs('/', 'thingCtrl.index').should.have.been.calledOnce; + routerStub.get.withArgs('/', 'thingCtrl.index').should.have.been.calledOnce; }); });<% if(filters.mongoose) { %> @@ -45,7 +45,7 @@ describe('Thing API Router:', function() { describe('GET /api/things/:id', function() { it('should route to thing.controller.show', function() { - router.get.withArgs('/:id', 'thingCtrl.show').should.have.been.calledOnce; + routerStub.get.withArgs('/:id', 'thingCtrl.show').should.have.been.calledOnce; }); }); @@ -53,7 +53,7 @@ describe('Thing API Router:', function() { describe('POST /api/things', function() { it('should route to thing.controller.create', function() { - router.post.withArgs('/', 'thingCtrl.create').should.have.been.calledOnce; + routerStub.post.withArgs('/', 'thingCtrl.create').should.have.been.calledOnce; }); }); @@ -61,7 +61,7 @@ describe('Thing API Router:', function() { describe('PUT /api/things/:id', function() { it('should route to thing.controller.update', function() { - router.put.withArgs('/:id', 'thingCtrl.update').should.have.been.calledOnce; + routerStub.put.withArgs('/:id', 'thingCtrl.update').should.have.been.calledOnce; }); }); @@ -69,7 +69,7 @@ describe('Thing API Router:', function() { describe('PATCH /api/things/:id', function() { it('should route to thing.controller.update', function() { - router.patch.withArgs('/:id', 'thingCtrl.update').should.have.been.calledOnce; + routerStub.patch.withArgs('/:id', 'thingCtrl.update').should.have.been.calledOnce; }); }); @@ -77,7 +77,7 @@ describe('Thing API Router:', function() { describe('DELETE /api/things/:id', function() { it('should route to thing.controller.destroy', function() { - router.delete.withArgs('/:id', 'thingCtrl.destroy').should.have.been.calledOnce; + routerStub.delete.withArgs('/:id', 'thingCtrl.destroy').should.have.been.calledOnce; }); });<% } %> diff --git a/app/templates/server/api/user(auth)/index.spec.js b/app/templates/server/api/user(auth)/index.spec.js index 30b786fb3..b2510aa00 100644 --- a/app/templates/server/api/user(auth)/index.spec.js +++ b/app/templates/server/api/user(auth)/index.spec.js @@ -2,52 +2,52 @@ 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 - }); +var userCtrlStub = { + index: 'userCtrl.index', + destroy: 'userCtrl.destroy', + me: 'userCtrl.me', + changePassword: 'userCtrl.changePassword', + show: 'userCtrl.show', + create: 'userCtrl.create' +}; + +var authServiceStub = { + isAuthenticated: function() { + return 'authService.isAuthenticated'; + }, + hasRole: function(role) { + return 'authService.hasRole.' + role; + } +}; + +var routerStub = { + get: sinon.spy(), + put: sinon.spy(), + post: sinon.spy(), + delete: sinon.spy() +}; + +// require the index with our stubbed out modules +var userIndex = proxyquire('./index', { + 'express': { + Router: function() { + return routerStub; + } + }, + './user.controller': userCtrlStub, + '../../auth/auth.service': authServiceStub +}); describe('User API Router:', function() { it('should return an express router instance', function() { - index.should.equal(router); + userIndex.should.equal(routerStub); }); describe('GET /api/users', function() { it('should verify admin role and route to user.controller.index', function() { - router.get.withArgs('/', 'authService.hasRole.admin', 'userCtrl.index').should.have.been.calledOnce; + routerStub.get.withArgs('/', 'authService.hasRole.admin', 'userCtrl.index').should.have.been.calledOnce; }); }); @@ -55,7 +55,7 @@ describe('User API Router:', function() { describe('DELETE /api/users/:id', function() { it('should verify admin role and route to user.controller.destroy', function() { - router.delete.withArgs('/:id', 'authService.hasRole.admin', 'userCtrl.destroy').should.have.been.calledOnce; + routerStub.delete.withArgs('/:id', 'authService.hasRole.admin', 'userCtrl.destroy').should.have.been.calledOnce; }); }); @@ -63,7 +63,7 @@ describe('User API Router:', function() { describe('GET /api/users/me', function() { it('should be authenticated and route to user.controller.me', function() { - router.get.withArgs('/me', 'authService.isAuthenticated', 'userCtrl.me').should.have.been.calledOnce; + routerStub.get.withArgs('/me', 'authService.isAuthenticated', 'userCtrl.me').should.have.been.calledOnce; }); }); @@ -71,7 +71,7 @@ describe('User API Router:', function() { describe('PUT /api/users/:id/password', function() { it('should be authenticated and route to user.controller.changePassword', function() { - router.put.withArgs('/:id/password', 'authService.isAuthenticated', 'userCtrl.changePassword').should.have.been.calledOnce; + routerStub.put.withArgs('/:id/password', 'authService.isAuthenticated', 'userCtrl.changePassword').should.have.been.calledOnce; }); }); @@ -79,7 +79,7 @@ describe('User API Router:', function() { describe('GET /api/users/:id', function() { it('should be authenticated and route to user.controller.show', function() { - router.get.withArgs('/:id', 'authService.isAuthenticated', 'userCtrl.show').should.have.been.calledOnce; + routerStub.get.withArgs('/:id', 'authService.isAuthenticated', 'userCtrl.show').should.have.been.calledOnce; }); }); @@ -87,7 +87,7 @@ describe('User API Router:', function() { describe('POST /api/users', function() { it('should route to user.controller.create', function() { - router.post.withArgs('/', 'userCtrl.create').should.have.been.calledOnce; + routerStub.post.withArgs('/', 'userCtrl.create').should.have.been.calledOnce; }); }); diff --git a/endpoint/templates/index.spec.js b/endpoint/templates/index.spec.js index 648a841a0..031e379a4 100644 --- a/endpoint/templates/index.spec.js +++ b/endpoint/templates/index.spec.js @@ -2,42 +2,42 @@ var proxyquire = require('proxyquire').noPreserveCache(); - /* <%= name %>.controller stub */ -var <%= cameledName %>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': <%= cameledName %>Ctrl - }); +var <%= cameledName %>CtrlStub = { + index: '<%= name %>Ctrl.index'<% if(filters.mongoose) { %>, + show: '<%= name %>Ctrl.show', + create: '<%= name %>Ctrl.create', + update: '<%= name %>Ctrl.update', + destroy: '<%= name %>Ctrl.destroy'<% } %> +}; + +var routerStub = { + get: sinon.spy()<% if(filters.mongoose) { %>, + put: sinon.spy(), + patch: sinon.spy(), + post: sinon.spy(), + delete: sinon.spy()<% } %> +}; + +// require the index with our stubbed out modules +var <%= name %>Index = proxyquire('./index.js', { + 'express': { + Router: function() { + return routerStub; + } + }, + './<%= name %>.controller': <%= cameledName %>CtrlStub +}); describe('<%= classedName %> API Router:', function() { it('should return an express router instance', function() { - index.should.equal(router); + <%= name %>Index.should.equal(router); }); describe('GET <%= route %>', function() { it('should route to <%= name %>.controller.index', function() { - router.get.withArgs('/', '<%= name %>Ctrl.index').should.have.been.calledOnce; + routerStub.get.withArgs('/', '<%= name %>Ctrl.index').should.have.been.calledOnce; }); });<% if(filters.mongoose) { %> @@ -45,7 +45,7 @@ describe('<%= classedName %> API Router:', function() { describe('GET <%= route %>/:id', function() { it('should route to <%= name %>.controller.show', function() { - router.get.withArgs('/:id', '<%= name %>Ctrl.show').should.have.been.calledOnce; + routerStub.get.withArgs('/:id', '<%= name %>Ctrl.show').should.have.been.calledOnce; }); }); @@ -53,7 +53,7 @@ describe('<%= classedName %> API Router:', function() { describe('POST <%= route %>', function() { it('should route to <%= name %>.controller.create', function() { - router.post.withArgs('/', '<%= name %>Ctrl.create').should.have.been.calledOnce; + routerStub.post.withArgs('/', '<%= name %>Ctrl.create').should.have.been.calledOnce; }); }); @@ -61,7 +61,7 @@ describe('<%= classedName %> API Router:', function() { describe('PUT <%= route %>/:id', function() { it('should route to <%= name %>.controller.update', function() { - router.put.withArgs('/:id', '<%= name %>Ctrl.update').should.have.been.calledOnce; + routerStub.put.withArgs('/:id', '<%= name %>Ctrl.update').should.have.been.calledOnce; }); }); @@ -69,7 +69,7 @@ describe('<%= classedName %> API Router:', function() { describe('PATCH <%= route %>/:id', function() { it('should route to <%= name %>.controller.update', function() { - router.patch.withArgs('/:id', '<%= name %>Ctrl.update').should.have.been.calledOnce; + routerStub.patch.withArgs('/:id', '<%= name %>Ctrl.update').should.have.been.calledOnce; }); }); @@ -77,7 +77,7 @@ describe('<%= classedName %> API Router:', function() { describe('DELETE <%= route %>/:id', function() { it('should route to <%= name %>.controller.destroy', function() { - router.delete.withArgs('/:id', '<%= name %>Ctrl.destroy').should.have.been.calledOnce; + routerStub.delete.withArgs('/:id', '<%= name %>Ctrl.destroy').should.have.been.calledOnce; }); });<% } %> From 56134c0c20a131e5fd14bb3f6cf00cd67d7fc0c3 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sat, 20 Sep 2014 20:59:01 -0600 Subject: [PATCH 0022/1357] style(server): missing semicolon --- app/templates/server/api/thing/thing.socket(socketio).js | 2 +- endpoint/templates/name.socket(socketio).js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/server/api/thing/thing.socket(socketio).js b/app/templates/server/api/thing/thing.socket(socketio).js index dbf3e2fe7..d38e73e0d 100644 --- a/app/templates/server/api/thing/thing.socket(socketio).js +++ b/app/templates/server/api/thing/thing.socket(socketio).js @@ -13,7 +13,7 @@ exports.register = function(socket) { thing.schema.post('remove', function (doc) { onRemove(socket, doc); }); -} +}; function onSave(socket, doc, cb) { socket.emit('thing:save', doc); diff --git a/endpoint/templates/name.socket(socketio).js b/endpoint/templates/name.socket(socketio).js index 886f585ee..aabdadeb8 100644 --- a/endpoint/templates/name.socket(socketio).js +++ b/endpoint/templates/name.socket(socketio).js @@ -13,7 +13,7 @@ exports.register = function(socket) { <%= classedName %>.schema.post('remove', function (doc) { onRemove(socket, doc); }); -} +}; function onSave(socket, doc, cb) { socket.emit('<%= name %>:save', doc); From cda5261d75679b08400370230ff55662e846f7e5 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sat, 20 Sep 2014 21:33:40 -0600 Subject: [PATCH 0023/1357] use spread for saveAsync methods fixes #567, closes #568 --- app/templates/server/api/thing/thing.controller.js | 2 +- app/templates/server/api/user(auth)/user.controller.js | 4 ++-- endpoint/templates/name.controller.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/templates/server/api/thing/thing.controller.js b/app/templates/server/api/thing/thing.controller.js index 4d5abca05..23bfd6937 100644 --- a/app/templates/server/api/thing/thing.controller.js +++ b/app/templates/server/api/thing/thing.controller.js @@ -42,7 +42,7 @@ function saveUpdates(updates){ return function(entity){ var updated = _.merge(entity, updates); return updated.saveAsync() - .then(function () { + .spread(function (updated) { return updated; }); }; diff --git a/app/templates/server/api/user(auth)/user.controller.js b/app/templates/server/api/user(auth)/user.controller.js index 28e30199a..ed0b1749c 100644 --- a/app/templates/server/api/user(auth)/user.controller.js +++ b/app/templates/server/api/user(auth)/user.controller.js @@ -46,7 +46,7 @@ exports.create = function (req, res, next) { newUser.provider = 'local'; newUser.role = 'user'; newUser.saveAsync() - .then(function(user) { + .spread(function(user) { var token = jwt.sign({_id: user._id }, config.secrets.session, { expiresInMinutes: 60*5 }); res.json({ token: token }); }) @@ -94,7 +94,7 @@ exports.changePassword = function(req, res, next) { if(user.authenticate(oldPass)) { user.password = newPass; return user.saveAsync() - .then(respondWith(res, 200)) + .spread(respondWith(res, 200)) .catch(validationError(res)); } else { return res.send(403); diff --git a/endpoint/templates/name.controller.js b/endpoint/templates/name.controller.js index 5851a1338..2afb2be8c 100644 --- a/endpoint/templates/name.controller.js +++ b/endpoint/templates/name.controller.js @@ -33,7 +33,7 @@ function saveUpdates(updates){ return function(entity){ var updated = _.merge(entity, updates); return updated.saveAsync() - .then(function () { + .spread(function (updated) { return updated; }); }; From a817ec9ad3ecdbc93ffd21c617eecf4606f87775 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sat, 20 Sep 2014 23:19:41 -0600 Subject: [PATCH 0024/1357] fix test failures --- endpoint/templates/index.spec.js | 4 ++-- test/test-file-creation.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/endpoint/templates/index.spec.js b/endpoint/templates/index.spec.js index 031e379a4..fd1086b15 100644 --- a/endpoint/templates/index.spec.js +++ b/endpoint/templates/index.spec.js @@ -19,7 +19,7 @@ var routerStub = { }; // require the index with our stubbed out modules -var <%= name %>Index = proxyquire('./index.js', { +var <%= cameledName %>Index = proxyquire('./index.js', { 'express': { Router: function() { return routerStub; @@ -31,7 +31,7 @@ var <%= name %>Index = proxyquire('./index.js', { describe('<%= classedName %> API Router:', function() { it('should return an express router instance', function() { - <%= name %>Index.should.equal(router); + <%= cameledName %>Index.should.equal(routerStub); }); describe('GET <%= route %>', function() { diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 05e83c77f..ced7ce4ee 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -149,7 +149,7 @@ describe('angular-fullstack generator', function () { 'server/api/thing/index.js', 'server/api/thing/index.spec.js', 'server/api/thing/thing.controller.js', - 'server/api/thing/thing.e2e.js', + 'server/api/thing/thing.integration.js', 'server/components/errors/index.js', 'server/config/local.env.js', 'server/config/local.env.sample.js', @@ -215,7 +215,7 @@ describe('angular-fullstack generator', function () { 'server/api/user/index.js', 'server/api/user/index.spec.js', 'server/api/user/user.controller.js', - 'server/api/user/user.e2e.js', + 'server/api/user/user.integration.js', 'server/api/user/user.model.js', 'server/api/user/user.model.spec.js', 'server/auth/index.js', From 0fbea07d92e3e157ea013e5a77a2b4c51b636089 Mon Sep 17 00:00:00 2001 From: kingcody Date: Sun, 21 Sep 2014 05:09:45 -0400 Subject: [PATCH 0025/1357] test(app): add protractor tests for account pages Changes: - add protractor tests for auth related pages - add `onPrepare` and `params` to `protractor.conf.js` --- .../e2e/account(auth)/login/login.po.js | 27 ++++++++ .../e2e/account(auth)/login/login.spec.js | 62 +++++++++++++++++++ .../e2e/account(auth)/logout/logout.spec.js | 46 ++++++++++++++ .../e2e/account(auth)/signup/signup.po.js | 28 +++++++++ .../e2e/account(auth)/signup/signup.spec.js | 61 ++++++++++++++++++ .../e2e/components/navbar/navbar.po.js | 16 +++++ app/templates/protractor.conf.js | 18 +++++- 7 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 app/templates/e2e/account(auth)/login/login.po.js create mode 100644 app/templates/e2e/account(auth)/login/login.spec.js create mode 100644 app/templates/e2e/account(auth)/logout/logout.spec.js create mode 100644 app/templates/e2e/account(auth)/signup/signup.po.js create mode 100644 app/templates/e2e/account(auth)/signup/signup.spec.js create mode 100644 app/templates/e2e/components/navbar/navbar.po.js diff --git a/app/templates/e2e/account(auth)/login/login.po.js b/app/templates/e2e/account(auth)/login/login.po.js new file mode 100644 index 000000000..1186cdb6b --- /dev/null +++ b/app/templates/e2e/account(auth)/login/login.po.js @@ -0,0 +1,27 @@ +/** + * This file uses the Page Object pattern to define the main page for tests + * https://docs.google.com/presentation/d/1B6manhG0zEXkC-H-tPo2vwU06JhL8w9-XCF9oehXzAQ + */ + +'use strict'; + +var LoginPage = function() { + this.form = element(by.css('.form')); + this.form.email = this.form.element(by.model('user.email')); + this.form.password = this.form.element(by.model('user.password')); + this.form.submit = this.form.element(by.css('.btn-login')); + + this.login = function(data) { + for (var prop in data) { + var formElem = this.form[prop]; + if (data.hasOwnProperty(prop) && formElem && typeof formElem.sendKeys === 'function') { + formElem.sendKeys(data[prop]); + } + } + + this.form.submit.click(); + }; +}; + +module.exports = new LoginPage(); + diff --git a/app/templates/e2e/account(auth)/login/login.spec.js b/app/templates/e2e/account(auth)/login/login.spec.js new file mode 100644 index 000000000..d3f0d48ed --- /dev/null +++ b/app/templates/e2e/account(auth)/login/login.spec.js @@ -0,0 +1,62 @@ +'use strict'; + +var config = protractor.getInstance().params; +var UserModel = require(config.serverConfig.root + '/server/api/user/user.model'); + +describe('Login View', function() { + var page; + + var loadPage = function() { + browser.get('/login'); + page = require('./login.po'); + }; + + var testUser = { + name: 'Test User', + email: 'test@test.com', + password: 'test' + }; + + beforeEach(function(done) { + UserModel.removeAsync() + .then(function() { + return UserModel.createAsync(testUser); + }) + .then(loadPage) + .finally(done); + }); + + it('should include login form with correct inputs and submit button', function() { + expect(page.form.email.getAttribute('type')).toBe('email'); + expect(page.form.email.getAttribute('name')).toBe('email'); + expect(page.form.password.getAttribute('type')).toBe('password'); + expect(page.form.password.getAttribute('name')).toBe('password'); + expect(page.form.submit.getAttribute('type')).toBe('submit'); + expect(page.form.submit.getText()).toBe('Login'); + }); + + describe('with local auth', function() { + + it('should login a user and redirecting to "/"', function() { + page.login(testUser); + + var navbar = require('../../components/navbar/navbar.po'); + + expect(browser.getLocationAbsUrl()).toBe(config.baseUrl + '/'); + expect(navbar.navbarAccountGreeting.getText()).toBe('Hello ' + testUser.name); + }); + + it('should indicate login failures', function() { + page.login({ + email: testUser.email, + password: 'badPassword' + }); + + expect(browser.getLocationAbsUrl()).toBe(config.baseUrl + '/login'); + + var helpBlock = page.form.element(by.css('.form-group.has-error .help-block.ng-binding')); + expect(helpBlock.getText()).toBe('This password is not correct.'); + }); + + }); +}); diff --git a/app/templates/e2e/account(auth)/logout/logout.spec.js b/app/templates/e2e/account(auth)/logout/logout.spec.js new file mode 100644 index 000000000..f496459d8 --- /dev/null +++ b/app/templates/e2e/account(auth)/logout/logout.spec.js @@ -0,0 +1,46 @@ +'use strict'; + +var config = protractor.getInstance().params; +var UserModel = require(config.serverConfig.root + '/server/api/user/user.model'); + +describe('Logout View', function() { + var login = function(user) { + browser.get('/login'); + require('../login/login.po').login(user); + }; + + var testUser = { + name: 'Test User', + email: 'test@test.com', + password: 'test' + }; + + beforeEach(function(done) { + UserModel.removeAsync() + .then(function() { + return UserModel.createAsync(testUser); + }) + .then(function() { + return login(testUser); + }) + .finally(done); + }); + + describe('with local auth', function() { + + it('should logout a user and redirecting to "/"', function() { + var navbar = require('../../components/navbar/navbar.po'); + + expect(browser.getLocationAbsUrl()).toBe(config.baseUrl + '/'); + expect(navbar.navbarAccountGreeting.getText()).toBe('Hello ' + testUser.name); + + browser.get('/logout'); + + navbar = require('../../components/navbar/navbar.po'); + + expect(browser.getLocationAbsUrl()).toBe(config.baseUrl + '/'); + expect(navbar.navbarAccountGreeting.isDisplayed()).toBe(false); + }); + + }); +}); diff --git a/app/templates/e2e/account(auth)/signup/signup.po.js b/app/templates/e2e/account(auth)/signup/signup.po.js new file mode 100644 index 000000000..3a496c6e3 --- /dev/null +++ b/app/templates/e2e/account(auth)/signup/signup.po.js @@ -0,0 +1,28 @@ +/** + * This file uses the Page Object pattern to define the main page for tests + * https://docs.google.com/presentation/d/1B6manhG0zEXkC-H-tPo2vwU06JhL8w9-XCF9oehXzAQ + */ + +'use strict'; + +var SignupPage = function() { + this.form = element(by.css('.form')); + this.form.name = this.form.element(by.model('user.name')); + this.form.email = this.form.element(by.model('user.email')); + this.form.password = this.form.element(by.model('user.password')); + this.form.submit = this.form.element(by.css('.btn-register')); + + this.signup = function(data) { + for (var prop in data) { + var formElem = this.form[prop]; + if (data.hasOwnProperty(prop) && formElem && typeof formElem.sendKeys === 'function') { + formElem.sendKeys(data[prop]); + } + } + + this.form.submit.click(); + }; +}; + +module.exports = new SignupPage(); + diff --git a/app/templates/e2e/account(auth)/signup/signup.spec.js b/app/templates/e2e/account(auth)/signup/signup.spec.js new file mode 100644 index 000000000..cc63a5b7b --- /dev/null +++ b/app/templates/e2e/account(auth)/signup/signup.spec.js @@ -0,0 +1,61 @@ +'use strict'; + +var config = protractor.getInstance().params; +var UserModel = require(config.serverConfig.root + '/server/api/user/user.model'); + +describe('Signup View', function() { + var page; + + var loadPage = function() { + browser.get('/signup'); + page = require('./signup.po'); + }; + + var testUser = { + name: 'Test User', + email: 'test@test.com', + password: 'test' + }; + + beforeEach(function() { + loadPage(); + }); + + it('should include signup form with correct inputs and submit button', function() { + expect(page.form.name.getAttribute('type')).toBe('text'); + expect(page.form.name.getAttribute('name')).toBe('name'); + expect(page.form.email.getAttribute('type')).toBe('email'); + expect(page.form.email.getAttribute('name')).toBe('email'); + expect(page.form.password.getAttribute('type')).toBe('password'); + expect(page.form.password.getAttribute('name')).toBe('password'); + expect(page.form.submit.getAttribute('type')).toBe('submit'); + expect(page.form.submit.getText()).toBe('Sign up'); + }); + + describe('with local auth', function() { + + it('should signup a new user, log them in, and redirecting to "/"', function(done) { + UserModel.remove(function() { + page.signup(testUser); + + var navbar = require('../../components/navbar/navbar.po'); + + expect(browser.getLocationAbsUrl()).toBe(config.baseUrl + '/'); + expect(navbar.navbarAccountGreeting.getText()).toBe('Hello ' + testUser.name); + + done(); + }); + }); + + it('should indicate signup failures', function() { + page.signup(testUser); + + expect(browser.getLocationAbsUrl()).toBe(config.baseUrl + '/signup'); + expect(page.form.email.getAttribute('class')).toContain('ng-invalid-mongoose'); + + var helpBlock = page.form.element(by.css('.form-group.has-error .help-block.ng-binding')); + expect(helpBlock.getText()).toBe('The specified email address is already in use.'); + }); + + }); +}); diff --git a/app/templates/e2e/components/navbar/navbar.po.js b/app/templates/e2e/components/navbar/navbar.po.js new file mode 100644 index 000000000..ee2ec1ada --- /dev/null +++ b/app/templates/e2e/components/navbar/navbar.po.js @@ -0,0 +1,16 @@ +/** + * This file uses the Page Object pattern to define the main page for tests + * https://docs.google.com/presentation/d/1B6manhG0zEXkC-H-tPo2vwU06JhL8w9-XCF9oehXzAQ + */ + +'use strict'; + +var NavbarComponent = function() { + this.navbar = element(by.css('.navbar')); + this.navbarHeader = this.navbar.element(by.css('.navbar-header')); + this.navbarNav = this.navbar.element(by.css('#navbar-main .nav.navbar-nav:not(.navbar-right)'));<% if(filters.auth) { %> + this.navbarAccount = this.navbar.element(by.css('#navbar-main .nav.navbar-nav.navbar-right')); + this.navbarAccountGreeting = this.navbarAccount.element(by.binding('Hello {{ getCurrentUser().name }}'));<% } %> +}; + +module.exports = new NavbarComponent(); diff --git a/app/templates/protractor.conf.js b/app/templates/protractor.conf.js index cb66c67c1..195733525 100644 --- a/app/templates/protractor.conf.js +++ b/app/templates/protractor.conf.js @@ -3,7 +3,7 @@ 'use strict'; -exports.config = { +var config = { // The timeout for each script run on the browser. This should be longer // than the maximum time your application needs to stabilize between tasks. allScriptsTimeout: 110000, @@ -46,5 +46,21 @@ exports.config = { // See the full list at https://github.com/juliemr/minijasminenode jasmineNodeOpts: { defaultTimeoutInterval: 30000 + }, + + // Prepare environment for tests + params: { + serverConfig: require('./server/config/environment') + }, + + onPrepare: function() { + var serverConfig = config.params.serverConfig; + + // Setup mongo tests + var mongoose = require('mongoose-bird')(); + mongoose.connect(serverConfig.mongo.uri, serverConfig.mongo.options); // Connect to database } }; + +config.params.baseUrl = config.baseUrl; +exports.config = config; From 5898e0c98f552bc5a3609a7329f4f200de0cc262 Mon Sep 17 00:00:00 2001 From: kingcody Date: Sun, 21 Sep 2014 05:52:31 -0400 Subject: [PATCH 0026/1357] fix(app-signup): switch button classes --- .../client/app/account(auth)/signup/signup(html).html | 4 ++-- .../client/app/account(auth)/signup/signup(jade).jade | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/templates/client/app/account(auth)/signup/signup(html).html b/app/templates/client/app/account(auth)/signup/signup(html).html index 28d6c39ab..ee4f17fa4 100644 --- a/app/templates/client/app/account(auth)/signup/signup(html).html +++ b/app/templates/client/app/account(auth)/signup/signup(html).html @@ -55,10 +55,10 @@

Sign up

diff --git a/app/templates/client/app/account(auth)/signup/signup(jade).jade b/app/templates/client/app/account(auth)/signup/signup(jade).jade index 7e21b101c..8c5710686 100644 --- a/app/templates/client/app/account(auth)/signup/signup(jade).jade +++ b/app/templates/client/app/account(auth)/signup/signup(jade).jade @@ -33,10 +33,10 @@ div(ng-include='"components/navbar/navbar.html"') | {{ errors.password }} div - button.btn.btn-inverse.btn-lg.btn-login(type='submit') + button.btn.btn-inverse.btn-lg.btn-register(type='submit') | Sign up = ' ' - a.btn.btn-default.btn-lg.btn-register(<% if(filters.uirouter) { %>ui-sref='login'<% } else { %>href='http://github.com/login'<% } %>) + a.btn.btn-default.btn-lg.btn-login(<% if(filters.uirouter) { %>ui-sref='login'<% } else { %>href='http://github.com/login'<% } %>) | Login <% if(filters.oauth) {%> From 650d244b8b36c254848743929fb9ee2498343265 Mon Sep 17 00:00:00 2001 From: kingcody Date: Sun, 21 Sep 2014 05:56:17 -0400 Subject: [PATCH 0027/1357] fix(app-logout): add blank templates to logout route/state Closes #570 --- app/templates/client/app/account(auth)/account(js).js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/templates/client/app/account(auth)/account(js).js b/app/templates/client/app/account(auth)/account(js).js index d31ff19d2..8c005c952 100644 --- a/app/templates/client/app/account(auth)/account(js).js +++ b/app/templates/client/app/account(auth)/account(js).js @@ -10,6 +10,7 @@ angular.module('<%= scriptAppName %>') .when('/logout', { name: 'logout', referrer: '/', + template: '', controller: function($location, $route, Auth) { var referrer = $route.current.params.referrer || $route.current.referrer || @@ -44,6 +45,7 @@ angular.module('<%= scriptAppName %>') .state('logout', { url: '/logout?referrer', referrer: 'main', + template: '', controller: function($state, Auth) { var referrer = $state.params.referrer || $state.current.referrer || From 50ca41d21b71962e829bc2743cc37819c650dc41 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sat, 20 Sep 2014 23:19:41 -0600 Subject: [PATCH 0028/1357] feat(generator): use sauce labs for running e2e tests with travis CI closes #572 --- .travis.yml | 6 ++++++ Gruntfile.js | 18 +++++++++++++----- app/templates/protractor.conf.js | 7 ++++--- endpoint/templates/index.spec.js | 4 ++-- test/test-file-creation.js | 24 +++++++++++------------- 5 files changed, 36 insertions(+), 23 deletions(-) diff --git a/.travis.yml b/.travis.yml index 85fbe4a6b..ae5a22e65 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,12 @@ language: node_js node_js: - '0.10' - '0.11' +env: + global: + - secure: fBqMlUrbIwaRJeKe39zxVsRcvtPIP/R98JNzrD0ycHzdfbhsWge0J7FCpdKjgRCf99ggqMhyevJafSJv7cfiVgJhB6kYudhG0G60V+vBjj4NIZnOelpVeQHXyLlekRpu+Qa/DaL43jovRAI0I11cwVfIRWtXZwiQOjCd/Elsdl8= + - secure: GZ95FcH0K88RG7P0SJjoIcHLfUalFRHeu5Vd7Kh0wXTh3O6Zku7iauk6Cd+aYGuFedL5wSzht5qnVBRm10VxhhJMxHiZ+I+VBxt4bysKM0axMZ+SMTfPK3zajVVXKfzIsIYO0m0qwYtHCgSXUrMnwAczESxczxq48VxA/rCXbYc= +addons: + sauce_connect: true before_install: - gem update --system - gem install sass --version "=3.3.7" diff --git a/Gruntfile.js b/Gruntfile.js index 9819a4041..3a510072a 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -3,7 +3,7 @@ var markdown = require('marked'); var semver = require('semver'); var _s = require('underscore.string'); var shell = require('shelljs'); -var process = require('child_process'); +var child_process = require('child_process'); var Q = require('q'); var helpers = require('yeoman-generator').test; var fs = require('fs-extra'); @@ -227,12 +227,20 @@ module.exports = function (grunt) { shell.cd('test/fixtures'); grunt.log.ok('installing npm dependencies for generated app'); - process.exec('npm install --quiet', {cwd: '../fixtures'}, function (error, stdout, stderr) { + child_process.exec('npm install --quiet', {cwd: '../fixtures'}, function (error, stdout, stderr) { grunt.log.ok('installing bower dependencies for generated app'); - process.exec('bower install', {cwd: '../fixtures'}, function (error, stdout, stderr) { - shell.cd('../../'); - done(); + child_process.exec('bower install', {cwd: '../fixtures'}, function (error, stdout, stderr) { + + if(!process.env.SAUCE_USERNAME) { + child_process.exec('npm run update-webdriver', function() { + shell.cd('../../'); + done(); + }); + } else { + shell.cd('../../'); + done(); + } }) }); }); diff --git a/app/templates/protractor.conf.js b/app/templates/protractor.conf.js index cb66c67c1..d05f9e4d1 100644 --- a/app/templates/protractor.conf.js +++ b/app/templates/protractor.conf.js @@ -12,9 +12,10 @@ exports.config = { // with relative paths will be prepended with this. baseUrl: 'http://localhost/' + (process.env.PORT || '9000'), - // If true, only chromedriver will be started, not a standalone selenium. - // Tests for browsers other than chrome will not run. - chromeOnly: true, + // Credientials for Saucelabs + sauceUser: process.env.SAUCE_USERNAME, + + sauceKey: process.env.SAUCE_ACCESS_KEY, // list of files / patterns to load in the browser specs: [ diff --git a/endpoint/templates/index.spec.js b/endpoint/templates/index.spec.js index 031e379a4..fd1086b15 100644 --- a/endpoint/templates/index.spec.js +++ b/endpoint/templates/index.spec.js @@ -19,7 +19,7 @@ var routerStub = { }; // require the index with our stubbed out modules -var <%= name %>Index = proxyquire('./index.js', { +var <%= cameledName %>Index = proxyquire('./index.js', { 'express': { Router: function() { return routerStub; @@ -31,7 +31,7 @@ var <%= name %>Index = proxyquire('./index.js', { describe('<%= classedName %> API Router:', function() { it('should return an express router instance', function() { - <%= name %>Index.should.equal(router); + <%= cameledName %>Index.should.equal(routerStub); }); describe('GET <%= route %>', function() { diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 05e83c77f..568315d92 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -149,7 +149,7 @@ describe('angular-fullstack generator', function () { 'server/api/thing/index.js', 'server/api/thing/index.spec.js', 'server/api/thing/thing.controller.js', - 'server/api/thing/thing.e2e.js', + 'server/api/thing/thing.integration.js', 'server/components/errors/index.js', 'server/config/local.env.js', 'server/config/local.env.sample.js', @@ -215,7 +215,7 @@ describe('angular-fullstack generator', function () { 'server/api/user/index.js', 'server/api/user/index.spec.js', 'server/api/user/user.controller.js', - 'server/api/user/user.e2e.js', + 'server/api/user/user.integration.js', 'server/api/user/user.model.js', 'server/api/user/user.model.spec.js', 'server/auth/index.js', @@ -347,17 +347,15 @@ describe('angular-fullstack generator', function () { }); }); -// it('should run e2e tests successfully', function(done) { -// this.timeout(80000); -// gen.run({}, function () { -// exec('npm run update-webdriver', function (error, stdout, stderr) { -// exec('grunt test:e2e', function (error, stdout, stderr) { -// expect(stdout, 'Client tests failed \n' + stdout ).to.contain('Done, without errors.'); -// done(); -// }); -// }); -// }) -// }); + it('should run e2e tests successfully', function(done) { + this.timeout(80000); + gen.run({}, function () { + exec('grunt test:e2e', function (error, stdout, stderr) { + expect(stdout, 'Client tests failed \n' + stdout).to.contain('0 failures'); + done(); + }); + }); + }); }); describe('with other preprocessors and oauth', function() { From 7bd31938ca5116e62fafb30812e80d78b5d4c2ca Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sun, 21 Sep 2014 05:20:24 -0600 Subject: [PATCH 0029/1357] add log info for running npm run update-webdriver --- Gruntfile.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Gruntfile.js b/Gruntfile.js index 3a510072a..8edbe3ccd 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -233,6 +233,7 @@ module.exports = function (grunt) { child_process.exec('bower install', {cwd: '../fixtures'}, function (error, stdout, stderr) { if(!process.env.SAUCE_USERNAME) { + grunt.log.ok('running npm run update-webdriver'); child_process.exec('npm run update-webdriver', function() { shell.cd('../../'); done(); From 24bfde4de8e747ecfcd8b8b7737044fefffb7623 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sun, 21 Sep 2014 13:41:26 -0600 Subject: [PATCH 0030/1357] add capabilities to protractor config --- app/templates/protractor.conf.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/templates/protractor.conf.js b/app/templates/protractor.conf.js index 2bdcde7fe..18b9ba6af 100644 --- a/app/templates/protractor.conf.js +++ b/app/templates/protractor.conf.js @@ -32,7 +32,10 @@ var config = { // and // https://code.google.com/p/selenium/source/browse/javascript/webdriver/capabilities.js capabilities: { - 'browserName': 'chrome' + 'browserName': 'chrome', + 'name': 'Fullstack E2E', + 'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER, + 'build': process.env.TRAVIS_BUILD_NUMBER }, // ----- The test framework ----- From 456631e056fede3d2e0afad6d88b793cdffc45ca Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sun, 21 Sep 2014 14:06:21 -0600 Subject: [PATCH 0031/1357] use opensauce saucelabs account --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ae5a22e65..d408bd4db 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,8 +4,8 @@ node_js: - '0.11' env: global: - - secure: fBqMlUrbIwaRJeKe39zxVsRcvtPIP/R98JNzrD0ycHzdfbhsWge0J7FCpdKjgRCf99ggqMhyevJafSJv7cfiVgJhB6kYudhG0G60V+vBjj4NIZnOelpVeQHXyLlekRpu+Qa/DaL43jovRAI0I11cwVfIRWtXZwiQOjCd/Elsdl8= - - secure: GZ95FcH0K88RG7P0SJjoIcHLfUalFRHeu5Vd7Kh0wXTh3O6Zku7iauk6Cd+aYGuFedL5wSzht5qnVBRm10VxhhJMxHiZ+I+VBxt4bysKM0axMZ+SMTfPK3zajVVXKfzIsIYO0m0qwYtHCgSXUrMnwAczESxczxq48VxA/rCXbYc= + - secure: hwJX8w4D15UPdU4UIS+iB4XC/lxmh/y6m3IN5Ia5ha++rHs2JZ3FVOPdosb03fMoXYpR2682pzvTEHrZw6Ks0dpmJs3KJWB4kgsK7slfKyKA38j8rDvSU+iBfiB2lo8lTmj9g5Ua8c2hiJcw6EMt8VlLlhgoJLy3heycPTsW04A= + - secure: gl/h7p5S+hfR7Cv2tl53c+biW3Mfhh6P4VI4VxrPFj5Mm1ha89dbMYjPn0PuLkmjaZ2+n9siU7j6lwlOdyWGAo0tkPtK/EC62L2Q938O204jD8VXnvjQ8kbP9zcjHogicD+elF0X5hvnXApW9I7nOZIs59V5Pp8DXkuHEWMIo8U= addons: sauce_connect: true before_install: From fca79d9a93c736328d19686dd1d77c2ed423d778 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sun, 21 Sep 2014 18:30:14 -0600 Subject: [PATCH 0032/1357] caching folders to reduce build time --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index d408bd4db..63d45919a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,11 @@ env: - secure: gl/h7p5S+hfR7Cv2tl53c+biW3Mfhh6P4VI4VxrPFj5Mm1ha89dbMYjPn0PuLkmjaZ2+n9siU7j6lwlOdyWGAo0tkPtK/EC62L2Q938O204jD8VXnvjQ8kbP9zcjHogicD+elF0X5hvnXApW9I7nOZIs59V5Pp8DXkuHEWMIo8U= addons: sauce_connect: true +cache: + directories: + - node_modules + - test/fixtures/node_modules + - test/fixtures/bower_components before_install: - gem update --system - gem install sass --version "=3.3.7" From f9e7f6d7af72201675a1f528062313df95b098d4 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sun, 21 Sep 2014 18:38:38 -0600 Subject: [PATCH 0033/1357] revert caching --- .travis.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 63d45919a..d408bd4db 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,11 +8,6 @@ env: - secure: gl/h7p5S+hfR7Cv2tl53c+biW3Mfhh6P4VI4VxrPFj5Mm1ha89dbMYjPn0PuLkmjaZ2+n9siU7j6lwlOdyWGAo0tkPtK/EC62L2Q938O204jD8VXnvjQ8kbP9zcjHogicD+elF0X5hvnXApW9I7nOZIs59V5Pp8DXkuHEWMIo8U= addons: sauce_connect: true -cache: - directories: - - node_modules - - test/fixtures/node_modules - - test/fixtures/bower_components before_install: - gem update --system - gem install sass --version "=3.3.7" From 25d91873d1e9adedd39a2d165ca807bfbbf15d5e Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sun, 21 Sep 2014 19:32:57 -0600 Subject: [PATCH 0034/1357] fix test timeouts and sign up test failure --- app/templates/e2e/account(auth)/signup/signup.spec.js | 2 +- test/test-file-creation.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/e2e/account(auth)/signup/signup.spec.js b/app/templates/e2e/account(auth)/signup/signup.spec.js index cc63a5b7b..856786e4a 100644 --- a/app/templates/e2e/account(auth)/signup/signup.spec.js +++ b/app/templates/e2e/account(auth)/signup/signup.spec.js @@ -12,7 +12,7 @@ describe('Signup View', function() { }; var testUser = { - name: 'Test User', + name: 'Test', email: 'test@test.com', password: 'test' }; diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 568315d92..35ca54538 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -348,7 +348,7 @@ describe('angular-fullstack generator', function () { }); it('should run e2e tests successfully', function(done) { - this.timeout(80000); + this.timeout(240000); // 4 minutes gen.run({}, function () { exec('grunt test:e2e', function (error, stdout, stderr) { expect(stdout, 'Client tests failed \n' + stdout).to.contain('0 failures'); From 2f3ee4f5cb790144d8b2d24c6e4f56d814fa1375 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sun, 21 Sep 2014 19:50:56 -0600 Subject: [PATCH 0035/1357] run e2e tests for other builds --- .../app/account(auth)/login/login(jade).jade | 2 +- test/test-file-creation.js | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/app/templates/client/app/account(auth)/login/login(jade).jade b/app/templates/client/app/account(auth)/login/login(jade).jade index 686b1769e..5f608a67b 100644 --- a/app/templates/client/app/account(auth)/login/login(jade).jade +++ b/app/templates/client/app/account(auth)/login/login(jade).jade @@ -20,7 +20,7 @@ div(ng-include='"components/navbar/navbar.html"') form.form(name='form', ng-submit='login(form)', novalidate='') .form-group label Email - input.form-control(type='text', name='email', ng-model='user.email') + input.form-control(type='email', name='email', ng-model='user.email') .form-group label Password input.form-control(type='password', name='password', ng-model='user.password') diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 35ca54538..5eab66047 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -408,6 +408,16 @@ describe('angular-fullstack generator', function () { assertOnlyFiles(genFiles(testOptions), done); }); }); + + it('should run e2e tests successfully', function(done) { + this.timeout(240000); // 4 minutes + gen.run({}, function () { + exec('grunt test:e2e', function (error, stdout, stderr) { + expect(stdout, 'Client tests failed \n' + stdout).to.contain('0 failures'); + done(); + }); + }); + }); }); describe('with other preprocessors and no server options', function() { @@ -461,6 +471,16 @@ describe('angular-fullstack generator', function () { assertOnlyFiles(genFiles(testOptions), done); }); }); + + it('should run e2e tests successfully', function(done) { + this.timeout(240000); // 4 minutes + gen.run({}, function () { + exec('grunt test:e2e', function (error, stdout, stderr) { + expect(stdout, 'Client tests failed \n' + stdout).to.contain('0 failures'); + done(); + }); + }); + }); }); describe('with no preprocessors and no server options', function() { @@ -506,6 +526,16 @@ describe('angular-fullstack generator', function () { assertOnlyFiles(genFiles(testOptions), done); }); }); + + it('should run e2e tests successfully', function(done) { + this.timeout(240000); // 4 minutes + gen.run({}, function () { + exec('grunt test:e2e', function (error, stdout, stderr) { + expect(stdout, 'Client tests failed \n' + stdout).to.contain('0 failures'); + done(); + }); + }); + }); }); }); }); From 4bf07505509b64c65906220ec12da3288402790f Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sun, 21 Sep 2014 20:14:23 -0600 Subject: [PATCH 0036/1357] chore(docs): remove outdated readme from test folder --- test/readme.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 test/readme.md diff --git a/test/readme.md b/test/readme.md deleted file mode 100644 index 6c709f50b..000000000 --- a/test/readme.md +++ /dev/null @@ -1 +0,0 @@ -Run bower install and npm install in the fixtures folder before running tests \ No newline at end of file From c131bc4d451e02404785130df0f5b36ad8802da8 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sun, 21 Sep 2014 22:15:24 -0600 Subject: [PATCH 0037/1357] make tests more dry --- test/test-file-creation.js | 42 +++++++++++++------------------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 5eab66047..aecb08dcb 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -61,6 +61,16 @@ describe('angular-fullstack generator', function () { }); } + function runE2E() { + this.timeout(240000); // 4 minutes + gen.run({}, function () { + exec('grunt test:e2e', function (error, stdout, stderr) { + expect(stdout, 'Client tests failed \n' + stdout).to.contain('0 failures'); + done(); + }); + }); + }; + function runTest(cmd, self, cb) { var args = Array.prototype.slice.call(arguments), endpoint = (args[3] && typeof args[3] === 'string') ? args.splice(3, 1)[0] : null, @@ -348,13 +358,7 @@ describe('angular-fullstack generator', function () { }); it('should run e2e tests successfully', function(done) { - this.timeout(240000); // 4 minutes - gen.run({}, function () { - exec('grunt test:e2e', function (error, stdout, stderr) { - expect(stdout, 'Client tests failed \n' + stdout).to.contain('0 failures'); - done(); - }); - }); + runE2E(); }); }); @@ -410,13 +414,7 @@ describe('angular-fullstack generator', function () { }); it('should run e2e tests successfully', function(done) { - this.timeout(240000); // 4 minutes - gen.run({}, function () { - exec('grunt test:e2e', function (error, stdout, stderr) { - expect(stdout, 'Client tests failed \n' + stdout).to.contain('0 failures'); - done(); - }); - }); + runE2E(); }); }); @@ -473,13 +471,7 @@ describe('angular-fullstack generator', function () { }); it('should run e2e tests successfully', function(done) { - this.timeout(240000); // 4 minutes - gen.run({}, function () { - exec('grunt test:e2e', function (error, stdout, stderr) { - expect(stdout, 'Client tests failed \n' + stdout).to.contain('0 failures'); - done(); - }); - }); + runE2E(); }); }); @@ -528,13 +520,7 @@ describe('angular-fullstack generator', function () { }); it('should run e2e tests successfully', function(done) { - this.timeout(240000); // 4 minutes - gen.run({}, function () { - exec('grunt test:e2e', function (error, stdout, stderr) { - expect(stdout, 'Client tests failed \n' + stdout).to.contain('0 failures'); - done(); - }); - }); + runE2E(); }); }); }); From 828857bbd1a2c4147ecd943fdc9a6625888e89ec Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Mon, 22 Sep 2014 01:51:23 -0600 Subject: [PATCH 0038/1357] fix test failure --- test/test-file-creation.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/test/test-file-creation.js b/test/test-file-creation.js index aecb08dcb..31ed71ab2 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -61,8 +61,8 @@ describe('angular-fullstack generator', function () { }); } - function runE2E() { - this.timeout(240000); // 4 minutes + function runE2E(self, done) { + self.timeout(240000); // 4 minutes gen.run({}, function () { exec('grunt test:e2e', function (error, stdout, stderr) { expect(stdout, 'Client tests failed \n' + stdout).to.contain('0 failures'); @@ -87,6 +87,9 @@ describe('angular-fullstack generator', function () { case 'grunt jshint': expect(stdout).to.contain('Done, without errors.'); break; + case 'grunt jscs': + expect(stdout).to.contain('Done, without errors.'); + break; case 'grunt test:server': expect(stdout, 'Server tests failed (do you have mongoDB running?) \n' + stdout).to.contain('Done, without errors.'); break; @@ -358,7 +361,7 @@ describe('angular-fullstack generator', function () { }); it('should run e2e tests successfully', function(done) { - runE2E(); + runE2E(this, done); }); }); @@ -414,7 +417,7 @@ describe('angular-fullstack generator', function () { }); it('should run e2e tests successfully', function(done) { - runE2E(); + runE2E(this, done); }); }); @@ -471,7 +474,7 @@ describe('angular-fullstack generator', function () { }); it('should run e2e tests successfully', function(done) { - runE2E(); + runE2E(this, done); }); }); @@ -520,7 +523,7 @@ describe('angular-fullstack generator', function () { }); it('should run e2e tests successfully', function(done) { - runE2E(); + runE2E(this, done); }); }); }); From 4667013bb9f621e514a3f178985389ddc1d8af10 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Thu, 25 Sep 2014 19:40:11 -0600 Subject: [PATCH 0039/1357] update sauce labs config so e2e tests can run against pull requests --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index d408bd4db..6b84b4557 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,8 +4,8 @@ node_js: - '0.11' env: global: - - secure: hwJX8w4D15UPdU4UIS+iB4XC/lxmh/y6m3IN5Ia5ha++rHs2JZ3FVOPdosb03fMoXYpR2682pzvTEHrZw6Ks0dpmJs3KJWB4kgsK7slfKyKA38j8rDvSU+iBfiB2lo8lTmj9g5Ua8c2hiJcw6EMt8VlLlhgoJLy3heycPTsW04A= - - secure: gl/h7p5S+hfR7Cv2tl53c+biW3Mfhh6P4VI4VxrPFj5Mm1ha89dbMYjPn0PuLkmjaZ2+n9siU7j6lwlOdyWGAo0tkPtK/EC62L2Q938O204jD8VXnvjQ8kbP9zcjHogicD+elF0X5hvnXApW9I7nOZIs59V5Pp8DXkuHEWMIo8U= + - SAUCE_USERNAME=fullstack-ci + - SAUCE_ACCESS_KEY=1a527ca6-4aa5-4618-86ce-0278bf158cbf addons: sauce_connect: true before_install: From d2bd1f5d820e0fd03f81ab7aa8d3880530721195 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Thu, 25 Sep 2014 23:12:25 -0600 Subject: [PATCH 0040/1357] fix sauce username --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6b84b4557..676afbb43 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ node_js: - '0.11' env: global: - - SAUCE_USERNAME=fullstack-ci + - SAUCE_USERNAME=fullstack_ci - SAUCE_ACCESS_KEY=1a527ca6-4aa5-4618-86ce-0278bf158cbf addons: sauce_connect: true From 654de87ff7d695b9ff8d2b91b43f0b860d6c7e56 Mon Sep 17 00:00:00 2001 From: kingcody Date: Mon, 22 Sep 2014 06:37:09 -0400 Subject: [PATCH 0041/1357] feat(gen): unify testing framework Changes: - add prompt for Jasmine or Mocha - if Mocha choosen, prompt for Expect or Should - use `<%= does() %>` to dynamically insert assertions (expect|should) - add mocha variants for protractor tests - add mocha options to protractor.conf - remove `test/fixtures/(bower|package).json` from repo - move runE2E functionality to runTest and simplify switch - comment generator test functions - use node `0.11.13` in travis due to issues with `0.11.14`+ Note: Server-side jasmine test are needed to fully unify testing frameworks. Once Jasmine tests are included for server, mocha dep can be removed fully when selecting Jasmine. --- .travis.yml | 2 +- app/index.js | 133 +++++++++++++----- app/templates/_package.json | 18 ++- .../main/main.controller.spec(coffee).coffee | 5 +- .../app/main/main.controller.spec(js).js | 5 +- .../{login.spec.js => login.spec(jasmine).js} | 0 .../account(auth)/login/login.spec(mocha).js | 73 ++++++++++ ...logout.spec.js => logout.spec(jasmine).js} | 0 .../logout/logout.spec(mocha).js | 50 +++++++ ...signup.spec.js => signup.spec(jasmine).js} | 0 .../signup/signup.spec(mocha).js | 72 ++++++++++ .../{main.spec.js => main.spec(jasmine).js} | 0 app/templates/e2e/main/main.spec(mocha).js | 16 +++ app/templates/karma.conf.js | 13 +- app/templates/mocha.conf.js | 16 ++- app/templates/protractor.conf.js | 26 +++- script-base.js | 11 +- test/fixtures/bower.json | 25 ---- test/fixtures/package.json | 104 -------------- test/test-file-creation.js | 85 ++++++++--- 20 files changed, 438 insertions(+), 216 deletions(-) rename app/templates/e2e/account(auth)/login/{login.spec.js => login.spec(jasmine).js} (100%) create mode 100644 app/templates/e2e/account(auth)/login/login.spec(mocha).js rename app/templates/e2e/account(auth)/logout/{logout.spec.js => logout.spec(jasmine).js} (100%) create mode 100644 app/templates/e2e/account(auth)/logout/logout.spec(mocha).js rename app/templates/e2e/account(auth)/signup/{signup.spec.js => signup.spec(jasmine).js} (100%) create mode 100644 app/templates/e2e/account(auth)/signup/signup.spec(mocha).js rename app/templates/e2e/main/{main.spec.js => main.spec(jasmine).js} (100%) create mode 100644 app/templates/e2e/main/main.spec(mocha).js delete mode 100644 test/fixtures/bower.json delete mode 100644 test/fixtures/package.json diff --git a/.travis.yml b/.travis.yml index 676afbb43..e1abfbd26 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: node_js node_js: - '0.10' - - '0.11' + - '0.11.13' env: global: - SAUCE_USERNAME=fullstack_ci diff --git a/app/index.js b/app/index.js index 6e4724801..7dcee4d55 100644 --- a/app/index.js +++ b/app/index.js @@ -24,6 +24,15 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ this.pkg = require('../package.json'); this.filters = {}; + + // dynamic assertion statement + this.does = this.is = function(foo) { + if (this.filters.should) { + return foo + '.should'; + } else { + return 'expect(' + foo + ').to'; + } + }.bind(this); }, info: function () { @@ -36,9 +45,9 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ if(this.config.get('filters')) { this.prompt([{ - type: "confirm", - name: "skipConfig", - message: "Existing .yo-rc configuration found, would you like to use it?", + type: 'confirm', + name: 'skipConfig', + message: 'Existing .yo-rc configuration found, would you like to use it?', default: true, }], function (answers) { this.skipConfig = answers.skipConfig; @@ -66,10 +75,10 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ this.log('# Client\n'); this.prompt([{ - type: "list", - name: "script", - message: "What would you like to write scripts with?", - choices: [ "JavaScript", "CoffeeScript"], + type: 'list', + name: 'script', + message: 'What would you like to write scripts with?', + choices: [ 'JavaScript', 'CoffeeScript'], filter: function( val ) { var filterMap = { 'JavaScript': 'js', @@ -79,33 +88,33 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ return filterMap[val]; } }, { - type: "list", - name: "markup", - message: "What would you like to write markup with?", - choices: [ "HTML", "Jade"], + type: 'list', + name: 'markup', + message: 'What would you like to write markup with?', + choices: [ 'HTML', 'Jade'], filter: function( val ) { return val.toLowerCase(); } }, { - type: "list", - name: "stylesheet", + type: 'list', + name: 'stylesheet', default: 1, - message: "What would you like to write stylesheets with?", - choices: [ "CSS", "Sass", "Stylus", "Less"], + message: 'What would you like to write stylesheets with?', + choices: [ 'CSS', 'Sass', 'Stylus', 'Less'], filter: function( val ) { return val.toLowerCase(); } }, { - type: "list", - name: "router", + type: 'list', + name: 'router', default: 1, - message: "What Angular router would you like to use?", - choices: [ "ngRoute", "uiRouter"], + message: 'What Angular router would you like to use?', + choices: [ 'ngRoute', 'uiRouter'], filter: function( val ) { return val.toLowerCase(); } }, { - type: "confirm", - name: "bootstrap", - message: "Would you like to include Bootstrap?" + type: 'confirm', + name: 'bootstrap', + message: 'Would you like to include Bootstrap?' }, { - type: "confirm", - name: "uibootstrap", - message: "Would you like to include UI Bootstrap?", + type: 'confirm', + name: 'uibootstrap', + message: 'Would you like to include UI Bootstrap?', when: function (answers) { return answers.bootstrap; } @@ -116,7 +125,7 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ this.filters[answers.router] = true; this.filters.bootstrap = !!answers.bootstrap; this.filters.uibootstrap = !!answers.uibootstrap; - cb(); + cb(); }.bind(this)); }, @@ -128,13 +137,13 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ this.log('\n# Server\n'); this.prompt([{ - type: "confirm", - name: "mongoose", - message: "Would you like to use mongoDB with Mongoose for data modeling?" + type: 'confirm', + name: 'mongoose', + message: 'Would you like to use mongoDB with Mongoose for data modeling?' }, { - type: "confirm", - name: "auth", - message: "Would you scaffold out an authentication boilerplate?", + type: 'confirm', + name: 'auth', + message: 'Would you scaffold out an authentication boilerplate?', when: function (answers) { return answers.mongoose; } @@ -163,9 +172,9 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ } ] }, { - type: "confirm", - name: "socketio", - message: "Would you like to use socket.io?", + type: 'confirm', + name: 'socketio', + message: 'Would you like to use socket.io?', // to-do: should not be dependent on mongoose when: function (answers) { return answers.mongoose; @@ -186,6 +195,47 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ }.bind(this)); }, + projectPrompts: function() { + if(this.skipConfig) return; + var cb = this.async(); + var self = this; + + this.log('\n# Project\n'); + + this.prompt([{ + type: 'list', + name: 'testing', + message: 'What would you like to write tests with?', + choices: [ 'Jasmine', 'Mocha + Chai + Sinon'], + filter: function( val ) { + var filterMap = { + 'Jasmine': 'jasmine', + 'Mocha + Chai + Sinon': 'mocha' + }; + + return filterMap[val]; + } + }, { + type: 'list', + name: 'chai', + message: 'What would you like to write Chai assertions with?', + choices: ['Expect', 'Should'], + filter: function( val ) { + return val.toLowerCase(); + }, + when: function( answers ) { + return answers.testing === 'mocha'; + } + }], function (answers) { + this.filters[answers.testing] = true; + if (this.filters.mocha) { + this.filters[answers.chai] = true; + } + + cb(); + }.bind(this)); + }, + saveSettings: function() { if(this.skipConfig) return; this.config.set('insertRoutes', true); @@ -207,10 +257,15 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ if(this.skipConfig) return; var appPath = 'client/app/'; var extensions = []; - var filters = []; + var filters = [ + 'ngroute', + 'uirouter', + 'jasmine', + 'mocha', + 'expect', + 'should' + ].filter(function(v) {return this.filters[v];}, this); - if(this.filters.ngroute) filters.push('ngroute'); - if(this.filters.uirouter) filters.push('uirouter'); if(this.filters.coffee) extensions.push('coffee'); if(this.filters.js) extensions.push('js'); if(this.filters.html) extensions.push('html'); @@ -249,7 +304,7 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ if(this.filters.uirouter) angModules.push("'ui.router'"); if(this.filters.uibootstrap) angModules.push("'ui.bootstrap'"); - this.angularModules = "\n " + angModules.join(",\n ") +"\n"; + this.angularModules = '\n ' + angModules.join(',\n ') +'\n'; }, generate: function() { diff --git a/app/templates/_package.json b/app/templates/_package.json index 1912903fa..08784aa6c 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -31,7 +31,6 @@ "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,9 +61,7 @@ "grunt-protractor-runner": "^1.1.0", "grunt-asset-injector": "^0.1.0", "grunt-karma": "~0.8.2", - "grunt-build-control": "DaftMonk/grunt-build-control", - "grunt-mocha-test": "~0.10.2", - "grunt-mocha-istanbul": "^2.0.0",<% if(filters.sass) { %> + "grunt-build-control": "DaftMonk/grunt-build-control",<% if(filters.sass) { %> "grunt-contrib-sass": "^0.7.3",<% } %><% if(filters.stylus) { %> "grunt-contrib-stylus": "latest",<% } %> "jit-grunt": "^0.5.0", @@ -74,12 +71,19 @@ "open": "~0.0.4", "jshint-stylish": "~0.1.5", "connect-livereload": "~0.4.0", + "grunt-mocha-test": "~0.10.2", + "grunt-mocha-istanbul": "^2.0.0", + "chai-as-promised": "^4.1.1", + "chai-things": "^0.2.0", + "sinon-chai": "^2.5.0",<% if(filters.mocha) { %> + "karma-mocha": "^0.1.9", + "karma-chai-plugins": "^0.2.3",<% } if(filters.jasmine) { %> + "karma-jasmine": "~0.1.5",<% } %> "karma-ng-scenario": "~0.1.0", "karma-firefox-launcher": "~0.1.3", "karma-script-launcher": "~0.1.0", "karma-html2js-preprocessor": "~0.1.0", "karma-ng-jade2js-preprocessor": "^0.1.2", - "karma-jasmine": "~0.1.5", "karma-chrome-launcher": "~0.1.3", "requirejs": "~2.1.11", "karma-requirejs": "~0.2.1", @@ -88,9 +92,9 @@ "karma-phantomjs-launcher": "~0.1.4", "karma": "~0.12.9", "karma-ng-html2js-preprocessor": "~0.1.0", + "karma-spec-reporter": "0.0.13", "proxyquire": "^1.0.1", - "supertest": "~0.11.0", - "sinon-chai": "^2.5.0" + "supertest": "~0.11.0" }, "engines": { "node": ">=0.10.0" diff --git a/app/templates/client/app/main/main.controller.spec(coffee).coffee b/app/templates/client/app/main/main.controller.spec(coffee).coffee index f974a081d..5bdf4f840 100644 --- a/app/templates/client/app/main/main.controller.spec(coffee).coffee +++ b/app/templates/client/app/main/main.controller.spec(coffee).coffee @@ -27,5 +27,6 @@ describe 'Controller: MainCtrl', -> $scope: scope it 'should attach a list of things to the scope', -> - $httpBackend.flush() - expect(scope.awesomeThings.length).toBe 4 + $httpBackend.flush()<% if (filters.jasmine) { %> + expect(scope.awesomeThings.length).toBe 4 <% } if (filters.mocha) { %> + <%= does("scope.awesomeThings.length") %>.equal 4<% } %> diff --git a/app/templates/client/app/main/main.controller.spec(js).js b/app/templates/client/app/main/main.controller.spec(js).js index 21b8aba70..dc048b4af 100644 --- a/app/templates/client/app/main/main.controller.spec(js).js +++ b/app/templates/client/app/main/main.controller.spec(js).js @@ -26,7 +26,8 @@ describe('Controller: MainCtrl', function () { })); it('should attach a list of things to the scope', function () { - $httpBackend.flush(); - expect(scope.awesomeThings.length).toBe(4); + $httpBackend.flush();<% if (filters.jasmine) { %> + expect(scope.awesomeThings.length).toBe(4);<% } if (filters.mocha) { %> + <%= does("scope.awesomeThings.length") %>.equal(4);<% } %> }); }); diff --git a/app/templates/e2e/account(auth)/login/login.spec.js b/app/templates/e2e/account(auth)/login/login.spec(jasmine).js similarity index 100% rename from app/templates/e2e/account(auth)/login/login.spec.js rename to app/templates/e2e/account(auth)/login/login.spec(jasmine).js diff --git a/app/templates/e2e/account(auth)/login/login.spec(mocha).js b/app/templates/e2e/account(auth)/login/login.spec(mocha).js new file mode 100644 index 000000000..a2c986f32 --- /dev/null +++ b/app/templates/e2e/account(auth)/login/login.spec(mocha).js @@ -0,0 +1,73 @@ +'use strict'; + +var config = protractor.getInstance().params; +var UserModel = require(config.serverConfig.root + '/server/api/user/user.model'); + +describe('Login View', function() { + var page; + + var loadPage = function() { + browser.get('/login'); + page = require('./login.po'); + }; + + var testUser = { + name: 'Test User', + email: 'test@test.com', + password: 'test' + }; + + before(function() { + return UserModel + .removeAsync() + .then(function() { + return UserModel.createAsync(testUser); + }) + .then(loadPage); + }); + + after(function() { + return UserModel.removeAsync(); + }); + + it('should include login form with correct inputs and submit button', function() { + <%= does("page.form.email.getAttribute('type')") %>.eventually.equal('email'); + <%= does("page.form.email.getAttribute('name')") %>.eventually.equal('email'); + <%= does("page.form.password.getAttribute('type')") %>.eventually.equal('password'); + <%= does("page.form.password.getAttribute('name')") %>.eventually.equal('password'); + <%= does("page.form.submit.getAttribute('type')") %>.eventually.equal('submit'); + <%= does("page.form.submit.getText()") %>.eventually.equal('Login'); + }); + + describe('with local auth', function() { + + it('should login a user and redirecting to "/"', function() { + page.login(testUser); + + var navbar = require('../../components/navbar/navbar.po'); + + <%= does("browser.getLocationAbsUrl()") %>.eventually.equal(config.baseUrl + '/'); + <%= does("navbar.navbarAccountGreeting.getText()") %>.eventually.equal('Hello ' + testUser.name); + }); + + describe('and invalid credentials', function() { + before(function() { + return loadPage(); + }) + + it('should indicate login failures', function() { + page.login({ + email: testUser.email, + password: 'badPassword' + }); + + <%= does("browser.getLocationAbsUrl()") %>.eventually.equal(config.baseUrl + '/login'); + + var helpBlock = page.form.element(by.css('.form-group.has-error .help-block.ng-binding')); + <%= does("helpBlock.getText()") %>.eventually.equal('This password is not correct.'); + }); + + }); + + }); +}); diff --git a/app/templates/e2e/account(auth)/logout/logout.spec.js b/app/templates/e2e/account(auth)/logout/logout.spec(jasmine).js similarity index 100% rename from app/templates/e2e/account(auth)/logout/logout.spec.js rename to app/templates/e2e/account(auth)/logout/logout.spec(jasmine).js diff --git a/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js b/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js new file mode 100644 index 000000000..3adba51f8 --- /dev/null +++ b/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js @@ -0,0 +1,50 @@ +'use strict'; + +var config = protractor.getInstance().params; +var UserModel = require(config.serverConfig.root + '/server/api/user/user.model'); + +describe('Logout View', function() { + var login = function(user) { + browser.get('/login'); + require('../login/login.po').login(user); + }; + + var testUser = { + name: 'Test User', + email: 'test@test.com', + password: 'test' + }; + + beforeEach(function() { + return UserModel + .removeAsync() + .then(function() { + return UserModel.createAsync(testUser); + }) + .then(function() { + return login(testUser); + }); + }); + + after(function() { + return UserModel.removeAsync(); + }) + + describe('with local auth', function() { + + it('should logout a user and redirecting to "/"', function() { + var navbar = require('../../components/navbar/navbar.po'); + + <%= does("browser.getLocationAbsUrl()") %>.eventually.equal(config.baseUrl + '/'); + <%= does("navbar.navbarAccountGreeting.getText()") %>.eventually.equal('Hello ' + testUser.name); + + browser.get('/logout'); + + navbar = require('../../components/navbar/navbar.po'); + + <%= does("browser.getLocationAbsUrl()") %>.eventually.equal(config.baseUrl + '/'); + <%= does("navbar.navbarAccountGreeting.isDisplayed()") %>.eventually.equal(false); + }); + + }); +}); diff --git a/app/templates/e2e/account(auth)/signup/signup.spec.js b/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js similarity index 100% rename from app/templates/e2e/account(auth)/signup/signup.spec.js rename to app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js diff --git a/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js b/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js new file mode 100644 index 000000000..6a6b0a775 --- /dev/null +++ b/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js @@ -0,0 +1,72 @@ +'use strict'; + +var config = protractor.getInstance().params; +var UserModel = require(config.serverConfig.root + '/server/api/user/user.model'); + +describe('Signup View', function() { + var page; + + var loadPage = function() { + browser.get('/signup'); + page = require('./signup.po'); + }; + + var testUser = { + name: 'Test', + email: 'test@test.com', + password: 'test' + }; + + before(function() { + return loadPage(); + }); + + after(function() { + return UserModel.removeAsync(); + }); + + it('should include signup form with correct inputs and submit button', function() { + <%= does("page.form.name.getAttribute('type')") %>.eventually.equal('text'); + <%= does("page.form.name.getAttribute('name')") %>.eventually.equal('name'); + <%= does("page.form.email.getAttribute('type')") %>.eventually.equal('email'); + <%= does("page.form.email.getAttribute('name')") %>.eventually.equal('email'); + <%= does("page.form.password.getAttribute('type')") %>.eventually.equal('password'); + <%= does("page.form.password.getAttribute('name')") %>.eventually.equal('password'); + <%= does("page.form.submit.getAttribute('type')") %>.eventually.equal('submit'); + <%= does("page.form.submit.getText()") %>.eventually.equal('Sign up'); + }); + + describe('with local auth', function() { + + it('should signup a new user, log them in, and redirecting to "/"', function(done) { + UserModel.remove(function() { + page.signup(testUser); + + var navbar = require('../../components/navbar/navbar.po'); + + <%= does("browser.getLocationAbsUrl()") %>.eventually.equal(config.baseUrl + '/'); + <%= does("navbar.navbarAccountGreeting.getText()") %>.eventually.equal('Hello ' + testUser.name); + + done(); + }); + }); + + describe('and invalid credentials', function() { + before(function() { + return loadPage(); + }); + + it('should indicate signup failures', function() { + page.signup(testUser); + + <%= does("browser.getLocationAbsUrl()") %>.eventually.equal(config.baseUrl + '/signup'); + <%= does("page.form.email.getAttribute('class')") %>.eventually.contain('ng-invalid-mongoose'); + + var helpBlock = page.form.element(by.css('.form-group.has-error .help-block.ng-binding')); + <%= does("helpBlock.getText()") %>.eventually.equal('The specified email address is already in use.'); + }); + + }); + + }); +}); diff --git a/app/templates/e2e/main/main.spec.js b/app/templates/e2e/main/main.spec(jasmine).js similarity index 100% rename from app/templates/e2e/main/main.spec.js rename to app/templates/e2e/main/main.spec(jasmine).js diff --git a/app/templates/e2e/main/main.spec(mocha).js b/app/templates/e2e/main/main.spec(mocha).js new file mode 100644 index 000000000..1962ba765 --- /dev/null +++ b/app/templates/e2e/main/main.spec(mocha).js @@ -0,0 +1,16 @@ +'use strict'; + +describe('Main View', function() { + var page; + + beforeEach(function() { + browser.get('/'); + page = require('./main.po'); + }); + + it('should include jumbotron with correct data', function() { + <%= does("page.h1El.getText()") %>.eventually.equal('\'Allo, \'Allo!'); + <%= does("page.imgEl.getAttribute('src')") %>.eventually.match(/assets\/images\/yeoman.png$/); + <%= does("page.imgEl.getAttribute('alt')") %>.eventually.equal('I\'m Yeoman'); + }); +}); diff --git a/app/templates/karma.conf.js b/app/templates/karma.conf.js index 57b3fa6f2..6b6c6c477 100644 --- a/app/templates/karma.conf.js +++ b/app/templates/karma.conf.js @@ -6,8 +6,9 @@ module.exports = function(config) { // base path, that will be used to resolve files and exclude basePath: '', - // testing framework to use (jasmine/mocha/qunit/...) - frameworks: ['jasmine'], + // testing framework to use (jasmine/mocha/qunit/...)<% if(filters.jasmine) { %> + frameworks: ['jasmine'],<% } if(filters.mocha) { %> + frameworks: ['mocha', 'chai', 'sinon-chai', 'chai-as-promised', 'chai-things'],<% } %> // list of files / patterns to load in the browser files: [ @@ -58,6 +59,14 @@ module.exports = function(config) { // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG logLevel: config.LOG_INFO, + // reporter types: + // - dots + // - progress (default) + // - spec (karma-spec-reporter) + // - junit + // - growl + // - coverage + reporters: ['spec'], // enable / disable watching file and executing tests whenever any file changes autoWatch: false, diff --git a/app/templates/mocha.conf.js b/app/templates/mocha.conf.js index 497d43b2c..54e33bb6f 100644 --- a/app/templates/mocha.conf.js +++ b/app/templates/mocha.conf.js @@ -1,14 +1,16 @@ 'use strict'; var chai = require('chai'); -var sinon = require('sinon'); -var sinonChai = require('sinon-chai'); -var chaiAsPromised = require('chai-as-promised'); +// Load Chai assertions global.expect = chai.expect; global.assert = chai.assert; -global.sinon = sinon; - chai.should(); -chai.use(sinonChai); -chai.use(chaiAsPromised); + +// Load Sinon +global.sinon = require('sinon'); + +// Initialize Chai plugins +chai.use(require('sinon-chai')); +chai.use(require('chai-as-promised')); +chai.use(require('chai-things')) diff --git a/app/templates/protractor.conf.js b/app/templates/protractor.conf.js index 18b9ba6af..14f704b3d 100644 --- a/app/templates/protractor.conf.js +++ b/app/templates/protractor.conf.js @@ -43,24 +43,40 @@ var config = { // Jasmine and Cucumber are fully supported as a test and assertion framework. // Mocha has limited beta support. You will need to include your own // assertion framework if working with mocha. - framework: 'jasmine', - + framework: '<% if(filters.jasmine) { %>jasmine<% } if(filters.mocha) { %>mocha<% } %>', +<% if(filters.jasmine) { %> // ----- Options to be passed to minijasminenode ----- // // See the full list at https://github.com/juliemr/minijasminenode jasmineNodeOpts: { defaultTimeoutInterval: 30000 - }, + },<% } if(filters.mocha) { %> + // ----- Options to be passed to mocha ----- + mochaOpts: { + reporter: 'spec', + timeout: 30000, + defaultTimeoutInterval: 30000 + },<% } %> // Prepare environment for tests params: { serverConfig: require('./server/config/environment') }, - onPrepare: function() { + onPrepare: function() {<% if(filters.mocha) { %> + // Load Mocha and Chai + plugins + require('./mocha.conf'); + + // Expose should assertions (see https://github.com/angular/protractor/issues/633) + Object.defineProperty( + protractor.promise.Promise.prototype, + 'should', + Object.getOwnPropertyDescriptor(Object.prototype, 'should') + ); +<% } %> var serverConfig = config.params.serverConfig; - // Setup mongo tests + // Setup mongo for tests var mongoose = require('mongoose-bird')(); mongoose.connect(serverConfig.mongo.uri, serverConfig.mongo.options); // Connect to database } diff --git a/script-base.js b/script-base.js index 2f44ce09f..5d6c7dd2e 100644 --- a/script-base.js +++ b/script-base.js @@ -18,8 +18,17 @@ var Generator = module.exports = function Generator() { this.cameledName = this._.camelize(this.name); this.classedName = this._.classify(this.name); + // dynamic assertion statement + this.does = this.is = function(foo) { + if (this.filters.should) { + return foo + '.should'; + } else { + return 'expect(' + foo + ').to'; + } + }.bind(this); + this.filters = this.config.get('filters'); this.sourceRoot(path.join(__dirname, '/templates')); }; -util.inherits(Generator, yeoman.generators.NamedBase); \ No newline at end of file +util.inherits(Generator, yeoman.generators.NamedBase); diff --git a/test/fixtures/bower.json b/test/fixtures/bower.json deleted file mode 100644 index 7d9aae354..000000000 --- a/test/fixtures/bower.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "tempApp", - "version": "0.0.0", - "dependencies": { - "angular": ">=1.2.*", - "json3": "~3.3.1", - "es5-shim": "~3.0.1", - "jquery": "~1.11.0", - "bootstrap-sass-official": "~3.1.1", - "bootstrap": "~3.1.1", - "angular-resource": ">=1.2.*", - "angular-cookies": ">=1.2.*", - "angular-sanitize": ">=1.2.*", - "angular-route": ">=1.2.*", - "angular-bootstrap": "~0.11.0", - "font-awesome": ">=4.1.0", - "lodash": "~2.4.1", - "angular-socket-io": "~0.6.0", - "angular-ui-router": "~0.2.10" - }, - "devDependencies": { - "angular-mocks": ">=1.2.*", - "angular-scenario": ">=1.2.*" - } -} diff --git a/test/fixtures/package.json b/test/fixtures/package.json deleted file mode 100644 index 48d48607e..000000000 --- a/test/fixtures/package.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "name": "tempApp", - "version": "0.0.0", - "main": "server/app.js", - "dependencies": { - "express": "~4.0.0", - "morgan": "~1.0.0", - "body-parser": "~1.5.0", - "method-override": "~1.0.0", - "serve-favicon": "~2.0.1", - "cookie-parser": "~1.0.1", - "express-session": "~1.0.2", - "errorhandler": "~1.0.0", - "compression": "~1.0.1", - "lodash": "~2.4.1", - "jade": "~1.2.0", - "ejs": "~0.8.4", - "mongoose": "~3.8.8", - "mongoose-bird": "~0.0.1", - "jsonwebtoken": "^0.3.0", - "express-jwt": "^0.1.3", - "passport": "~0.2.0", - "passport-local": "~0.1.6", - "passport-facebook": "latest", - "passport-twitter": "latest", - "passport-google-oauth": "latest", - "composable-middleware": "^0.3.0", - "connect-mongo": "^0.4.1", - "socket.io": "^1.0.6", - "socket.io-client": "^1.0.6", - "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", - "grunt-concurrent": "~0.5.0", - "grunt-contrib-clean": "~0.5.0", - "grunt-contrib-concat": "~0.4.0", - "grunt-contrib-copy": "~0.5.0", - "grunt-contrib-cssmin": "~0.9.0", - "grunt-contrib-htmlmin": "~0.2.0", - "grunt-contrib-imagemin": "~0.7.1", - "grunt-contrib-jshint": "~0.10.0", - "grunt-contrib-uglify": "~0.4.0", - "grunt-contrib-watch": "~0.6.1", - "grunt-contrib-coffee": "^0.10.1", - "grunt-contrib-jade": "^0.11.0", - "grunt-contrib-less": "^0.11.4", - "grunt-google-cdn": "~0.4.0", - "grunt-newer": "~0.7.0", - "grunt-ng-annotate": "^0.2.3", - "grunt-rev": "~0.1.0", - "grunt-svgmin": "~0.4.0", - "grunt-usemin": "~2.1.1", - "grunt-env": "~0.4.1", - "grunt-node-inspector": "~0.1.5", - "grunt-nodemon": "~0.2.0", - "grunt-angular-templates": "^0.5.4", - "grunt-dom-munger": "^3.4.0", - "grunt-protractor-runner": "^1.1.0", - "grunt-asset-injector": "^0.1.0", - "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", - "time-grunt": "~0.3.1", - "grunt-express-server": "~0.4.17", - "grunt-open": "~0.2.3", - "open": "~0.0.4", - "jshint-stylish": "~0.1.5", - "connect-livereload": "~0.4.0", - "karma-ng-scenario": "~0.1.0", - "karma-firefox-launcher": "~0.1.3", - "karma-script-launcher": "~0.1.0", - "karma-html2js-preprocessor": "~0.1.0", - "karma-ng-jade2js-preprocessor": "^0.1.2", - "karma-jasmine": "~0.1.5", - "karma-chrome-launcher": "~0.1.3", - "requirejs": "~2.1.11", - "karma-requirejs": "~0.2.1", - "karma-coffee-preprocessor": "~0.2.1", - "karma-jade-preprocessor": "0.0.11", - "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", - "sinon-chai": "^2.5.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "scripts": { - "start": "node server/app.js", - "test": "grunt test", - "update-webdriver": "node node_modules/grunt-protractor-runner/node_modules/protractor/bin/webdriver-manager update" - }, - "private": true -} diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 31ed71ab2..7db1d4afe 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -14,6 +14,8 @@ describe('angular-fullstack generator', function () { markup: 'html', stylesheet: 'sass', router: 'uirouter', + testing: 'mocha', + chai: 'expect', bootstrap: true, uibootstrap: true, mongoose: true, @@ -35,9 +37,18 @@ describe('angular-fullstack generator', function () { }); } + /** + * Assert that only an array of files exist at a given path + * + * @param {Array} expectedFiles - array of files + * @param {Function} done - callback(error{Error}) + * @param {String} path - top level path to assert files at (optional) + * @param {Array} skip - array of paths to skip/ignore (optional) + * + */ function assertOnlyFiles(expectedFiles, done, path, skip) { path = path || './'; - skip = skip || ['e2e', 'node_modules', 'client/bower_components']; + skip = skip || ['node_modules', 'client/bower_components']; recursiveReadDir(path, skip, function(err, actualFiles) { if (err) { return done(err); } @@ -61,16 +72,16 @@ describe('angular-fullstack generator', function () { }); } - function runE2E(self, done) { - self.timeout(240000); // 4 minutes - gen.run({}, function () { - exec('grunt test:e2e', function (error, stdout, stderr) { - expect(stdout, 'Client tests failed \n' + stdout).to.contain('0 failures'); - done(); - }); - }); - }; - + /** + * Exec a command and run test assertion(s) based on command type + * + * @param {String} cmd - the command to exec + * @param {Object} self - context of the test + * @param {Function} cb - callback() + * @param {String} endpoint - endpoint to generate before exec (optional) + * @param {Number} timeout - timeout for the exec and test (optional) + * + */ function runTest(cmd, self, cb) { var args = Array.prototype.slice.call(arguments), endpoint = (args[3] && typeof args[3] === 'string') ? args.splice(3, 1)[0] : null, @@ -81,15 +92,14 @@ describe('angular-fullstack generator', function () { var execFn = function() { exec(cmd, function(error, stdout, stderr) { switch(cmd) { - case 'grunt test:client': - expect(stdout, 'Client tests failed \n' + stdout ).to.contain('Executed 1 of 1\u001b[32m SUCCESS\u001b'); - break; case 'grunt jshint': - expect(stdout).to.contain('Done, without errors.'); - break; case 'grunt jscs': expect(stdout).to.contain('Done, without errors.'); break; + case 'grunt test:client': + case 'grunt test:e2e': + expect(stdout, 'Client tests failed \n' + stdout).to.contain('Done, without errors.'); + break; case 'grunt test:server': expect(stdout, 'Server tests failed (do you have mongoDB running?) \n' + stdout).to.contain('Done, without errors.'); break; @@ -108,6 +118,13 @@ describe('angular-fullstack generator', function () { } } + /** + * Generate an array of files to expect from a set of options + * + * @param {Object} ops - generator options + * @return {Array} - array of files + * + */ function genFiles(ops) { var mapping = { stylesheet: { @@ -127,6 +144,13 @@ describe('angular-fullstack generator', function () { }, files = []; + /** + * Generate an array of OAuth files based on type + * + * @param {String} type - type of oauth + * @return {Array} - array of files + * + */ var oauthFiles = function(type) { return [ 'server/auth/' + type + '/index.js', @@ -139,6 +163,7 @@ describe('angular-fullstack generator', function () { markup = mapping.markup[ops.markup], stylesheet = mapping.stylesheet[ops.stylesheet]; + /* Core Files */ files = files.concat([ 'client/.htaccess', 'client/.jshintrc', @@ -172,6 +197,9 @@ describe('angular-fullstack generator', function () { 'server/config/environment/production.js', 'server/config/environment/test.js', 'server/views/404.' + markup, + 'e2e/main/main.po.js', + 'e2e/main/main.spec.js', + 'e2e/components/navbar/navbar.po.js', '.bowerrc', '.buildignore', '.editorconfig', @@ -187,12 +215,14 @@ describe('angular-fullstack generator', function () { 'protractor.conf.js' ]); + /* Ui-Router */ if (ops.router === 'uirouter') { files = files.concat([ 'client/components/ui-router/ui-router.mock.' + script ]); } + /* Ui-Bootstrap */ if (ops.uibootstrap) { files = files.concat([ 'client/components/modal/modal.' + markup, @@ -201,6 +231,7 @@ describe('angular-fullstack generator', function () { ]); } + /* Mongoose */ if (ops.mongoose) { files = files.concat([ 'server/api/thing/thing.model.js', @@ -208,6 +239,7 @@ describe('angular-fullstack generator', function () { ]); } + /* Authentication */ if (ops.auth) { files = files.concat([ 'client/app/account/account.' + script, @@ -234,16 +266,23 @@ describe('angular-fullstack generator', function () { 'server/auth/index.js', 'server/auth/auth.service.js', 'server/auth/local/index.js', - 'server/auth/local/passport.js' + 'server/auth/local/passport.js', + 'e2e/account/login/login.po.js', + 'e2e/account/login/login.spec.js', + 'e2e/account/logout/logout.spec.js', + 'e2e/account/signup/signup.po.js', + 'e2e/account/signup/signup.spec.js' ]); } + /* OAuth (see oauthFiles function above) */ if (ops.oauth) { ops.oauth.forEach(function(type, i) { files = files.concat(oauthFiles(type.replace('Auth', ''))); }); } + /* Socket.IO */ if (ops.socketio) { files = files.concat([ 'client/components/socket/socket.service.' + script, @@ -361,7 +400,7 @@ describe('angular-fullstack generator', function () { }); it('should run e2e tests successfully', function(done) { - runE2E(this, done); + runTest('grunt test:e2e', this, done, 240000); }); }); @@ -371,6 +410,7 @@ describe('angular-fullstack generator', function () { markup: 'jade', stylesheet: 'less', router: 'uirouter', + testing: 'jasmine', mongoose: true, auth: true, oauth: ['twitterAuth', 'facebookAuth', 'googleAuth'], @@ -417,7 +457,7 @@ describe('angular-fullstack generator', function () { }); it('should run e2e tests successfully', function(done) { - runE2E(this, done); + runTest('grunt test:e2e', this, done, 240000); }); }); @@ -427,6 +467,8 @@ describe('angular-fullstack generator', function () { markup: 'jade', stylesheet: 'stylus', router: 'ngroute', + testing: 'mocha', + chai: 'should', mongoose: false, auth: false, oauth: [], @@ -474,7 +516,7 @@ describe('angular-fullstack generator', function () { }); it('should run e2e tests successfully', function(done) { - runE2E(this, done); + runTest('grunt test:e2e', this, done, 240000); }); }); @@ -484,6 +526,7 @@ describe('angular-fullstack generator', function () { markup: 'html', stylesheet: 'css', router: 'ngroute', + testing: 'jasmine', mongoose: false, auth: false, oauth: [], @@ -523,7 +566,7 @@ describe('angular-fullstack generator', function () { }); it('should run e2e tests successfully', function(done) { - runE2E(this, done); + runTest('grunt test:e2e', this, done, 240000); }); }); }); From 696c6fb9336e3319083dd7a684da541996b22db7 Mon Sep 17 00:00:00 2001 From: BenFradet Date: Sat, 27 Sep 2014 17:16:18 +0200 Subject: [PATCH 0042/1357] docs(gen:endpoint): standardized comments --- endpoint/templates/name.controller.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/endpoint/templates/name.controller.js b/endpoint/templates/name.controller.js index 2afb2be8c..87dd641de 100644 --- a/endpoint/templates/name.controller.js +++ b/endpoint/templates/name.controller.js @@ -50,7 +50,7 @@ function removeEntity(res){ }; }<% } %> -// Get list of <%= name %>s +// Gets list of <%= name %>s from the DB. exports.index = function(req, res) {<% if (!filters.mongoose) { %> res.json([]);<% } if (filters.mongoose) { %> <%= classedName %>.findAsync() @@ -58,7 +58,7 @@ exports.index = function(req, res) {<% if (!filters.mongoose) { %> .catch(handleError(res));<% } %> };<% if (filters.mongoose) { %> -// Get a single <%= name %> +// Gets a single <%= name %> from the DB. exports.show = function(req, res) { <%= classedName %>.findByIdAsync(req.params.id) .then(handleEntityNotFound(res)) From a29b71310239b2ef6a7e39ea077781abb78e582f Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sat, 27 Sep 2014 23:52:15 -0600 Subject: [PATCH 0043/1357] remove sauce connect addon from travis and replace with shell script --- .travis.yml | 5 ++- scripts/sauce_connect_setup.sh | 60 ++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 3 deletions(-) create mode 100755 scripts/sauce_connect_setup.sh diff --git a/.travis.yml b/.travis.yml index e1abfbd26..598a4b2ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,10 +6,9 @@ env: global: - SAUCE_USERNAME=fullstack_ci - SAUCE_ACCESS_KEY=1a527ca6-4aa5-4618-86ce-0278bf158cbf -addons: - sauce_connect: true before_install: + - ./scripts/sauce_connect_setup.sh - gem update --system - gem install sass --version "=3.3.7" - npm install -g bower grunt-cli -services: mongodb +services: mongodb \ No newline at end of file diff --git a/scripts/sauce_connect_setup.sh b/scripts/sauce_connect_setup.sh new file mode 100755 index 000000000..06b6e2092 --- /dev/null +++ b/scripts/sauce_connect_setup.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +# Setup and start Sauce Connect for your TravisCI build +# This script requires your .travis.yml to include the following two private env variables: +# SAUCE_USERNAME +# SAUCE_ACCESS_KEY +# Follow the steps at https://saucelabs.com/opensource/travis to set that up. +# https://gist.githubusercontent.com/santiycr/4683e262467c0a84d857/raw/1254ace59257e341ab200cbc8946e626756f079f/sauce-connect.sh + +if [ -z "${SAUCE_USERNAME}" ] || [ -z "${SAUCE_ACCESS_KEY}" ]; then + echo "This script can't run without your Sauce credentials" + echo "Please set SAUCE_USERNAME and SAUCE_ACCESS_KEY env variables" + echo "export SAUCE_USERNAME=ur-username" + echo "export SAUCE_ACCESS_KEY=ur-access-key" + exit 1 +fi + +SAUCE_TMP_DIR="$(mktemp -d -t sc.XXXX)" +echo "Using temp dir $SAUCE_TMP_DIR" +pushd $SAUCE_TMP_DIR + +SAUCE_CONNECT_PLATFORM=$(uname | sed -e 's/Darwin/osx/' -e 's/Linux/linux/') +case "${SAUCE_CONNECT_PLATFORM}" in + linux) + SC_DISTRIBUTION_FMT=tar.gz;; + *) + SC_DISTRIBUTION_FMT=zip;; +esac +SC_DISTRIBUTION=sc-latest-${SAUCE_CONNECT_PLATFORM}.${SC_DISTRIBUTION_FMT} +SC_READYFILE=sauce-connect-ready-$RANDOM +SC_LOGFILE=$HOME/sauce-connect.log +if [ ! -z "${TRAVIS_JOB_NUMBER}" ]; then + SC_TUNNEL_ID="-i ${TRAVIS_JOB_NUMBER}" +fi +echo "Downloading Sauce Connect" +wget https://saucelabs.com/downloads/${SC_DISTRIBUTION} +SC_DIR=$(tar -ztf ${SC_DISTRIBUTION} | head -n1) + +echo "Extracting Sauce Connect" +case "${SC_DISTRIBUTION_FMT}" in + tar.gz) + tar zxf $SC_DISTRIBUTION;; + zip) + unzip $SC_DISTRIBUTION;; +esac + +echo "Starting Sauce Connect" +${SC_DIR}/bin/sc \ + ${SC_TUNNEL_ID} \ + -f ${SC_READYFILE} \ + -l ${SC_LOGFILE} & + +echo "Waiting for Sauce Connect readyfile" +while [ ! -f ${SC_READYFILE} ]; do + sleep .5 +done + +unset SAUCE_CONNECT_PLATFORM SAUCE_TMP_DIR SC_DIR SC_DISTRIBUTION SC_READYFILE SC_LOGFILE SC_TUNNEL_ID + +popd \ No newline at end of file From 8a1a245f212c24604fc78ba8442a87af31586537 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sun, 21 Sep 2014 22:11:35 -0600 Subject: [PATCH 0044/1357] feat(app): add grunt jscs task for maintaining consistent code style --- app/templates/.jscs.json | 3 +++ app/templates/Gruntfile.js | 15 +++++++++++++++ app/templates/_package.json | 1 + 3 files changed, 19 insertions(+) create mode 100644 app/templates/.jscs.json diff --git a/app/templates/.jscs.json b/app/templates/.jscs.json new file mode 100644 index 000000000..dc46a2f34 --- /dev/null +++ b/app/templates/.jscs.json @@ -0,0 +1,3 @@ +{ + "preset": "google" +} \ No newline at end of file diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 6cd422daa..3e2da06c8 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -192,6 +192,21 @@ module.exports = function (grunt) { } }, + jscs: { + options: { + config: ".jscs.json" + }, + main: { + files: { + src: [ + '<%%= yeoman.client %>/app/**/*.js', + '<%%= yeoman.client %>/app/**/*.js', + 'server/**/*.js' + ] + } + } + }, + // Empties folders to start fresh clean: { dist: { diff --git a/app/templates/_package.json b/app/templates/_package.json index 08784aa6c..3775d0d90 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -48,6 +48,7 @@ "grunt-contrib-jade": "^0.11.0",<% } %><% if(filters.less) { %> "grunt-contrib-less": "^0.11.4",<% } %> "grunt-google-cdn": "~0.4.0", + "grunt-jscs": "~0.7.1", "grunt-newer": "~0.7.0", "grunt-ng-annotate": "^0.2.3", "grunt-rev": "~0.1.0", From 18c4c31d3c8c35690810966e0e27b22f74c26a13 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sat, 27 Sep 2014 01:41:39 -0600 Subject: [PATCH 0045/1357] style(app): update style to match jscs style guide --- app/templates/.jscs.json | 11 ++- app/templates/Gruntfile.js | 86 +++++++++---------- app/templates/_.gitignore | 2 +- app/templates/_bower.json | 10 +-- app/templates/_package.json | 30 +++---- .../app/account(auth)/account(coffee).coffee | 4 +- .../client/app/account(auth)/account(js).js | 4 +- .../app/account(auth)/login/login(html).html | 10 +-- .../app/account(auth)/login/login(jade).jade | 10 +-- .../app/account(auth)/login/login(less).less | 2 +- .../app/account(auth)/login/login(sass).scss | 2 +- .../login/login.controller(coffee).coffee | 6 +- .../login/login.controller(js).js | 12 +-- .../settings/settings.controller(js).js | 24 +++--- .../account(auth)/signup/signup(html).html | 10 +-- .../account(auth)/signup/signup(jade).jade | 10 +-- .../signup/signup.controller(coffee).coffee | 6 +- .../signup/signup.controller(js).js | 12 +-- .../app/admin(auth)/admin(coffee).coffee | 4 +- .../client/app/admin(auth)/admin(js).js | 6 +- .../app/admin(auth)/admin.controller(js).js | 2 +- app/templates/client/app/app(coffee).coffee | 22 ++--- app/templates/client/app/app(css).css | 4 +- app/templates/client/app/app(js).js | 26 +++--- app/templates/client/app/app(less).less | 6 +- app/templates/client/app/app(sass).scss | 6 +- app/templates/client/app/app(stylus).styl | 4 +- .../client/app/main/main(coffee).coffee | 4 +- app/templates/client/app/main/main(html).html | 4 +- app/templates/client/app/main/main(jade).jade | 4 +- app/templates/client/app/main/main(js).js | 6 +- .../app/main/main.controller(coffee).coffee | 8 +- .../client/app/main/main.controller(js).js | 12 +-- .../main/main.controller.spec(coffee).coffee | 10 +-- .../app/main/main.controller.spec(js).js | 20 ++--- .../components/navbar/navbar(html).html | 18 ++-- .../components/navbar/navbar(jade).jade | 22 ++--- .../navbar/navbar.controller(coffee).coffee | 6 +- .../navbar/navbar.controller(js).js | 6 +- app/templates/client/index.html | 4 +- .../e2e/components/navbar/navbar.po.js | 2 +- app/templates/karma.conf.js | 10 +-- app/templates/protractor.conf.js | 8 +- app/templates/server/api/thing/index.js | 2 +- app/templates/server/api/thing/index.spec.js | 30 +++++-- .../server/api/thing/thing.controller.js | 73 ++++++++-------- .../server/api/thing/thing.integration.js | 28 ++++-- .../server/api/thing/thing.model(mongoose).js | 4 +- .../api/thing/thing.socket(socketio).js | 4 +- .../server/api/user(auth)/index.spec.js | 24 ++++-- .../server/api/user(auth)/user.controller.js | 32 ++++--- .../server/api/user(auth)/user.integration.js | 4 +- .../server/api/user(auth)/user.model.js | 72 ++++++++++------ .../server/api/user(auth)/user.model.spec.js | 4 +- app/templates/server/app.js | 4 +- .../server/auth(auth)/auth.service.js | 21 +++-- .../facebook(facebookAuth)/index.js | 2 +- .../facebook(facebookAuth)/passport.js | 63 +++++++------- .../auth(auth)/google(googleAuth)/index.js | 2 +- .../auth(auth)/google(googleAuth)/passport.js | 55 ++++++------ app/templates/server/auth(auth)/index.js | 2 +- .../server/auth(auth)/local/index.js | 16 ++-- .../server/auth(auth)/local/passport.js | 48 ++++++----- .../auth(auth)/twitter(twitterAuth)/index.js | 2 +- .../twitter(twitterAuth)/passport.js | 11 +-- .../server/components/errors/index.js | 6 +- app/templates/server/config/_local.env.js | 2 +- .../server/config/environment/index.js | 10 +-- .../server/config/environment/production.js | 5 +- .../server/config/environment/test.js | 2 +- app/templates/server/config/express.js | 6 +- app/templates/server/config/seed(mongoose).js | 40 +++++---- .../server/config/socketio(socketio).js | 17 ++-- app/templates/server/routes.js | 6 +- endpoint/templates/index.js | 2 +- endpoint/templates/index.spec.js | 24 ++++-- endpoint/templates/name.controller.js | 36 ++++---- endpoint/templates/name.integration.js | 24 ++++-- endpoint/templates/name.model(mongoose).js | 4 +- endpoint/templates/name.socket(socketio).js | 6 +- test/test-file-creation.js | 29 +++++++ 81 files changed, 676 insertions(+), 521 deletions(-) diff --git a/app/templates/.jscs.json b/app/templates/.jscs.json index dc46a2f34..1c278d0c4 100644 --- a/app/templates/.jscs.json +++ b/app/templates/.jscs.json @@ -1,3 +1,12 @@ { - "preset": "google" + "preset": "google", + "maximumLineLength": { + "value": 100, + "allowComments": true, + "allowRegex": true + }, + "requireCamelCaseOrUpperCaseIdentifiers": "ignoreProperties", + "requireSpacesInsideObjectBrackets": "all", + "disallowSpacesInsideObjectBrackets": "nested", + "requireSpacesInConditionalExpression": true } \ No newline at end of file diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 3e2da06c8..224e84c66 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -80,7 +80,7 @@ module.exports = function (grunt) { '<%%= yeoman.client %>/{app,components}/**/*.mock.js' ], tasks: ['newer:jshint:all', 'karma'] - },<% if(filters.stylus) { %> + },<% if (filters.stylus) { %> injectStylus: { files: [ '<%%= yeoman.client %>/{app,components}/**/*.styl'], @@ -90,7 +90,7 @@ module.exports = function (grunt) { files: [ '<%%= yeoman.client %>/{app,components}/**/*.styl'], tasks: ['stylus', 'autoprefixer'] - },<% } %><% if(filters.sass) { %> + },<% } %><% if (filters.sass) { %> injectSass: { files: [ '<%%= yeoman.client %>/{app,components}/**/*.{scss,sass}'], @@ -100,7 +100,7 @@ module.exports = function (grunt) { files: [ '<%%= yeoman.client %>/{app,components}/**/*.{scss,sass}'], tasks: ['sass', 'autoprefixer'] - },<% } %><% if(filters.less) { %> + },<% } %><% if (filters.less) { %> injectLess: { files: [ '<%%= yeoman.client %>/{app,components}/**/*.less'], @@ -110,13 +110,13 @@ module.exports = function (grunt) { files: [ '<%%= yeoman.client %>/{app,components}/**/*.less'], tasks: ['less', 'autoprefixer'] - },<% } %><% if(filters.jade) { %> + },<% } %><% if (filters.jade) { %> jade: { files: [ '<%%= yeoman.client %>/{app,components}/*', '<%%= yeoman.client %>/{app,components}/**/*.jade'], tasks: ['jade'] - },<% } %><% if(filters.coffee) { %> + },<% } %><% if (filters.coffee) { %> coffee: { files: [ '<%%= yeoman.client %>/{app,components}/**/*.{coffee,litcoffee,coffee.md}', @@ -458,18 +458,18 @@ module.exports = function (grunt) { // Run some tasks in parallel to speed up the build process concurrent: { - server: [<% if(filters.coffee) { %> - 'coffee',<% } %><% if(filters.jade) { %> - 'jade',<% } %><% if(filters.stylus) { %> - 'stylus',<% } %><% if(filters.sass) { %> - 'sass',<% } %><% if(filters.less) { %> + server: [<% if (filters.coffee) { %> + 'coffee',<% } %><% if (filters.jade) { %> + 'jade',<% } %><% if (filters.stylus) { %> + 'stylus',<% } %><% if (filters.sass) { %> + 'sass',<% } %><% if (filters.less) { %> 'less',<% } %> ], - test: [<% if(filters.coffee) { %> - 'coffee',<% } %><% if(filters.jade) { %> - 'jade',<% } %><% if(filters.stylus) { %> - 'stylus',<% } %><% if(filters.sass) { %> - 'sass',<% } %><% if(filters.less) { %> + test: [<% if (filters.coffee) { %> + 'coffee',<% } %><% if (filters.jade) { %> + 'jade',<% } %><% if (filters.stylus) { %> + 'stylus',<% } %><% if (filters.sass) { %> + 'sass',<% } %><% if (filters.less) { %> 'less',<% } %> ], debug: { @@ -481,11 +481,11 @@ module.exports = function (grunt) { logConcurrentOutput: true } }, - dist: [<% if(filters.coffee) { %> - 'coffee',<% } %><% if(filters.jade) { %> - 'jade',<% } %><% if(filters.stylus) { %> - 'stylus',<% } %><% if(filters.sass) { %> - 'sass',<% } %><% if(filters.less) { %> + dist: [<% if (filters.coffee) { %> + 'coffee',<% } %><% if (filters.jade) { %> + 'jade',<% } %><% if (filters.stylus) { %> + 'stylus',<% } %><% if (filters.sass) { %> + 'sass',<% } %><% if (filters.less) { %> 'less',<% } %> 'imagemin', 'svgmin' @@ -579,7 +579,7 @@ module.exports = function (grunt) { NODE_ENV: 'production' }, all: localConfig - },<% if(filters.jade) { %> + },<% if (filters.jade) { %> // Compiles Jade to html jade: { @@ -599,7 +599,7 @@ module.exports = function (grunt) { ext: '.html' }] } - },<% } %><% if(filters.coffee) { %> + },<% } %><% if (filters.coffee) { %> // Compiles CoffeeScript to JavaScript coffee: { @@ -619,7 +619,7 @@ module.exports = function (grunt) { ext: '.js' }] } - },<% } %><% if(filters.stylus) { %> + },<% } %><% if (filters.stylus) { %> // Compiles Stylus to CSS stylus: { @@ -636,7 +636,7 @@ module.exports = function (grunt) { '.tmp/app/app.css' : '<%%= yeoman.client %>/app/app.styl' } } - },<% } %><% if(filters.sass) { %> + },<% } %><% if (filters.sass) { %> // Compiles Sass to CSS sass: { @@ -653,7 +653,7 @@ module.exports = function (grunt) { '.tmp/app/app.css' : '<%%= yeoman.client %>/app/app.scss' } } - },<% } %><% if(filters.less) { %> + },<% } %><% if (filters.less) { %> // Compiles Less to CSS less: { @@ -694,7 +694,7 @@ module.exports = function (grunt) { '!{.tmp,<%%= yeoman.client %>}/{app,components}/**/*.mock.js'] ] } - },<% if(filters.stylus) { %> + },<% if (filters.stylus) { %> // Inject component styl into app.styl stylus: { @@ -713,7 +713,7 @@ module.exports = function (grunt) { '!<%%= yeoman.client %>/app/app.styl' ] } - },<% } %><% if(filters.sass) { %> + },<% } %><% if (filters.sass) { %> // Inject component scss into app.scss sass: { @@ -732,7 +732,7 @@ module.exports = function (grunt) { '!<%%= yeoman.client %>/app/app.{scss,sass}' ] } - },<% } %><% if(filters.less) { %> + },<% } %><% if (filters.less) { %> // Inject component less into app.less less: { @@ -797,9 +797,9 @@ module.exports = function (grunt) { if (target === 'debug') { return grunt.task.run([ 'clean:server', - 'env:all',<% if(filters.stylus) { %> - 'injector:stylus', <% } %><% if(filters.less) { %> - 'injector:less', <% } %><% if(filters.sass) { %> + 'env:all',<% if (filters.stylus) { %> + 'injector:stylus', <% } %><% if (filters.less) { %> + 'injector:less', <% } %><% if (filters.sass) { %> 'injector:sass', <% } %> 'concurrent:server', 'injector', @@ -811,9 +811,9 @@ module.exports = function (grunt) { grunt.task.run([ 'clean:server', - 'env:all',<% if(filters.stylus) { %> - 'injector:stylus', <% } %><% if(filters.less) { %> - 'injector:less', <% } %><% if(filters.sass) { %> + 'env:all',<% if (filters.stylus) { %> + 'injector:stylus', <% } %><% if (filters.less) { %> + 'injector:less', <% } %><% if (filters.sass) { %> 'injector:sass', <% } %> 'concurrent:server', 'injector', @@ -844,9 +844,9 @@ module.exports = function (grunt) { else if (target === 'client') { return grunt.task.run([ 'clean:server', - 'env:all',<% if(filters.stylus) { %> - 'injector:stylus', <% } %><% if(filters.less) { %> - 'injector:less', <% } %><% if(filters.sass) { %> + 'env:all',<% if (filters.stylus) { %> + 'injector:stylus', <% } %><% if (filters.less) { %> + 'injector:less', <% } %><% if (filters.sass) { %> 'injector:sass', <% } %> 'concurrent:test', 'injector', @@ -859,9 +859,9 @@ module.exports = function (grunt) { return grunt.task.run([ 'clean:server', 'env:all', - 'env:test',<% if(filters.stylus) { %> - 'injector:stylus', <% } %><% if(filters.less) { %> - 'injector:less', <% } %><% if(filters.sass) { %> + 'env:test',<% if (filters.stylus) { %> + 'injector:stylus', <% } %><% if (filters.less) { %> + 'injector:less', <% } %><% if (filters.sass) { %> 'injector:sass', <% } %> 'concurrent:test', 'injector', @@ -914,9 +914,9 @@ module.exports = function (grunt) { }); grunt.registerTask('build', [ - 'clean:dist',<% if(filters.stylus) { %> - 'injector:stylus', <% } %><% if(filters.less) { %> - 'injector:less', <% } %><% if(filters.sass) { %> + 'clean:dist',<% if (filters.stylus) { %> + 'injector:stylus', <% } %><% if (filters.less) { %> + 'injector:less', <% } %><% if (filters.sass) { %> 'injector:sass', <% } %> 'concurrent:dist', 'injector', diff --git a/app/templates/_.gitignore b/app/templates/_.gitignore index 6b4afbb0f..6d88c2a0a 100644 --- a/app/templates/_.gitignore +++ b/app/templates/_.gitignore @@ -1,6 +1,6 @@ node_modules public -.tmp<% if(filters.sass) { %> +.tmp<% if (filters.sass) { %> .sass-cache<% } %> .idea client/bower_components diff --git a/app/templates/_bower.json b/app/templates/_bower.json index 1681050a2..aaf0f8b81 100644 --- a/app/templates/_bower.json +++ b/app/templates/_bower.json @@ -5,17 +5,17 @@ "angular": ">=1.2.*", "json3": "~3.3.1", "es5-shim": "~3.0.1", - "jquery": "~1.11.0",<% if(filters.bootstrap) { %><% if (filters.sass) { %> + "jquery": "~1.11.0",<% if (filters.bootstrap) { %><% if (filters.sass) { %> "bootstrap-sass-official": "~3.1.1",<% } %> "bootstrap": "~3.1.1",<% } %> "angular-resource": ">=1.2.*", "angular-cookies": ">=1.2.*", - "angular-sanitize": ">=1.2.*",<% if(filters.ngroute) { %> - "angular-route": ">=1.2.*",<% } %><% if(filters.uibootstrap) { %> + "angular-sanitize": ">=1.2.*",<% if (filters.ngroute) { %> + "angular-route": ">=1.2.*",<% } %><% if (filters.uibootstrap) { %> "angular-bootstrap": "~0.11.0",<% } %> "font-awesome": ">=4.1.0", - "lodash": "~2.4.1"<% if(filters.socketio) { %>, - "angular-socket-io": "~0.6.0"<% } %><% if(filters.uirouter) { %>, + "lodash": "~2.4.1"<% if (filters.socketio) { %>, + "angular-socket-io": "~0.6.0"<% } %><% if (filters.uirouter) { %>, "angular-ui-router": "~0.2.10"<% } %> }, "devDependencies": { diff --git a/app/templates/_package.json b/app/templates/_package.json index 3775d0d90..8963ff15d 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -12,20 +12,20 @@ "express-session": "~1.0.2", "errorhandler": "~1.0.0", "compression": "~1.0.1", - "lodash": "~2.4.1",<% if(filters.jade) { %> - "jade": "~1.2.0",<% } %><% if(filters.html) { %> - "ejs": "~0.8.4",<% } %><% if(filters.mongoose) { %> + "lodash": "~2.4.1",<% if (filters.jade) { %> + "jade": "~1.2.0",<% } %><% if (filters.html) { %> + "ejs": "~0.8.4",<% } %><% if (filters.mongoose) { %> "mongoose": "~3.8.8", - "mongoose-bird": "~0.0.1",<% } %><% if(filters.auth) { %> + "mongoose-bird": "~0.0.1",<% } %><% if (filters.auth) { %> "jsonwebtoken": "^0.3.0", "express-jwt": "^0.1.3", "passport": "~0.2.0", - "passport-local": "~0.1.6",<% } %><% if(filters.facebookAuth) { %> - "passport-facebook": "latest",<% } %><% if(filters.twitterAuth) { %> - "passport-twitter": "latest",<% } %><% if(filters.googleAuth) { %> + "passport-local": "~0.1.6",<% } %><% if (filters.facebookAuth) { %> + "passport-facebook": "latest",<% } %><% if (filters.twitterAuth) { %> + "passport-twitter": "latest",<% } %><% if (filters.googleAuth) { %> "passport-google-oauth": "latest",<% } %> "composable-middleware": "^0.3.0", - "connect-mongo": "^0.4.1"<% if(filters.socketio) { %>, + "connect-mongo": "^0.4.1"<% if (filters.socketio) { %>, "socket.io": "^1.0.6", "socket.io-client": "^1.0.6", "socketio-jwt": "^2.0.2"<% } %> @@ -43,9 +43,9 @@ "grunt-contrib-imagemin": "~0.7.1", "grunt-contrib-jshint": "~0.10.0", "grunt-contrib-uglify": "~0.4.0", - "grunt-contrib-watch": "~0.6.1",<% if(filters.coffee) { %> - "grunt-contrib-coffee": "^0.10.1",<% } %><% if(filters.jade) { %> - "grunt-contrib-jade": "^0.11.0",<% } %><% if(filters.less) { %> + "grunt-contrib-watch": "~0.6.1",<% if (filters.coffee) { %> + "grunt-contrib-coffee": "^0.10.1",<% } %><% if (filters.jade) { %> + "grunt-contrib-jade": "^0.11.0",<% } %><% if (filters.less) { %> "grunt-contrib-less": "^0.11.4",<% } %> "grunt-google-cdn": "~0.4.0", "grunt-jscs": "~0.7.1", @@ -62,8 +62,8 @@ "grunt-protractor-runner": "^1.1.0", "grunt-asset-injector": "^0.1.0", "grunt-karma": "~0.8.2", - "grunt-build-control": "DaftMonk/grunt-build-control",<% if(filters.sass) { %> - "grunt-contrib-sass": "^0.7.3",<% } %><% if(filters.stylus) { %> + "grunt-build-control": "DaftMonk/grunt-build-control",<% if (filters.sass) { %> + "grunt-contrib-sass": "^0.7.3",<% } %><% if (filters.stylus) { %> "grunt-contrib-stylus": "latest",<% } %> "jit-grunt": "^0.5.0", "time-grunt": "~0.3.1", @@ -76,9 +76,9 @@ "grunt-mocha-istanbul": "^2.0.0", "chai-as-promised": "^4.1.1", "chai-things": "^0.2.0", - "sinon-chai": "^2.5.0",<% if(filters.mocha) { %> + "sinon-chai": "^2.5.0",<% if (filters.mocha) { %> "karma-mocha": "^0.1.9", - "karma-chai-plugins": "^0.2.3",<% } if(filters.jasmine) { %> + "karma-chai-plugins": "^0.2.3",<% } if (filters.jasmine) { %> "karma-jasmine": "~0.1.5",<% } %> "karma-ng-scenario": "~0.1.0", "karma-firefox-launcher": "~0.1.3", diff --git a/app/templates/client/app/account(auth)/account(coffee).coffee b/app/templates/client/app/account(auth)/account(coffee).coffee index 088fb6840..c794d7f04 100644 --- a/app/templates/client/app/account(auth)/account(coffee).coffee +++ b/app/templates/client/app/account(auth)/account(coffee).coffee @@ -1,7 +1,7 @@ 'use strict' angular.module '<%= scriptAppName %>' -<% if(filters.ngroute) { %>.config ($routeProvider) -> +<% if (filters.ngroute) { %>.config ($routeProvider) -> $routeProvider .when '/login', templateUrl: 'app/account/login/login.html' @@ -27,7 +27,7 @@ angular.module '<%= scriptAppName %>' .run ($rootScope) -> $rootScope.$on '$routeChangeStart', (event, next, current) -> next.referrer = current.originalPath if next.name is "logout" and current and current.originalPath and not current.authenticate -<% } %><% if(filters.uirouter) { %>.config ($stateProvider) -> +<% } %><% if (filters.uirouter) { %>.config ($stateProvider) -> $stateProvider .state 'login', url: '/login' diff --git a/app/templates/client/app/account(auth)/account(js).js b/app/templates/client/app/account(auth)/account(js).js index 8c005c952..d60fd72fe 100644 --- a/app/templates/client/app/account(auth)/account(js).js +++ b/app/templates/client/app/account(auth)/account(js).js @@ -1,7 +1,7 @@ 'use strict'; angular.module('<%= scriptAppName %>') - <% if(filters.ngroute) { %>.config(function ($routeProvider) { + <% if (filters.ngroute) { %>.config(function($routeProvider) { $routeProvider .when('/login', { templateUrl: 'app/account/login/login.html', @@ -35,7 +35,7 @@ angular.module('<%= scriptAppName %>') next.referrer = current.originalPath; } }); - });<% } %><% if(filters.uirouter) { %>.config(function ($stateProvider) { + });<% } %><% if (filters.uirouter) { %>.config(function($stateProvider) { $stateProvider .state('login', { url: '/login', diff --git a/app/templates/client/app/account(auth)/login/login(html).html b/app/templates/client/app/account(auth)/login/login(html).html index 49a81b55d..f02de2616 100644 --- a/app/templates/client/app/account(auth)/login/login(html).html +++ b/app/templates/client/app/account(auth)/login/login(html).html @@ -37,19 +37,19 @@

Login

- ui-sref="signup"<% } else { %>href="http://github.com/signup"<% } %>> + ui-sref="signup"<% } else { %>href="http://github.com/signup"<% } %>> Register -<% if(filters.oauth) {%> +<% if (filters.oauth) {%>
-
<% if(filters.facebookAuth) {%> +
<% if (filters.facebookAuth) {%> Connect with Facebook - <% } %><% if(filters.googleAuth) {%> + <% } %><% if (filters.googleAuth) {%> Connect with Google+ - <% } %><% if(filters.twitterAuth) {%> + <% } %><% if (filters.twitterAuth) {%> Connect with Twitter <% } %> diff --git a/app/templates/client/app/account(auth)/login/login(jade).jade b/app/templates/client/app/account(auth)/login/login(jade).jade index 5f608a67b..fd95e6ff1 100644 --- a/app/templates/client/app/account(auth)/login/login(jade).jade +++ b/app/templates/client/app/account(auth)/login/login(jade).jade @@ -34,20 +34,20 @@ div(ng-include='"components/navbar/navbar.html"') button.btn.btn-inverse.btn-lg.btn-login(type='submit') | Login = ' ' - a.btn.btn-default.btn-lg.btn-register(<% if(filters.uirouter) { %>ui-sref='signup'<% } else { %>href='http://github.com/signup'<% } %>) + a.btn.btn-default.btn-lg.btn-register(<% if (filters.uirouter) { %>ui-sref='signup'<% } else { %>href='http://github.com/signup'<% } %>) | Register -<% if(filters.oauth) {%> +<% if (filters.oauth) {%> hr - div<% if(filters.facebookAuth) {%> + div<% if (filters.facebookAuth) {%> a.btn.btn-facebook(href='', ng-click='loginOauth("facebook")') i.fa.fa-facebook | Connect with Facebook - = ' '<% } %><% if(filters.googleAuth) {%> + = ' '<% } %><% if (filters.googleAuth) {%> a.btn.btn-google-plus(href='', ng-click='loginOauth("google")') i.fa.fa-google-plus | Connect with Google+ - = ' '<% } %><% if(filters.twitterAuth) {%> + = ' '<% } %><% if (filters.twitterAuth) {%> a.btn.btn-twitter(href='', ng-click='loginOauth("twitter")') i.fa.fa-twitter | Connect with Twitter<% } %><% } %> diff --git a/app/templates/client/app/account(auth)/login/login(less).less b/app/templates/client/app/account(auth)/login/login(less).less index bd01a056e..6eaecd90c 100644 --- a/app/templates/client/app/account(auth)/login/login(less).less +++ b/app/templates/client/app/account(auth)/login/login(less).less @@ -1,4 +1,4 @@ -<% if(filters.bootstrap) { %>// Colors +<% if (filters.bootstrap) { %>// Colors // -------------------------------------------------- @btnText: #fff; diff --git a/app/templates/client/app/account(auth)/login/login(sass).scss b/app/templates/client/app/account(auth)/login/login(sass).scss index eb214a8ca..5b6956124 100644 --- a/app/templates/client/app/account(auth)/login/login(sass).scss +++ b/app/templates/client/app/account(auth)/login/login(sass).scss @@ -1,4 +1,4 @@ -<% if(filters.bootstrap) { %>// Colors +<% if (filters.bootstrap) { %>// Colors // -------------------------------------------------- $btnText: #fff; diff --git a/app/templates/client/app/account(auth)/login/login.controller(coffee).coffee b/app/templates/client/app/account(auth)/login/login.controller(coffee).coffee index 036191f93..7bcb69969 100644 --- a/app/templates/client/app/account(auth)/login/login.controller(coffee).coffee +++ b/app/templates/client/app/account(auth)/login/login.controller(coffee).coffee @@ -1,7 +1,7 @@ 'use strict' angular.module '<%= scriptAppName %>' -.controller 'LoginCtrl', ($scope, Auth<% if(filters.ngroute) { %>, $location<% } %><% if(filters.uirouter) { %>, $state<% } %><% if(filters.oauth) {%>, $window<% } %>) -> +.controller 'LoginCtrl', ($scope, Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %><% if (filters.oauth) {%>, $window<% } %>) -> $scope.user = {} $scope.errors = {} $scope.login = (form) -> @@ -14,10 +14,10 @@ angular.module '<%= scriptAppName %>' password: $scope.user.password .then -> - <% if(filters.ngroute) { %>$location.path '/'<% } %><% if(filters.uirouter) { %>$state.go 'main'<% } %> + <% if (filters.ngroute) { %>$location.path '/'<% } %><% if (filters.uirouter) { %>$state.go 'main'<% } %> .catch (err) -> $scope.errors.other = err.message -<% if(filters.oauth) {%> +<% if (filters.oauth) {%> $scope.loginOauth = (provider) -> $window.location.href = '/auth/' + provider<% } %> diff --git a/app/templates/client/app/account(auth)/login/login.controller(js).js b/app/templates/client/app/account(auth)/login/login.controller(js).js index e2c5dcaa4..2417e62f4 100644 --- a/app/templates/client/app/account(auth)/login/login.controller(js).js +++ b/app/templates/client/app/account(auth)/login/login.controller(js).js @@ -1,28 +1,28 @@ 'use strict'; angular.module('<%= scriptAppName %>') - .controller('LoginCtrl', function ($scope, Auth<% if(filters.ngroute) { %>, $location<% } %><% if(filters.uirouter) { %>, $state<% } %><% if (filters.oauth) { %>, $window<% } %>) { + .controller('LoginCtrl', function($scope, Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %><% if (filters.oauth) { %>, $window<% } %>) { $scope.user = {}; $scope.errors = {}; $scope.login = function(form) { $scope.submitted = true; - if(form.$valid) { + if (form.$valid) { Auth.login({ email: $scope.user.email, password: $scope.user.password }) - .then( function() { + .then(function() { // Logged in, redirect to home - <% if(filters.ngroute) { %>$location.path('/');<% } %><% if(filters.uirouter) { %>$state.go('main');<% } %> + <% if (filters.ngroute) { %>$location.path('/');<% } %><% if (filters.uirouter) { %>$state.go('main');<% } %> }) - .catch( function(err) { + .catch(function(err) { $scope.errors.other = err.message; }); } }; -<% if(filters.oauth) {%> +<% if (filters.oauth) {%> $scope.loginOauth = function(provider) { $window.location.href = '/auth/' + provider; };<% } %> diff --git a/app/templates/client/app/account(auth)/settings/settings.controller(js).js b/app/templates/client/app/account(auth)/settings/settings.controller(js).js index 829bd8248..eeb1219cf 100644 --- a/app/templates/client/app/account(auth)/settings/settings.controller(js).js +++ b/app/templates/client/app/account(auth)/settings/settings.controller(js).js @@ -1,21 +1,21 @@ 'use strict'; angular.module('<%= scriptAppName %>') - .controller('SettingsCtrl', function ($scope, User, Auth) { + .controller('SettingsCtrl', function($scope, User, Auth) { $scope.errors = {}; $scope.changePassword = function(form) { $scope.submitted = true; - if(form.$valid) { - Auth.changePassword( $scope.user.oldPassword, $scope.user.newPassword ) - .then( function() { - $scope.message = 'Password successfully changed.'; - }) - .catch( function() { - form.password.$setValidity('mongoose', false); - $scope.errors.other = 'Incorrect password'; - $scope.message = ''; - }); + if (form.$valid) { + Auth.changePassword($scope.user.oldPassword, $scope.user.newPassword) + .then(function() { + $scope.message = 'Password successfully changed.'; + }) + .catch(function() { + form.password.$setValidity('mongoose', false); + $scope.errors.other = 'Incorrect password'; + $scope.message = ''; + }); } - }; + }; }); diff --git a/app/templates/client/app/account(auth)/signup/signup(html).html b/app/templates/client/app/account(auth)/signup/signup(html).html index ee4f17fa4..fc55d3790 100644 --- a/app/templates/client/app/account(auth)/signup/signup(html).html +++ b/app/templates/client/app/account(auth)/signup/signup(html).html @@ -58,19 +58,19 @@

Sign up

-
-<% if(filters.oauth) {%> +<% if (filters.oauth) {%>
-
<% if(filters.facebookAuth) {%> +
<% if (filters.facebookAuth) {%> Connect with Facebook - <% } %><% if(filters.googleAuth) {%> + <% } %><% if (filters.googleAuth) {%> Connect with Google+ - <% } %><% if(filters.twitterAuth) {%> + <% } %><% if (filters.twitterAuth) {%> Connect with Twitter <% } %> diff --git a/app/templates/client/app/account(auth)/signup/signup(jade).jade b/app/templates/client/app/account(auth)/signup/signup(jade).jade index 8c5710686..081657a6d 100644 --- a/app/templates/client/app/account(auth)/signup/signup(jade).jade +++ b/app/templates/client/app/account(auth)/signup/signup(jade).jade @@ -36,21 +36,21 @@ div(ng-include='"components/navbar/navbar.html"') button.btn.btn-inverse.btn-lg.btn-register(type='submit') | Sign up = ' ' - a.btn.btn-default.btn-lg.btn-login(<% if(filters.uirouter) { %>ui-sref='login'<% } else { %>href='http://github.com/login'<% } %>) + a.btn.btn-default.btn-lg.btn-login(<% if (filters.uirouter) { %>ui-sref='login'<% } else { %>href='http://github.com/login'<% } %>) | Login -<% if(filters.oauth) {%> +<% if (filters.oauth) {%> hr - div<% if(filters.facebookAuth) {%> + div<% if (filters.facebookAuth) {%> a.btn.btn-facebook(href='', ng-click='loginOauth("facebook")') i.fa.fa-facebook | Connect with Facebook - = ' '<% } %><% if(filters.googleAuth) {%> + = ' '<% } %><% if (filters.googleAuth) {%> a.btn.btn-google-plus(href='', ng-click='loginOauth("google")') i.fa.fa-google-plus | Connect with Google+ - = ' '<% } %><% if(filters.twitterAuth) {%> + = ' '<% } %><% if (filters.twitterAuth) {%> a.btn.btn-twitter(href='', ng-click='loginOauth("twitter")') i.fa.fa-twitter | Connect with Twitter<% } %><% } %> diff --git a/app/templates/client/app/account(auth)/signup/signup.controller(coffee).coffee b/app/templates/client/app/account(auth)/signup/signup.controller(coffee).coffee index ac240faa8..3d96f3bf5 100644 --- a/app/templates/client/app/account(auth)/signup/signup.controller(coffee).coffee +++ b/app/templates/client/app/account(auth)/signup/signup.controller(coffee).coffee @@ -1,7 +1,7 @@ 'use strict' angular.module '<%= scriptAppName %>' -.controller 'SignupCtrl', ($scope, Auth<% if(filters.ngroute) { %>, $location<% } %><% if(filters.uirouter) { %>, $state<% } %><% if(filters.oauth) {%>, $window<% } %>) -> +.controller 'SignupCtrl', ($scope, Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %><% if (filters.oauth) {%>, $window<% } %>) -> $scope.user = {} $scope.errors = {} $scope.register = (form) -> @@ -15,7 +15,7 @@ angular.module '<%= scriptAppName %>' password: $scope.user.password .then -> - <% if(filters.ngroute) { %>$location.path '/'<% } %><% if(filters.uirouter) { %>$state.go 'main'<% } %> + <% if (filters.ngroute) { %>$location.path '/'<% } %><% if (filters.uirouter) { %>$state.go 'main'<% } %> .catch (err) -> err = err.data @@ -25,6 +25,6 @@ angular.module '<%= scriptAppName %>' angular.forEach err.errors, (error, field) -> form[field].$setValidity 'mongoose', false $scope.errors[field] = error.message -<% if(filters.oauth) {%> +<% if (filters.oauth) {%> $scope.loginOauth = (provider) -> $window.location.href = '/auth/' + provider<% } %> diff --git a/app/templates/client/app/account(auth)/signup/signup.controller(js).js b/app/templates/client/app/account(auth)/signup/signup.controller(js).js index 10685079d..7e93a6949 100644 --- a/app/templates/client/app/account(auth)/signup/signup.controller(js).js +++ b/app/templates/client/app/account(auth)/signup/signup.controller(js).js @@ -1,24 +1,24 @@ 'use strict'; angular.module('<%= scriptAppName %>') - .controller('SignupCtrl', function ($scope, Auth<% if(filters.ngroute) { %>, $location<% } %><% if(filters.uirouter) { %>, $state<% } %><% if (filters.oauth) { %>, $window<% } %>) { + .controller('SignupCtrl', function($scope, Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %><% if (filters.oauth) { %>, $window<% } %>) { $scope.user = {}; $scope.errors = {}; $scope.register = function(form) { $scope.submitted = true; - if(form.$valid) { + if (form.$valid) { Auth.createUser({ name: $scope.user.name, email: $scope.user.email, password: $scope.user.password }) - .then( function() { + .then(function() { // Account created, redirect to home - <% if(filters.ngroute) { %>$location.path('/');<% } %><% if(filters.uirouter) { %>$state.go('main');<% } %> + <% if (filters.ngroute) { %>$location.path('/');<% } %><% if (filters.uirouter) { %>$state.go('main');<% } %> }) - .catch( function(err) { + .catch(function(err) { err = err.data; $scope.errors = {}; @@ -30,7 +30,7 @@ angular.module('<%= scriptAppName %>') }); } }; -<% if(filters.oauth) {%> +<% if (filters.oauth) {%> $scope.loginOauth = function(provider) { $window.location.href = '/auth/' + provider; };<% } %> diff --git a/app/templates/client/app/admin(auth)/admin(coffee).coffee b/app/templates/client/app/admin(auth)/admin(coffee).coffee index a0497445e..18bb9d4ad 100644 --- a/app/templates/client/app/admin(auth)/admin(coffee).coffee +++ b/app/templates/client/app/admin(auth)/admin(coffee).coffee @@ -1,12 +1,12 @@ 'use strict' angular.module '<%= scriptAppName %>' -<% if(filters.ngroute) { %>.config ($routeProvider) -> +<% if (filters.ngroute) { %>.config ($routeProvider) -> $routeProvider .when '/admin', templateUrl: 'app/admin/admin.html' controller: 'AdminCtrl' -<% } %><% if(filters.uirouter) { %>.config ($stateProvider) -> +<% } %><% if (filters.uirouter) { %>.config ($stateProvider) -> $stateProvider .state 'admin', url: '/admin' diff --git a/app/templates/client/app/admin(auth)/admin(js).js b/app/templates/client/app/admin(auth)/admin(js).js index 270e8a974..f37ba9fcc 100644 --- a/app/templates/client/app/admin(auth)/admin(js).js +++ b/app/templates/client/app/admin(auth)/admin(js).js @@ -1,17 +1,17 @@ 'use strict'; angular.module('<%= scriptAppName %>') - <% if(filters.ngroute) { %>.config(function ($routeProvider) { + <% if (filters.ngroute) { %>.config(function($routeProvider) { $routeProvider .when('/admin', { templateUrl: 'app/admin/admin.html', controller: 'AdminCtrl' }); - });<% } %><% if(filters.uirouter) { %>.config(function ($stateProvider) { + });<% } %><% if (filters.uirouter) { %>.config(function($stateProvider) { $stateProvider .state('admin', { url: '/admin', templateUrl: 'app/admin/admin.html', controller: 'AdminCtrl' }); - });<% } %> \ No newline at end of file + });<% } %> diff --git a/app/templates/client/app/admin(auth)/admin.controller(js).js b/app/templates/client/app/admin(auth)/admin.controller(js).js index dd6b09405..51a52b759 100644 --- a/app/templates/client/app/admin(auth)/admin.controller(js).js +++ b/app/templates/client/app/admin(auth)/admin.controller(js).js @@ -1,7 +1,7 @@ 'use strict'; angular.module('<%= scriptAppName %>') - .controller('AdminCtrl', function ($scope, $http, Auth, User) { + .controller('AdminCtrl', function($scope, $http, Auth, User) { // Use the User $resource to fetch all users $scope.users = User.query(); diff --git a/app/templates/client/app/app(coffee).coffee b/app/templates/client/app/app(coffee).coffee index cb6d0c5b1..25b572a75 100644 --- a/app/templates/client/app/app(coffee).coffee +++ b/app/templates/client/app/app(coffee).coffee @@ -1,22 +1,22 @@ 'use strict' angular.module '<%= scriptAppName %>', [<%= angularModules %>] -<% if(filters.ngroute) { %>.config ($routeProvider, $locationProvider<% if(filters.auth) { %>, $httpProvider<% } %>) -> +<% if (filters.ngroute) { %>.config ($routeProvider, $locationProvider<% if (filters.auth) { %>, $httpProvider<% } %>) -> $routeProvider .otherwise redirectTo: '/' - $locationProvider.html5Mode true<% if(filters.auth) { %> + $locationProvider.html5Mode true<% if (filters.auth) { %> $httpProvider.interceptors.push 'authInterceptor'<% } %> -<% } %><% if(filters.uirouter) { %>.config ($stateProvider, $urlRouterProvider, $locationProvider<% if(filters.auth) { %>, $httpProvider<% } %>) -> +<% } %><% if (filters.uirouter) { %>.config ($stateProvider, $urlRouterProvider, $locationProvider<% if (filters.auth) { %>, $httpProvider<% } %>) -> $urlRouterProvider .otherwise '/' - $locationProvider.html5Mode true<% if(filters.auth) { %> + $locationProvider.html5Mode true<% if (filters.auth) { %> $httpProvider.interceptors.push 'authInterceptor'<% } %> -<% } %><% if(filters.auth) { %> -.factory 'authInterceptor', ($rootScope, $q, $cookieStore<% if(filters.ngroute) { %>, $location<% } if(filters.uirouter) { %>, $injector<% } %>) -> - <% if(filters.uirouter) { %>state = null +<% } %><% if (filters.auth) { %> +.factory 'authInterceptor', ($rootScope, $q, $cookieStore<% if (filters.ngroute) { %>, $location<% } if (filters.uirouter) { %>, $injector<% } %>) -> + <% if (filters.uirouter) { %>state = null <% } %># Add authorization token to headers request: (config) -> config.headers = config.headers or {} @@ -26,15 +26,15 @@ angular.module '<%= scriptAppName %>', [<%= angularModules %>] # Intercept 401s and redirect you to login responseError: (response) -> if response.status is 401 - <% if(filters.ngroute) { %>$location.path '/login'<% } if(filters.uirouter) { %>(state || state = $injector.get '$state').go 'login'<% } %> + <% if (filters.ngroute) { %>$location.path '/login'<% } if (filters.uirouter) { %>(state || state = $injector.get '$state').go 'login'<% } %> # remove any stale tokens $cookieStore.remove 'token' $q.reject response -.run ($rootScope<% if(filters.ngroute) { %>, $location<% } %><% if(filters.uirouter) { %>, $state<% } %>, Auth) -> +.run ($rootScope<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %>, Auth) -> # Redirect to login if route requires auth and you're not logged in - $rootScope.$on <% if(filters.ngroute) { %>'$routeChangeStart'<% } %><% if(filters.uirouter) { %>'$stateChangeStart'<% } %>, (event, next) -> + $rootScope.$on <% if (filters.ngroute) { %>'$routeChangeStart'<% } %><% if (filters.uirouter) { %>'$stateChangeStart'<% } %>, (event, next) -> Auth.isLoggedIn (loggedIn) -> - <% if(filters.ngroute) { %>$location.path '/login'<% } %><% if(filters.uirouter) { %>$state.go 'login'<% } %> if next.authenticate and not loggedIn + <% if (filters.ngroute) { %>$location.path '/login'<% } %><% if (filters.uirouter) { %>$state.go 'login'<% } %> if next.authenticate and not loggedIn <% } %> diff --git a/app/templates/client/app/app(css).css b/app/templates/client/app/app(css).css index f1a61a918..b4e05273d 100644 --- a/app/templates/client/app/app(css).css +++ b/app/templates/client/app/app(css).css @@ -1,4 +1,4 @@ -<% if(filters.bootstrap) { %> +<% if (filters.bootstrap) { %> /** * Bootstrap Fonts */ @@ -37,7 +37,7 @@ color: #000; padding: 0.2em 0; } -<% if (!filters.bootstrap) { %> +<% if(!filters.bootstrap) { %> /* Responsive: Portrait tablets and up */ @media screen and (min-width: 768px) { .container { diff --git a/app/templates/client/app/app(js).js b/app/templates/client/app/app(js).js index 35b8ad327..b45db3c7f 100644 --- a/app/templates/client/app/app(js).js +++ b/app/templates/client/app/app(js).js @@ -1,27 +1,27 @@ 'use strict'; angular.module('<%= scriptAppName %>', [<%= angularModules %>]) - <% if(filters.ngroute) { %>.config(function ($routeProvider, $locationProvider<% if(filters.auth) { %>, $httpProvider<% } %>) { + <% if (filters.ngroute) { %>.config(function($routeProvider, $locationProvider<% if (filters.auth) { %>, $httpProvider<% } %>) { $routeProvider .otherwise({ redirectTo: '/' }); - $locationProvider.html5Mode(true);<% if(filters.auth) { %> + $locationProvider.html5Mode(true);<% if (filters.auth) { %> $httpProvider.interceptors.push('authInterceptor');<% } %> - })<% } if(filters.uirouter) { %>.config(function ($stateProvider, $urlRouterProvider, $locationProvider<% if(filters.auth) { %>, $httpProvider<% } %>) { + })<% } if (filters.uirouter) { %>.config(function($stateProvider, $urlRouterProvider, $locationProvider<% if (filters.auth) { %>, $httpProvider<% } %>) { $urlRouterProvider .otherwise('/'); - $locationProvider.html5Mode(true);<% if(filters.auth) { %> + $locationProvider.html5Mode(true);<% if (filters.auth) { %> $httpProvider.interceptors.push('authInterceptor');<% } %> - })<% } if(filters.auth) { %> + })<% } if (filters.auth) { %> - .factory('authInterceptor', function ($rootScope, $q, $cookieStore<% if(filters.ngroute) { %>, $location<% } if(filters.uirouter) { %>, $injector<% } %>) { - <% if(filters.uirouter) { %>var state; + .factory('authInterceptor', function($rootScope, $q, $cookieStore<% if (filters.ngroute) { %>, $location<% } if (filters.uirouter) { %>, $injector<% } %>) { + <% if (filters.uirouter) { %>var state; <% } %>return { // Add authorization token to headers - request: function (config) { + request: function(config) { config.headers = config.headers || {}; if ($cookieStore.get('token')) { config.headers.Authorization = 'Bearer ' + $cookieStore.get('token'); @@ -31,8 +31,8 @@ angular.module('<%= scriptAppName %>', [<%= angularModules %>]) // Intercept 401s and redirect you to login responseError: function(response) { - if(response.status === 401) { - <% if(filters.ngroute) { %>$location.path('/login');<% } if(filters.uirouter) { %>(state || (state = $injector.get('$state'))).go('login');<% } %> + if (response.status === 401) { + <% if (filters.ngroute) { %>$location.path('/login');<% } if (filters.uirouter) { %>(state || (state = $injector.get('$state'))).go('login');<% } %> // remove any stale tokens $cookieStore.remove('token'); return $q.reject(response); @@ -44,12 +44,12 @@ angular.module('<%= scriptAppName %>', [<%= angularModules %>]) }; }) - .run(function ($rootScope<% if(filters.ngroute) { %>, $location<% } if(filters.uirouter) { %>, $state<% } %>, Auth) { + .run(function($rootScope<% if (filters.ngroute) { %>, $location<% } if (filters.uirouter) { %>, $state<% } %>, Auth) { // Redirect to login if route requires auth and you're not logged in - $rootScope.$on(<% if(filters.ngroute) { %>'$routeChangeStart'<% } %><% if(filters.uirouter) { %>'$stateChangeStart'<% } %>, function (event, next) { + $rootScope.$on(<% if (filters.ngroute) { %>'$routeChangeStart'<% } %><% if (filters.uirouter) { %>'$stateChangeStart'<% } %>, function(event, next) { Auth.isLoggedIn(function(loggedIn) { if (next.authenticate && !loggedIn) { - <% if(filters.ngroute) { %>$location.path('/login');<% } if(filters.uirouter) { %>$state.go('login');<% } %> + <% if (filters.ngroute) { %>$location.path('/login');<% } if (filters.uirouter) { %>$state.go('login');<% } %> } }); }); diff --git a/app/templates/client/app/app(less).less b/app/templates/client/app/app(less).less index 30639f539..71381ceb1 100644 --- a/app/templates/client/app/app(less).less +++ b/app/templates/client/app/app(less).less @@ -1,7 +1,7 @@ -<% if(filters.bootstrap) { %>@import 'http://github.com/bootstrap/less/bootstrap.less';<% } %> +<% if (filters.bootstrap) { %>@import 'http://github.com/bootstrap/less/bootstrap.less';<% } %> @import 'http://github.com/font-awesome/less/font-awesome.less'; -<% if(filters.bootstrap) { %>@icon-font-path: '/bower_components/bootstrap/fonts/';<% } %> +<% if (filters.bootstrap) { %>@icon-font-path: '/bower_components/bootstrap/fonts/';<% } %> @fa-font-path: '/bower_components/font-awesome/fonts'; /** @@ -14,7 +14,7 @@ color: #000; padding: 0.2em 0; } -<% if (!filters.bootstrap) { %> +<% if(!filters.bootstrap) { %> /* Responsive: Portrait tablets and up */ @media screen and (min-width: 768px) { .container { diff --git a/app/templates/client/app/app(sass).scss b/app/templates/client/app/app(sass).scss index 4b8ae7a04..fe03d7044 100644 --- a/app/templates/client/app/app(sass).scss +++ b/app/templates/client/app/app(sass).scss @@ -1,6 +1,6 @@ -<% if(filters.bootstrap) { %>$icon-font-path: "/bower_components/bootstrap-sass-official/vendor/assets/fonts/bootstrap/";<% } %> +<% if (filters.bootstrap) { %>$icon-font-path: "/bower_components/bootstrap-sass-official/vendor/assets/fonts/bootstrap/";<% } %> $fa-font-path: "/bower_components/font-awesome/fonts"; -<% if(filters.bootstrap) { %> +<% if (filters.bootstrap) { %> @import 'http://github.com/bootstrap-sass-official/vendor/assets/stylesheets/bootstrap';<% } %> @import 'http://github.com/font-awesome/scss/font-awesome'; @@ -14,7 +14,7 @@ $fa-font-path: "/bower_components/font-awesome/fonts"; color: #000; padding: 0.2em 0; } -<% if (!filters.bootstrap) { %> +<% if(!filters.bootstrap) { %> /* Responsive: Portrait tablets and up */ @media screen and (min-width: 768px) { .container { diff --git a/app/templates/client/app/app(stylus).styl b/app/templates/client/app/app(stylus).styl index b7e4bb9c1..2d8afe893 100644 --- a/app/templates/client/app/app(stylus).styl +++ b/app/templates/client/app/app(stylus).styl @@ -1,5 +1,5 @@ @import "http://github.com/font-awesome/css/font-awesome.css" -<% if(filters.bootstrap) { %>@import "http://github.com/bootstrap/dist/css/bootstrap.css" +<% if (filters.bootstrap) { %>@import "http://github.com/bootstrap/dist/css/bootstrap.css" // // Bootstrap Fonts @@ -36,7 +36,7 @@ color #000 margin 0.2em 0 padding 0.2em 0 -<% if (!filters.bootstrap) { %> +<% if(!filters.bootstrap) { %> // Responsive: Portrait tablets and up @media screen and (min-width: 768px) .container diff --git a/app/templates/client/app/main/main(coffee).coffee b/app/templates/client/app/main/main(coffee).coffee index 6d84bdc1e..5d28335d1 100644 --- a/app/templates/client/app/main/main(coffee).coffee +++ b/app/templates/client/app/main/main(coffee).coffee @@ -1,12 +1,12 @@ 'use strict' angular.module '<%= scriptAppName %>' -<% if(filters.ngroute) { %>.config ($routeProvider) -> +<% if (filters.ngroute) { %>.config ($routeProvider) -> $routeProvider .when '/', templateUrl: 'app/main/main.html' controller: 'MainCtrl' -<% } %><% if(filters.uirouter) { %>.config ($stateProvider) -> +<% } %><% if (filters.uirouter) { %>.config ($stateProvider) -> $stateProvider .state 'main', url: '/' diff --git a/app/templates/client/app/main/main(html).html b/app/templates/client/app/main/main(html).html index cd0f185b2..7d0d5c44b 100644 --- a/app/templates/client/app/main/main(html).html +++ b/app/templates/client/app/main/main(html).html @@ -13,10 +13,10 @@

'Allo, 'Allo!

-
<% if(filters.socketio) { %> +
<% if (filters.socketio) { %>
diff --git a/app/templates/client/app/main/main(jade).jade b/app/templates/client/app/main/main(jade).jade index 76784c855..ee66a5fc6 100644 --- a/app/templates/client/app/main/main(jade).jade +++ b/app/templates/client/app/main/main(jade).jade @@ -13,8 +13,8 @@ header#banner.hero-unit ul.nav.nav-tabs.nav-stacked.col-md-4.col-lg-4.col-sm-6(ng-repeat='thing in awesomeThings') li a(href='#', tooltip='{{thing.info}}') - | {{thing.name}}<% if(filters.socketio) { %> - button.close(type='button', ng-click='deleteThing(thing)') ×<% } %><% if(filters.socketio) { %> + | {{thing.name}}<% if (filters.socketio) { %> + button.close(type='button', ng-click='deleteThing(thing)') ×<% } %><% if (filters.socketio) { %> form.thing-form label Syncs in realtime across clients diff --git a/app/templates/client/app/main/main(js).js b/app/templates/client/app/main/main(js).js index 1d3bc318a..165181ffe 100644 --- a/app/templates/client/app/main/main(js).js +++ b/app/templates/client/app/main/main(js).js @@ -1,17 +1,17 @@ 'use strict'; angular.module('<%= scriptAppName %>') - <% if(filters.ngroute) { %>.config(function ($routeProvider) { + <% if (filters.ngroute) { %>.config(function($routeProvider) { $routeProvider .when('/', { templateUrl: 'app/main/main.html', controller: 'MainCtrl' }); - });<% } %><% if(filters.uirouter) { %>.config(function ($stateProvider) { + });<% } %><% if (filters.uirouter) { %>.config(function($stateProvider) { $stateProvider .state('main', { url: '/', templateUrl: 'app/main/main.html', controller: 'MainCtrl' }); - });<% } %> \ No newline at end of file + });<% } %> diff --git a/app/templates/client/app/main/main.controller(coffee).coffee b/app/templates/client/app/main/main.controller(coffee).coffee index 143e7f387..3dffae2f7 100644 --- a/app/templates/client/app/main/main.controller(coffee).coffee +++ b/app/templates/client/app/main/main.controller(coffee).coffee @@ -1,13 +1,13 @@ 'use strict' angular.module '<%= scriptAppName %>' -.controller 'MainCtrl', ($scope, $http<% if(filters.socketio) { %>, socket<% } %>) -> +.controller 'MainCtrl', ($scope, $http<% if (filters.socketio) { %>, socket<% } %>) -> $scope.awesomeThings = [] $http.get('/api/things').success (awesomeThings) -> $scope.awesomeThings = awesomeThings - <% if(filters.socketio) { %>socket.syncUpdates 'thing', $scope.awesomeThings<% } %> -<% if(filters.mongoose) { %> + <% if (filters.socketio) { %>socket.syncUpdates 'thing', $scope.awesomeThings<% } %> +<% if (filters.mongoose) { %> $scope.addThing = -> return if $scope.newThing is '' $http.post '/api/things', @@ -16,7 +16,7 @@ angular.module '<%= scriptAppName %>' $scope.newThing = '' $scope.deleteThing = (thing) -> - $http.delete '/api/things/' + thing._id<% } %><% if(filters.socketio) { %> + $http.delete '/api/things/' + thing._id<% } %><% if (filters.socketio) { %> $scope.$on '$destroy', -> socket.unsyncUpdates 'thing'<% } %> diff --git a/app/templates/client/app/main/main.controller(js).js b/app/templates/client/app/main/main.controller(js).js index 433a10fe4..8164a90dc 100644 --- a/app/templates/client/app/main/main.controller(js).js +++ b/app/templates/client/app/main/main.controller(js).js @@ -1,16 +1,16 @@ 'use strict'; angular.module('<%= scriptAppName %>') - .controller('MainCtrl', function ($scope, $http<% if(filters.socketio) { %>, socket<% } %>) { + .controller('MainCtrl', function($scope, $http<% if (filters.socketio) { %>, socket<% } %>) { $scope.awesomeThings = []; $http.get('/api/things').success(function(awesomeThings) { - $scope.awesomeThings = awesomeThings;<% if(filters.socketio) { %> + $scope.awesomeThings = awesomeThings;<% if (filters.socketio) { %> socket.syncUpdates('thing', $scope.awesomeThings);<% } %> }); -<% if(filters.mongoose) { %> +<% if (filters.mongoose) { %> $scope.addThing = function() { - if($scope.newThing === '') { + if ($scope.newThing === '') { return; } $http.post('/api/things', { name: $scope.newThing }); @@ -19,9 +19,9 @@ angular.module('<%= scriptAppName %>') $scope.deleteThing = function(thing) { $http.delete('/api/things/' + thing._id); - };<% } %><% if(filters.socketio) { %> + };<% } %><% if (filters.socketio) { %> - $scope.$on('$destroy', function () { + $scope.$on('$destroy', function() { socket.unsyncUpdates('thing'); });<% } %> }); diff --git a/app/templates/client/app/main/main.controller.spec(coffee).coffee b/app/templates/client/app/main/main.controller.spec(coffee).coffee index 5bdf4f840..a72ae8695 100644 --- a/app/templates/client/app/main/main.controller.spec(coffee).coffee +++ b/app/templates/client/app/main/main.controller.spec(coffee).coffee @@ -3,17 +3,17 @@ describe 'Controller: MainCtrl', -> # load the controller's module - beforeEach module '<%= scriptAppName %>' <% if(filters.uirouter) {%> - beforeEach module 'stateMock' <% } %><% if(filters.socketio) {%> + beforeEach module '<%= scriptAppName %>' <% if (filters.uirouter) {%> + beforeEach module 'stateMock' <% } %><% if (filters.socketio) {%> beforeEach module 'socketMock' <% } %> MainCtrl = undefined - scope = undefined<% if(filters.uirouter) {%> + scope = undefined<% if (filters.uirouter) {%> state = undefined<% } %> $httpBackend = undefined # Initialize the controller and a mock scope - beforeEach inject (_$httpBackend_, $controller, $rootScope<% if(filters.uirouter) {%>, $state<% } %>) -> + beforeEach inject (_$httpBackend_, $controller, $rootScope<% if (filters.uirouter) {%>, $state<% } %>) -> $httpBackend = _$httpBackend_ $httpBackend.expectGET('/api/things').respond [ 'HTML5 Boilerplate' @@ -21,7 +21,7 @@ describe 'Controller: MainCtrl', -> 'Karma' 'Express' ] - scope = $rootScope.$new()<% if(filters.uirouter) {%> + scope = $rootScope.$new()<% if (filters.uirouter) {%> state = $state<% } %> MainCtrl = $controller 'MainCtrl', $scope: scope diff --git a/app/templates/client/app/main/main.controller.spec(js).js b/app/templates/client/app/main/main.controller.spec(js).js index dc048b4af..71fd2a783 100644 --- a/app/templates/client/app/main/main.controller.spec(js).js +++ b/app/templates/client/app/main/main.controller.spec(js).js @@ -1,31 +1,31 @@ 'use strict'; -describe('Controller: MainCtrl', function () { +describe('Controller: MainCtrl', function() { // load the controller's module - beforeEach(module('<%= scriptAppName %>'));<% if(filters.uirouter) {%> - beforeEach(module('stateMock'));<% } %><% if(filters.socketio) {%> + beforeEach(module('<%= scriptAppName %>'));<% if (filters.uirouter) {%> + beforeEach(module('stateMock'));<% } %><% if (filters.socketio) {%> beforeEach(module('socketMock'));<% } %> - var MainCtrl, - scope,<% if(filters.uirouter) {%> - state,<% } %> - $httpBackend; + var MainCtrl; + var scope;<% if (filters.uirouter) {%> + var state;<% } %> + var $httpBackend; // Initialize the controller and a mock scope - beforeEach(inject(function (_$httpBackend_, $controller, $rootScope<% if(filters.uirouter) {%>, $state<% } %>) { + beforeEach(inject(function(_$httpBackend_, $controller, $rootScope<% if (filters.uirouter) {%>, $state<% } %>) { $httpBackend = _$httpBackend_; $httpBackend.expectGET('/api/things') .respond(['HTML5 Boilerplate', 'AngularJS', 'Karma', 'Express']); - scope = $rootScope.$new();<% if(filters.uirouter) {%> + scope = $rootScope.$new();<% if (filters.uirouter) {%> state = $state;<% } %> MainCtrl = $controller('MainCtrl', { $scope: scope }); })); - it('should attach a list of things to the scope', function () { + it('should attach a list of things to the scope', function() { $httpBackend.flush();<% if (filters.jasmine) { %> expect(scope.awesomeThings.length).toBe(4);<% } if (filters.mocha) { %> <%= does("scope.awesomeThings.length") %>.equal(4);<% } %> diff --git a/app/templates/client/components/navbar/navbar(html).html b/app/templates/client/components/navbar/navbar(html).html index a93839562..ec9e4682d 100644 --- a/app/templates/client/components/navbar/navbar(html).html +++ b/app/templates/client/components/navbar/navbar(html).html @@ -11,18 +11,18 @@
diff --git a/app/templates/client/components/navbar/navbar(jade).jade b/app/templates/client/components/navbar/navbar(jade).jade index 7863f4e0a..5d7cb2795 100644 --- a/app/templates/client/components/navbar/navbar(jade).jade +++ b/app/templates/client/components/navbar/navbar(jade).jade @@ -10,25 +10,25 @@ div.navbar.navbar-default.navbar-static-top(ng-controller='NavbarCtrl') div#navbar-main.navbar-collapse.collapse(collapse='isCollapsed') ul.nav.navbar-nav - li(ng-repeat='item in menu', <% if(filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: isActive(item.link)}'<% } %>) - a(<% if(filters.uirouter) { %>ui-sref='{{item.state}}'<% } else { %>ng-href='http://github.com/%7B%7Bitem.link%7D%7D'<% } %>) {{item.title}}<% if(filters.auth) { %> + li(ng-repeat='item in menu', <% if (filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: isActive(item.link)}'<% } %>) + a(<% if (filters.uirouter) { %>ui-sref='{{item.state}}'<% } else { %>ng-href='http://github.com/%7B%7Bitem.link%7D%7D'<% } %>) {{item.title}}<% if (filters.auth) { %> - li(ng-show='isAdmin()', <% if(filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: isActive("/admin")}'<% } %>) - a(<% if(filters.uirouter) { %>ui-sref='admin'<% } else { %>href='http://github.com/admin'<% } %>) Admin + li(ng-show='isAdmin()', <% if (filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: isActive("/admin")}'<% } %>) + a(<% if (filters.uirouter) { %>ui-sref='admin'<% } else { %>href='http://github.com/admin'<% } %>) Admin ul.nav.navbar-nav.navbar-right - li(ng-hide='isLoggedIn()', <% if(filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: isActive("/signup")}'<% } %>) - a(<% if(filters.uirouter) { %>ui-sref='signup'<% } else { %>href='http://github.com/signup'<% } %>) Sign up + li(ng-hide='isLoggedIn()', <% if (filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: isActive("/signup")}'<% } %>) + a(<% if (filters.uirouter) { %>ui-sref='signup'<% } else { %>href='http://github.com/signup'<% } %>) Sign up - li(ng-hide='isLoggedIn()', <% if(filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: isActive("/login")}'<% } %>) - a(<% if(filters.uirouter) { %>ui-sref='login'<% } else { %>href='http://github.com/login'<% } %>) Login + li(ng-hide='isLoggedIn()', <% if (filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: isActive("/login")}'<% } %>) + a(<% if (filters.uirouter) { %>ui-sref='login'<% } else { %>href='http://github.com/login'<% } %>) Login li(ng-show='isLoggedIn()') p.navbar-text Hello {{ getCurrentUser().name }} - li(ng-show='isLoggedIn()', <% if(filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: isActive("/settings")}'<% } %>) - a(<% if(filters.uirouter) { %>ui-sref='settings'<% } else { %>href='http://github.com/settings'<% } %>) + li(ng-show='isLoggedIn()', <% if (filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: isActive("/settings")}'<% } %>) + a(<% if (filters.uirouter) { %>ui-sref='settings'<% } else { %>href='http://github.com/settings'<% } %>) span.glyphicon.glyphicon-cog li(ng-show='isLoggedIn()') - a(<% if(filters.uirouter) { %>ui-sref='logout'<% } else { %>href='http://github.com/logout'<% } %>) Logout<% } %> \ No newline at end of file + a(<% if (filters.uirouter) { %>ui-sref='logout'<% } else { %>href='http://github.com/logout'<% } %>) Logout<% } %> \ No newline at end of file diff --git a/app/templates/client/components/navbar/navbar.controller(coffee).coffee b/app/templates/client/components/navbar/navbar.controller(coffee).coffee index 121437cf1..9dda1ae4b 100644 --- a/app/templates/client/components/navbar/navbar.controller(coffee).coffee +++ b/app/templates/client/components/navbar/navbar.controller(coffee).coffee @@ -1,12 +1,12 @@ 'use strict' angular.module '<%= scriptAppName %>' -.controller 'NavbarCtrl', ($scope<% if(!filters.uirouter) { %>, $location<% } %><% if(filters.auth) {%>, Auth<% } %>) -> +.controller 'NavbarCtrl', ($scope<% if(!filters.uirouter) { %>, $location<% } %><% if (filters.auth) {%>, Auth<% } %>) -> $scope.menu = [ title: 'Home' - <% if(filters.uirouter) { %>state: 'main'<% } else { %>link: '/'<% } %> + <% if (filters.uirouter) { %>state: 'main'<% } else { %>link: '/'<% } %> ] - $scope.isCollapsed = true<% if(filters.auth) {%> + $scope.isCollapsed = true<% if (filters.auth) {%> $scope.isLoggedIn = Auth.isLoggedIn $scope.isAdmin = Auth.isAdmin $scope.getCurrentUser = Auth.getCurrentUser<% } %><% if(!filters.uirouter) { %> diff --git a/app/templates/client/components/navbar/navbar.controller(js).js b/app/templates/client/components/navbar/navbar.controller(js).js index 2428ac15b..b3eef7cf6 100644 --- a/app/templates/client/components/navbar/navbar.controller(js).js +++ b/app/templates/client/components/navbar/navbar.controller(js).js @@ -1,13 +1,13 @@ 'use strict'; angular.module('<%= scriptAppName %>') - .controller('NavbarCtrl', function ($scope<% if(!filters.uirouter) { %>, $location<% } %><% if(filters.auth) {%>, Auth<% } %>) { + .controller('NavbarCtrl', function ($scope<% if(!filters.uirouter) { %>, $location<% } %><% if (filters.auth) {%>, Auth<% } %>) { $scope.menu = [{ 'title': 'Home', - <% if(filters.uirouter) { %>'state': 'main'<% } else { %>'link': '/'<% } %> + <% if (filters.uirouter) { %>'state': 'main'<% } else { %>'link': '/'<% } %> }]; - $scope.isCollapsed = true;<% if(filters.auth) {%> + $scope.isCollapsed = true;<% if (filters.auth) {%> $scope.isLoggedIn = Auth.isLoggedIn; $scope.isAdmin = Auth.isAdmin; $scope.getCurrentUser = Auth.getCurrentUser;<% } %><% if(!filters.uirouter) { %> diff --git a/app/templates/client/index.html b/app/templates/client/index.html index e823e372d..479a3f2a3 100644 --- a/app/templates/client/index.html +++ b/app/templates/client/index.html @@ -27,7 +27,7 @@ - <% if(filters.ngroute) { %>
<% } %><% if(filters.uirouter) { %>
<% } %> + <% if (filters.ngroute) { %>
<% } %><% if (filters.uirouter) { %>
<% } %> <% } %> diff --git a/app/templates/e2e/components/navbar/navbar.po.js b/app/templates/e2e/components/navbar/navbar.po.js index ee2ec1ada..62f407210 100644 --- a/app/templates/e2e/components/navbar/navbar.po.js +++ b/app/templates/e2e/components/navbar/navbar.po.js @@ -8,7 +8,7 @@ var NavbarComponent = function() { this.navbar = element(by.css('.navbar')); this.navbarHeader = this.navbar.element(by.css('.navbar-header')); - this.navbarNav = this.navbar.element(by.css('#navbar-main .nav.navbar-nav:not(.navbar-right)'));<% if(filters.auth) { %> + this.navbarNav = this.navbar.element(by.css('#navbar-main .nav.navbar-nav:not(.navbar-right)'));<% if (filters.auth) { %> this.navbarAccount = this.navbar.element(by.css('#navbar-main .nav.navbar-nav.navbar-right')); this.navbarAccountGreeting = this.navbarAccount.element(by.binding('Hello {{ getCurrentUser().name }}'));<% } %> }; diff --git a/app/templates/karma.conf.js b/app/templates/karma.conf.js index 6b6c6c477..ed4cd2955 100644 --- a/app/templates/karma.conf.js +++ b/app/templates/karma.conf.js @@ -6,8 +6,8 @@ module.exports = function(config) { // base path, that will be used to resolve files and exclude basePath: '', - // testing framework to use (jasmine/mocha/qunit/...)<% if(filters.jasmine) { %> - frameworks: ['jasmine'],<% } if(filters.mocha) { %> + // testing framework to use (jasmine/mocha/qunit/...)<% if (filters.jasmine) { %> + frameworks: ['jasmine'],<% } if (filters.mocha) { %> frameworks: ['mocha', 'chai', 'sinon-chai', 'chai-as-promised', 'chai-things'],<% } %> // list of files / patterns to load in the browser @@ -18,10 +18,10 @@ module.exports = function(config) { 'client/bower_components/angular-resource/angular-resource.js', 'client/bower_components/angular-cookies/angular-cookies.js', 'client/bower_components/angular-sanitize/angular-sanitize.js', - 'client/bower_components/angular-route/angular-route.js',<% if(filters.uibootstrap) { %> + 'client/bower_components/angular-route/angular-route.js',<% if (filters.uibootstrap) { %> 'client/bower_components/angular-bootstrap/ui-bootstrap-tpls.js',<% } %> - 'client/bower_components/lodash/dist/lodash.compat.js',<% if(filters.socketio) { %> - 'client/bower_components/angular-socket-io/socket.js',<% } %><% if(filters.uirouter) { %> + 'client/bower_components/lodash/dist/lodash.compat.js',<% if (filters.socketio) { %> + 'client/bower_components/angular-socket-io/socket.js',<% } %><% if (filters.uirouter) { %> 'client/bower_components/angular-ui-router/release/angular-ui-router.js',<% } %> 'client/app/app.js', 'client/app/app.coffee', diff --git a/app/templates/protractor.conf.js b/app/templates/protractor.conf.js index 14f704b3d..f0061ff86 100644 --- a/app/templates/protractor.conf.js +++ b/app/templates/protractor.conf.js @@ -43,14 +43,14 @@ var config = { // Jasmine and Cucumber are fully supported as a test and assertion framework. // Mocha has limited beta support. You will need to include your own // assertion framework if working with mocha. - framework: '<% if(filters.jasmine) { %>jasmine<% } if(filters.mocha) { %>mocha<% } %>', -<% if(filters.jasmine) { %> + framework: '<% if (filters.jasmine) { %>jasmine<% } if (filters.mocha) { %>mocha<% } %>', +<% if (filters.jasmine) { %> // ----- Options to be passed to minijasminenode ----- // // See the full list at https://github.com/juliemr/minijasminenode jasmineNodeOpts: { defaultTimeoutInterval: 30000 - },<% } if(filters.mocha) { %> + },<% } if (filters.mocha) { %> // ----- Options to be passed to mocha ----- mochaOpts: { reporter: 'spec', @@ -63,7 +63,7 @@ var config = { serverConfig: require('./server/config/environment') }, - onPrepare: function() {<% if(filters.mocha) { %> + onPrepare: function() {<% if (filters.mocha) { %> // Load Mocha and Chai + plugins require('./mocha.conf'); diff --git a/app/templates/server/api/thing/index.js b/app/templates/server/api/thing/index.js index e77e80c5b..ea697d38b 100644 --- a/app/templates/server/api/thing/index.js +++ b/app/templates/server/api/thing/index.js @@ -5,7 +5,7 @@ var controller = require('./thing.controller'); var router = express.Router(); -router.get('/', controller.index);<% if(filters.mongoose) { %> +router.get('/', controller.index);<% if (filters.mongoose) { %> router.get('/:id', controller.show); router.post('/', controller.create); router.put('/:id', controller.update); diff --git a/app/templates/server/api/thing/index.spec.js b/app/templates/server/api/thing/index.spec.js index 3c6c71fc2..899b22d79 100644 --- a/app/templates/server/api/thing/index.spec.js +++ b/app/templates/server/api/thing/index.spec.js @@ -3,7 +3,7 @@ var proxyquire = require('proxyquire').noPreserveCache(); var thingCtrlStub = { - index: 'thingCtrl.index'<% if(filters.mongoose) { %>, + index: 'thingCtrl.index'<% if (filters.mongoose) { %>, show: 'thingCtrl.show', create: 'thingCtrl.create', update: 'thingCtrl.update', @@ -11,7 +11,7 @@ var thingCtrlStub = { }; var routerStub = { - get: sinon.spy()<% if(filters.mongoose) { %>, + get: sinon.spy()<% if (filters.mongoose) { %>, put: sinon.spy(), patch: sinon.spy(), post: sinon.spy(), @@ -37,15 +37,19 @@ describe('Thing API Router:', function() { describe('GET /api/things', function() { it('should route to thing.controller.index', function() { - routerStub.get.withArgs('/', 'thingCtrl.index').should.have.been.calledOnce; + routerStub.get + .withArgs('/', 'thingCtrl.index') + .should.have.been.calledOnce; }); - });<% if(filters.mongoose) { %> + });<% if (filters.mongoose) { %> describe('GET /api/things/:id', function() { it('should route to thing.controller.show', function() { - routerStub.get.withArgs('/:id', 'thingCtrl.show').should.have.been.calledOnce; + routerStub.get + .withArgs('/:id', 'thingCtrl.show') + .should.have.been.calledOnce; }); }); @@ -53,7 +57,9 @@ describe('Thing API Router:', function() { describe('POST /api/things', function() { it('should route to thing.controller.create', function() { - routerStub.post.withArgs('/', 'thingCtrl.create').should.have.been.calledOnce; + routerStub.post + .withArgs('/', 'thingCtrl.create') + .should.have.been.calledOnce; }); }); @@ -61,7 +67,9 @@ describe('Thing API Router:', function() { describe('PUT /api/things/:id', function() { it('should route to thing.controller.update', function() { - routerStub.put.withArgs('/:id', 'thingCtrl.update').should.have.been.calledOnce; + routerStub.put + .withArgs('/:id', 'thingCtrl.update') + .should.have.been.calledOnce; }); }); @@ -69,7 +77,9 @@ describe('Thing API Router:', function() { describe('PATCH /api/things/:id', function() { it('should route to thing.controller.update', function() { - routerStub.patch.withArgs('/:id', 'thingCtrl.update').should.have.been.calledOnce; + routerStub.patch + .withArgs('/:id', 'thingCtrl.update') + .should.have.been.calledOnce; }); }); @@ -77,7 +87,9 @@ describe('Thing API Router:', function() { describe('DELETE /api/things/:id', function() { it('should route to thing.controller.destroy', function() { - routerStub.delete.withArgs('/:id', 'thingCtrl.destroy').should.have.been.calledOnce; + routerStub.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 23bfd6937..710c7cd38 100644 --- a/app/templates/server/api/thing/thing.controller.js +++ b/app/templates/server/api/thing/thing.controller.js @@ -12,25 +12,25 @@ var _ = require('lodash'); var Thing = require('./thing.model'); -function handleError(res, statusCode){ +function handleError(res, statusCode) { statusCode = statusCode || 500; - return function(err){ + return function(err) { res.send(statusCode, err); }; } -function responseWithResult(res, statusCode){ +function responseWithResult(res, statusCode) { statusCode = statusCode || 200; - return function(entity){ - if(entity){ + return function(entity) { + if (entity) { return res.json(statusCode, entity); } }; } -function handleEntityNotFound(res){ - return function(entity){ - if(!entity){ +function handleEntityNotFound(res) { + return function(entity) { + if (!entity) { res.send(404); return null; } @@ -38,19 +38,19 @@ function handleEntityNotFound(res){ }; } -function saveUpdates(updates){ - return function(entity){ +function saveUpdates(updates) { + return function(entity) { var updated = _.merge(entity, updates); return updated.saveAsync() - .spread(function (updated) { + .spread(function(updated) { return updated; }); }; } -function removeEntity(res){ - return function (entity) { - if(entity){ +function removeEntity(res) { + return function(entity) { + if (entity) { return entity.removeAsync() .then(function() { return res.send(204); @@ -60,28 +60,31 @@ function removeEntity(res){ }<% } %> // Get list of things -exports.index = function(req, res) {<% if (!filters.mongoose) { %> - res.json([ - { - name : 'Development Tools', - info : 'Integration with popular tools such as Bower, Grunt, Karma, Mocha, JSHint, Node Inspector, Livereload, Protractor, Jade, Stylus, Sass, CoffeeScript, and Less.' +exports.index = function(req, res) {<% if(!filters.mongoose) { %> + res.json([{ + name : 'Development Tools', + info : 'Integration with popular tools such as Bower, Grunt, Karma, Mocha, JSHint, ' + + 'Node Inspector, Livereload, Protractor, Jade, Stylus, Sass, CoffeeScript, and Less.' }, { - name : 'Server and Client integration', - info : 'Built with a powerful and fun stack: MongoDB, Express, AngularJS, and Node.' + name : 'Server and Client integration', + info : 'Built with a powerful and fun stack: MongoDB, Express, AngularJS, and Node.' }, { - name : 'Smart Build System', - info : 'Build system ignores `spec` files, allowing you to keep tests alongside code. Automatic injection of scripts and styles into your index.html' - }, { - name : 'Modular Structure', - info : 'Best practice client and server structures allow for more code reusability and maximum scalability' - }, { - name : 'Optimized Build', - info : 'Build process packs up your templates as a single JavaScript payload, minifies your scripts/css/images, and rewrites asset names for caching.' - },{ - name : 'Deployment Ready', - info : 'Easily deploy your app to Heroku or Openshift with the heroku and openshift subgenerators' - } - ]);<% } if (filters.mongoose) { %> + name : 'Smart Build System', + info : 'Build system ignores `spec` files, allowing you to keep tests alongside code. ' + + 'Automatic injection of scripts and styles into your index.html' + }, { + name : 'Modular Structure', + info : 'Best practice client and server structures allow for more code reusability and ' + + 'maximum scalability' + }, { + name : 'Optimized Build', + info : 'Build process packs up your templates as a single JavaScript payload, minifies ' + + 'your scripts/css/images, and rewrites asset names for caching.' + }, { + name : 'Deployment Ready', + info : 'Easily deploy your app to Heroku or Openshift with the heroku and openshift ' + + 'subgenerators' + }]);<% } if (filters.mongoose) { %> Thing.findAsync() .then(responseWithResult(res)) .catch(handleError(res));<% } %> @@ -104,7 +107,7 @@ exports.create = function(req, res) { // Updates an existing thing in the DB. exports.update = function(req, res) { - if(req.body._id) { + if (req.body._id) { delete req.body._id; } Thing.findByIdAsync(req.params.id) diff --git a/app/templates/server/api/thing/thing.integration.js b/app/templates/server/api/thing/thing.integration.js index 1140df7e9..de7ed7ff5 100644 --- a/app/templates/server/api/thing/thing.integration.js +++ b/app/templates/server/api/thing/thing.integration.js @@ -1,7 +1,7 @@ 'use strict'; var app = require('../../app'); -var request = require('supertest');<% if(filters.mongoose) { %> +var request = require('supertest');<% if (filters.mongoose) { %> var newThing;<% } %> @@ -16,7 +16,9 @@ describe('Thing API:', function() { .expect(200) .expect('Content-Type', /json/) .end(function(err, res) { - if (err) return done(err); + if (err) { + return done(err); + } things = res.body; done(); }); @@ -26,7 +28,7 @@ describe('Thing API:', function() { things.should.be.instanceOf(Array); }); - });<% if(filters.mongoose) { %> + });<% if (filters.mongoose) { %> describe('POST /api/things', function() { beforeEach(function(done) { @@ -39,7 +41,9 @@ describe('Thing API:', function() { .expect(201) .expect('Content-Type', /json/) .end(function(err, res) { - if (err) return done(err); + if (err) { + return done(err); + } newThing = res.body; done(); }); @@ -61,7 +65,9 @@ describe('Thing API:', function() { .expect(200) .expect('Content-Type', /json/) .end(function(err, res) { - if (err) return done(err); + if (err) { + return done(err); + } thing = res.body; done(); }); @@ -91,7 +97,9 @@ describe('Thing API:', function() { .expect(200) .expect('Content-Type', /json/) .end(function(err, res) { - if (err) return done(err); + if (err) { + return done(err); + } updatedThing = res.body; done(); }); @@ -115,7 +123,9 @@ describe('Thing API:', function() { .delete('/api/things/' + newThing._id) .expect(204) .end(function(err, res) { - if (err) return done(err); + if (err) { + return done(err); + } done(); }); }); @@ -125,7 +135,9 @@ describe('Thing API:', function() { .delete('/api/things/' + newThing._id) .expect(404) .end(function(err, res) { - if (err) return done(err); + 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 a44bc710e..d1e6e49ea 100644 --- a/app/templates/server/api/thing/thing.model(mongoose).js +++ b/app/templates/server/api/thing/thing.model(mongoose).js @@ -1,7 +1,7 @@ 'use strict'; -var mongoose = require('mongoose-bird')(), - Schema = mongoose.Schema; +var mongoose = require('mongoose-bird')(); +var Schema = mongoose.Schema; var ThingSchema = new Schema({ name: String, diff --git a/app/templates/server/api/thing/thing.socket(socketio).js b/app/templates/server/api/thing/thing.socket(socketio).js index d38e73e0d..2d0171cdc 100644 --- a/app/templates/server/api/thing/thing.socket(socketio).js +++ b/app/templates/server/api/thing/thing.socket(socketio).js @@ -7,10 +7,10 @@ var thing = require('./thing.model'); exports.register = function(socket) { - thing.schema.post('save', function (doc) { + thing.schema.post('save', function(doc) { onSave(socket, doc); }); - thing.schema.post('remove', function (doc) { + thing.schema.post('remove', function(doc) { onRemove(socket, doc); }); }; diff --git a/app/templates/server/api/user(auth)/index.spec.js b/app/templates/server/api/user(auth)/index.spec.js index b2510aa00..d2ee914bd 100644 --- a/app/templates/server/api/user(auth)/index.spec.js +++ b/app/templates/server/api/user(auth)/index.spec.js @@ -47,7 +47,9 @@ describe('User API Router:', function() { describe('GET /api/users', function() { it('should verify admin role and route to user.controller.index', function() { - routerStub.get.withArgs('/', 'authService.hasRole.admin', 'userCtrl.index').should.have.been.calledOnce; + routerStub.get + .withArgs('/', 'authService.hasRole.admin', 'userCtrl.index') + .should.have.been.calledOnce; }); }); @@ -55,7 +57,9 @@ describe('User API Router:', function() { describe('DELETE /api/users/:id', function() { it('should verify admin role and route to user.controller.destroy', function() { - routerStub.delete.withArgs('/:id', 'authService.hasRole.admin', 'userCtrl.destroy').should.have.been.calledOnce; + routerStub.delete + .withArgs('/:id', 'authService.hasRole.admin', 'userCtrl.destroy') + .should.have.been.calledOnce; }); }); @@ -63,7 +67,9 @@ describe('User API Router:', function() { describe('GET /api/users/me', function() { it('should be authenticated and route to user.controller.me', function() { - routerStub.get.withArgs('/me', 'authService.isAuthenticated', 'userCtrl.me').should.have.been.calledOnce; + routerStub.get + .withArgs('/me', 'authService.isAuthenticated', 'userCtrl.me') + .should.have.been.calledOnce; }); }); @@ -71,7 +77,9 @@ describe('User API Router:', function() { describe('PUT /api/users/:id/password', function() { it('should be authenticated and route to user.controller.changePassword', function() { - routerStub.put.withArgs('/:id/password', 'authService.isAuthenticated', 'userCtrl.changePassword').should.have.been.calledOnce; + routerStub.put + .withArgs('/:id/password', 'authService.isAuthenticated', 'userCtrl.changePassword') + .should.have.been.calledOnce; }); }); @@ -79,7 +87,9 @@ describe('User API Router:', function() { describe('GET /api/users/:id', function() { it('should be authenticated and route to user.controller.show', function() { - routerStub.get.withArgs('/:id', 'authService.isAuthenticated', 'userCtrl.show').should.have.been.calledOnce; + routerStub.get + .withArgs('/:id', 'authService.isAuthenticated', 'userCtrl.show') + .should.have.been.calledOnce; }); }); @@ -87,7 +97,9 @@ describe('User API Router:', function() { describe('POST /api/users', function() { it('should route to user.controller.create', function() { - routerStub.post.withArgs('/', 'userCtrl.create').should.have.been.calledOnce; + routerStub.post + .withArgs('/', 'userCtrl.create') + .should.have.been.calledOnce; }); }); diff --git a/app/templates/server/api/user(auth)/user.controller.js b/app/templates/server/api/user(auth)/user.controller.js index ed0b1749c..793da0255 100644 --- a/app/templates/server/api/user(auth)/user.controller.js +++ b/app/templates/server/api/user(auth)/user.controller.js @@ -7,21 +7,21 @@ var jwt = require('jsonwebtoken'); var validationError = function(res, statusCode) { statusCode = statusCode || 422; - return function(err){ + return function(err) { res.json(statusCode, err); }; }; -function handleError(res, statusCode){ +function handleError(res, statusCode) { statusCode = statusCode || 500; - return function(err){ + return function(err) { res.send(statusCode, err); }; } -function respondWith(res, statusCode){ +function respondWith(res, statusCode) { statusCode = statusCode || 200; - return function(){ + return function() { res.send(statusCode); }; } @@ -32,7 +32,7 @@ function respondWith(res, statusCode){ */ exports.index = function(req, res) { User.findAsync({}, '-salt -hashedPassword') - .then(function (users) { + .then(function(users) { res.json(200, users); }) .catch(handleError(res)); @@ -41,13 +41,15 @@ exports.index = function(req, res) { /** * Creates a new user */ -exports.create = function (req, res, next) { +exports.create = function(req, res, next) { var newUser = new User(req.body); newUser.provider = 'local'; newUser.role = 'user'; newUser.saveAsync() .spread(function(user) { - var token = jwt.sign({_id: user._id }, config.secrets.session, { expiresInMinutes: 60*5 }); + var token = jwt.sign({ _id: user._id }, config.secrets.session, { + expiresInMinutes: 60 * 5 + }); res.json({ token: token }); }) .catch(validationError(res)); @@ -56,17 +58,17 @@ exports.create = function (req, res, next) { /** * Get a single user */ -exports.show = function (req, res, next) { +exports.show = function(req, res, next) { var userId = req.params.id; User.findByIdAsync(userId) - .then(function (user) { - if(!user) { + .then(function(user) { + if (!user) { return res.send(401); } res.json(user.profile); }) - .catch(function(err){ + .catch(function(err) { return next(err); }); }; @@ -91,7 +93,7 @@ exports.changePassword = function(req, res, next) { User.findByIdAsync(userId) .then(function(user) { - if(user.authenticate(oldPass)) { + if (user.authenticate(oldPass)) { user.password = newPass; return user.saveAsync() .spread(respondWith(res, 200)) @@ -113,7 +115,9 @@ exports.me = function(req, res, next) { if (!user) { return res.json(401); } res.json(user); }) - .catch(function(err){ return next(err); }); + .catch(function(err) { + return next(err); + }); }; /** diff --git a/app/templates/server/api/user(auth)/user.integration.js b/app/templates/server/api/user(auth)/user.integration.js index 917acedd9..ee97d3051 100644 --- a/app/templates/server/api/user(auth)/user.integration.js +++ b/app/templates/server/api/user(auth)/user.integration.js @@ -17,7 +17,9 @@ describe('User API:', function() { }); user.save(function(err) { - if (err) return done(err); + if (err) { + return done(err); + } done(); }); }); diff --git a/app/templates/server/api/user(auth)/user.model.js b/app/templates/server/api/user(auth)/user.model.js index b90386886..201afb4bc 100644 --- a/app/templates/server/api/user(auth)/user.model.js +++ b/app/templates/server/api/user(auth)/user.model.js @@ -2,12 +2,15 @@ var mongoose = require('mongoose-bird')(); var Schema = mongoose.Schema; -var crypto = require('crypto');<% if(filters.oauth) { %> +var crypto = require('crypto');<% if (filters.oauth) { %> var authTypes = ['github', 'twitter', 'facebook', 'google'];<% } %> var UserSchema = new Schema({ name: String, - email: { type: String, lowercase: true }, + email: { + type: String, + lowercase: true + }, role: { type: String, default: 'user' @@ -53,9 +56,9 @@ UserSchema UserSchema .path('email') .validate(function(email) {<% if (filters.oauth) { %> - if (authTypes.indexOf(this.provider) !== -1){ + if (authTypes.indexOf(this.provider) !== -1) { return true; - } <% } %> + }<% } %> return email.length; }, 'Email cannot be blank'); @@ -63,9 +66,9 @@ UserSchema UserSchema .path('password') .validate(function(password) {<% if (filters.oauth) { %> - if (authTypes.indexOf(this.provider) !== -1){ + if (authTypes.indexOf(this.provider) !== -1) { return true; - } <% } %> + }<% } %> return password.length; }, 'Password cannot be blank'); @@ -74,20 +77,20 @@ UserSchema .path('email') .validate(function(value, respond) { var self = this; - return this.constructor.findOneAsync({email: value}) + return this.constructor.findOneAsync({ email: value }) .then(function(user) { - if(user) { - if(self.id === user.id) { + if (user) { + if (self.id === user.id) { return respond(true); } return respond(false); } return respond(true); }) - .catch(function(err){ + .catch(function(err) { throw err; }); -}, 'The specified email address is already in use.'); + }, 'The specified email address is already in use.'); var validatePresenceOf = function(value) { return value && value.length; @@ -100,17 +103,21 @@ UserSchema .pre('save', function(next) { // Handle new/update passwords if (this.password) { - if (!validatePresenceOf(this.password)<% if (filters.oauth) { %> && authTypes.indexOf(this.provider) === -1<% } %>) + if (!validatePresenceOf(this.password)<% if (filters.oauth) { %> && authTypes.indexOf(this.provider) === -1<% } %>) { next(new Error('Invalid password')); + } // Make salt with a callback var _this = this; this.makeSalt(function(saltErr, salt) { - if (saltErr) next(saltErr); + if (saltErr) { + next(saltErr); + } _this.salt = salt; - // Async hash _this.encryptPassword(_this.password, function(encryptErr, hashedPassword) { - if (encryptErr) next(encryptErr); + if (encryptErr) { + next(encryptErr); + } _this.password = hashedPassword; next(); }); @@ -127,22 +134,26 @@ UserSchema.methods = { /** * Authenticate - check if the passwords are the same * - * @param {String} plainText - * @callback {callback} Optional callback + * @param {String} password + * @param {Function} callback * @return {Boolean} * @api public */ authenticate: function(password, callback) { - if (!callback) + if (!callback) { return this.password === this.encryptPassword(password); + } var _this = this; this.encryptPassword(password, function(err, pwdGen) { - if (err) callback(err); + if (err) { + callback(err); + } if (_this.password === pwdGen) { callback(null, true); - } else { + } + else { callback(null, false); } }); @@ -152,7 +163,7 @@ UserSchema.methods = { * Make salt * * @param {Number} byteSize Optional salt byte size, default to 16 - * @callback {callback} Optional callback + * @param {Function} callback * @return {String} * @api public */ @@ -162,7 +173,8 @@ UserSchema.methods = { if (typeof arguments[0] === 'function') { callback = arguments[0]; byteSize = defaultByteSize; - } else if (typeof arguments[1] === 'function') { + } + else if (typeof arguments[1] === 'function') { callback = arguments[1]; } @@ -175,7 +187,9 @@ UserSchema.methods = { } return crypto.randomBytes(byteSize, function(err, salt) { - if (err) callback(err); + if (err) { + callback(err); + } return callback(null, salt.toString('base64')); }); }, @@ -184,7 +198,7 @@ UserSchema.methods = { * Encrypt password * * @param {String} password - * @callback {callback} Optional callback + * @param {Function} callback * @return {String} * @api public */ @@ -197,11 +211,15 @@ UserSchema.methods = { var defaultKeyLength = 64; var salt = new Buffer(this.salt, 'base64'); - if (!callback) - return crypto.pbkdf2Sync(password, salt, defaultIterations, defaultKeyLength).toString('base64'); + if (!callback) { + return crypto.pbkdf2Sync(password, salt, defaultIterations, defaultKeyLength) + .toString('base64'); + } return crypto.pbkdf2(password, salt, defaultIterations, defaultKeyLength, function(err, key) { - if (err) callback(err); + if (err) { + callback(err); + } return callback(null, key.toString('base64')); }); } 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 fe51ea2ea..16de6e2de 100644 --- a/app/templates/server/api/user(auth)/user.model.spec.js +++ b/app/templates/server/api/user(auth)/user.model.spec.js @@ -38,11 +38,11 @@ describe('User Model', function() { return user.saveAsync().should.be.rejected; }); - it("should authenticate user if password is valid", function() { + it('should authenticate user if password is valid', function() { user.authenticate('password').should.be.true; }); - it("should not authenticate user if password is invalid", function() { + it('should not authenticate user if password is invalid', function() { user.authenticate('blah').should.not.be.true; }); }); diff --git a/app/templates/server/app.js b/app/templates/server/app.js index 5369e94ef..632dd134f 100644 --- a/app/templates/server/app.js +++ b/app/templates/server/app.js @@ -15,7 +15,7 @@ var config = require('./config/environment'); mongoose.connect(config.mongo.uri, config.mongo.options); // Populate DB with sample data -if(config.seedDB) { require('./config/seed'); } +if (config.seedDB) { require('./config/seed'); } <% } %>// Setup server var app = express(); @@ -29,7 +29,7 @@ require('./config/express')(app); require('./routes')(app); // Start server -server.listen(config.port, config.ip, function () { +server.listen(config.port, config.ip, function() { console.log('Express server listening on %d, in %s mode', config.port, app.get('env')); }); diff --git a/app/templates/server/auth(auth)/auth.service.js b/app/templates/server/auth(auth)/auth.service.js index 101dcc5c5..43ea2851f 100644 --- a/app/templates/server/auth(auth)/auth.service.js +++ b/app/templates/server/auth(auth)/auth.service.js @@ -7,7 +7,9 @@ var jwt = require('jsonwebtoken'); var expressJwt = require('express-jwt'); var compose = require('composable-middleware'); var User = require('../api/user/user.model'); -var validateJwt = expressJwt({ secret: config.secrets.session }); +var validateJwt = expressJwt({ + secret: config.secrets.session +}); /** * Attaches the user object to the request if authenticated @@ -18,7 +20,7 @@ function isAuthenticated() { // Validate jwt .use(function(req, res, next) { // allow access_token to be passed through query parameter as well - if(req.query && req.query.hasOwnProperty('access_token')) { + if (req.query && req.query.hasOwnProperty('access_token')) { req.headers.authorization = 'Bearer ' + req.query.access_token; } validateJwt(req, res, next); @@ -26,14 +28,14 @@ function isAuthenticated() { // Attach user to request .use(function(req, res, next) { User.findByIdAsync(req.user._id) - .then(function (user) { + .then(function(user) { if (!user) { return res.send(401); } req.user = user; next(); }) - .catch(function(err){ + .catch(function(err) { return next(err); }); }); @@ -50,7 +52,8 @@ function hasRole(roleRequired) { return compose() .use(isAuthenticated()) .use(function meetsRequirements(req, res, next) { - if (config.userRoles.indexOf(req.user.role) >= config.userRoles.indexOf(roleRequired)) { + if (config.userRoles.indexOf(req.user.role) >= + config.userRoles.indexOf(roleRequired)) { next(); } else { @@ -63,7 +66,9 @@ function hasRole(roleRequired) { * Returns a jwt token signed by the app secret */ function signToken(id) { - return jwt.sign({ _id: id }, config.secrets.session, { expiresInMinutes: 60*5 }); + return jwt.sign({ _id: id }, config.secrets.session, { + expiresInMinutes: 60 * 5 + }); } /** @@ -71,7 +76,9 @@ function signToken(id) { */ function setTokenCookie(req, res) { if (!req.user) { - return res.json(404, { message: 'Something went wrong, please try again.'}); + return res.json(404, { + message: 'Something went wrong, please try again.' + }); } var token = signToken(req.user._id, req.user.role); res.cookie('token', JSON.stringify(token)); diff --git a/app/templates/server/auth(auth)/facebook(facebookAuth)/index.js b/app/templates/server/auth(auth)/facebook(facebookAuth)/index.js index 4a6f87886..f13d463e1 100644 --- a/app/templates/server/auth(auth)/facebook(facebookAuth)/index.js +++ b/app/templates/server/auth(auth)/facebook(facebookAuth)/index.js @@ -18,4 +18,4 @@ router session: false }), auth.setTokenCookie); -module.exports = router; \ No newline at end of file +module.exports = router; diff --git a/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js b/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js index 90ae48939..b29d74c69 100644 --- a/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js +++ b/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js @@ -1,37 +1,38 @@ var passport = require('passport'); var FacebookStrategy = require('passport-facebook').Strategy; -exports.setup = function (User, config) { +exports.setup = function(User, config) { passport.use(new FacebookStrategy({ - clientID: config.facebook.clientID, - clientSecret: config.facebook.clientSecret, - callbackURL: config.facebook.callbackURL + clientID: config.facebook.clientID, + clientSecret: config.facebook.clientSecret, + callbackURL: config.facebook.callbackURL + }, + function(accessToken, refreshToken, profile, done) { + User.findOne({ + 'facebook.id': profile.id }, - function(accessToken, refreshToken, profile, done) { - User.findOne({ - 'facebook.id': profile.id - }, - function(err, user) { - if (err) { - return done(err); - } - if (!user) { - user = new User({ - name: profile.displayName, - email: profile.emails[0].value, - role: 'user', - username: profile.username, - provider: 'facebook', - facebook: profile._json - }); - user.save(function(err) { - if (err) done(err); - return done(err, user); - }); - } else { + function(err, user) { + if (err) { + return done(err); + } + if (!user) { + user = new User({ + name: profile.displayName, + email: profile.emails[0].value, + role: 'user', + username: profile.username, + provider: 'facebook', + facebook: profile._json + }); + user.save(function(err) { + if (err) { + done(err); + } return done(err, user); - } - }) - } - )); -}; \ No newline at end of file + }); + } else { + return done(err, user); + } + }) + })); +}; diff --git a/app/templates/server/auth(auth)/google(googleAuth)/index.js b/app/templates/server/auth(auth)/google(googleAuth)/index.js index 9b1ce39fe..673c22db4 100644 --- a/app/templates/server/auth(auth)/google(googleAuth)/index.js +++ b/app/templates/server/auth(auth)/google(googleAuth)/index.js @@ -21,4 +21,4 @@ router session: false }), auth.setTokenCookie); -module.exports = router; \ No newline at end of file +module.exports = router; diff --git a/app/templates/server/auth(auth)/google(googleAuth)/passport.js b/app/templates/server/auth(auth)/google(googleAuth)/passport.js index d304e8ac9..0e7a3602d 100644 --- a/app/templates/server/auth(auth)/google(googleAuth)/passport.js +++ b/app/templates/server/auth(auth)/google(googleAuth)/passport.js @@ -1,33 +1,34 @@ var passport = require('passport'); var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy; -exports.setup = function (User, config) { +exports.setup = function(User, config) { passport.use(new GoogleStrategy({ - clientID: config.google.clientID, - clientSecret: config.google.clientSecret, - callbackURL: config.google.callbackURL - }, - function(accessToken, refreshToken, profile, done) { - User.findOne({ - 'google.id': profile.id - }, function(err, user) { - if (!user) { - user = new User({ - name: profile.displayName, - email: profile.emails[0].value, - role: 'user', - username: profile.username, - provider: 'google', - google: profile._json - }); - user.save(function(err) { - if (err) done(err); - return done(err, user); - }); - } else { + clientID: config.google.clientID, + clientSecret: config.google.clientSecret, + callbackURL: config.google.callbackURL + }, + function(accessToken, refreshToken, profile, done) { + User.findOne({ + 'google.id': profile.id + }, function(err, user) { + if (!user) { + user = new User({ + name: profile.displayName, + email: profile.emails[0].value, + role: 'user', + username: profile.username, + provider: 'google', + google: profile._json + }); + user.save(function(err) { + if (err) { + done(err); + } return done(err, user); - } - }); - } - )); + }); + } else { + return done(err, user); + } + }); + })); }; diff --git a/app/templates/server/auth(auth)/index.js b/app/templates/server/auth(auth)/index.js index e3e6c87ad..b930ad93f 100644 --- a/app/templates/server/auth(auth)/index.js +++ b/app/templates/server/auth(auth)/index.js @@ -18,4 +18,4 @@ router.use('/facebook', require('./facebook'));<% } %><% if (filters.twitterAuth router.use('/twitter', require('./twitter'));<% } %><% if (filters.googleAuth) { %> router.use('/google', require('./google'));<% } %> -module.exports = router; \ No newline at end of file +module.exports = router; diff --git a/app/templates/server/auth(auth)/local/index.js b/app/templates/server/auth(auth)/local/index.js index 8bf88a046..3a9198d11 100644 --- a/app/templates/server/auth(auth)/local/index.js +++ b/app/templates/server/auth(auth)/local/index.js @@ -7,14 +7,20 @@ var auth = require('../auth.service'); var router = express.Router(); router.post('/', function(req, res, next) { - passport.authenticate('local', function (err, user, info) { + passport.authenticate('local', function(err, user, info) { var error = err || info; - if (error) return res.json(401, error); - if (!user) return res.json(404, {message: 'Something went wrong, please try again.'}); + if (error) { + return res.json(401, error); + } + if (!user) { + return res.json(404, { + message: 'Something went wrong, please try again.' + }); + } var token = auth.signToken(user._id, user.role); - res.json({token: token}); + res.json({ token: token }); })(req, res, next) }); -module.exports = router; \ No newline at end of file +module.exports = router; diff --git a/app/templates/server/auth(auth)/local/passport.js b/app/templates/server/auth(auth)/local/passport.js index 4221f8786..f4898b73a 100644 --- a/app/templates/server/auth(auth)/local/passport.js +++ b/app/templates/server/auth(auth)/local/passport.js @@ -1,29 +1,35 @@ var passport = require('passport'); var LocalStrategy = require('passport-local').Strategy; -exports.setup = function (User, config) { +exports.setup = function(User, config) { passport.use(new LocalStrategy({ - usernameField: 'email', - passwordField: 'password' // this is the virtual field on the model - }, - function(email, password, done) { - User.findOne({ - email: email.toLowerCase() - }, function(err, user) { - if (err) return done(err); + usernameField: 'email', + passwordField: 'password' // this is the virtual field on the model + }, function(email, password, done) { + User.findOne({ + email: email.toLowerCase() + }, function(err, user) { + if (err) { + return done(err); + } - if (!user) { - return done(null, false, { message: 'This email is not registered.' }); - } - user.authenticate(password, function(authError, authenticated) { - if (authError) return done(authError); - if (!authenticated) { - return done(null, false, { message: 'This password is not correct.' }); - } else { - return done(null, user); - } + if (!user) { + return done(null, false, { + message: 'This email is not registered.' }); + } + user.authenticate(password, function(authError, authenticated) { + if (authError) { + return done(authError); + } + if (!authenticated) { + return done(null, false, { + message: 'This password is not correct.' + }); + } else { + return done(null, user); + } }); - } - )); + }); + })); }; diff --git a/app/templates/server/auth(auth)/twitter(twitterAuth)/index.js b/app/templates/server/auth(auth)/twitter(twitterAuth)/index.js index 8360247b8..8e6f32b5d 100644 --- a/app/templates/server/auth(auth)/twitter(twitterAuth)/index.js +++ b/app/templates/server/auth(auth)/twitter(twitterAuth)/index.js @@ -17,4 +17,4 @@ router session: false }), auth.setTokenCookie); -module.exports = router; \ No newline at end of file +module.exports = router; diff --git a/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js b/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js index a2eb4a537..7428e8afd 100644 --- a/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js +++ b/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js @@ -1,4 +1,4 @@ -exports.setup = function (User, config) { +exports.setup = function(User, config) { var passport = require('passport'); var TwitterStrategy = require('passport-twitter').Strategy; @@ -23,13 +23,14 @@ exports.setup = function (User, config) { twitter: profile._json }); user.save(function(err) { - if (err) return done(err); + if (err) { + return done(err); + } return done(err, user); }); } else { return done(err, user); } }); - } - )); -}; \ No newline at end of file + })); +}; diff --git a/app/templates/server/components/errors/index.js b/app/templates/server/components/errors/index.js index 4c5a57c99..52dba3749 100644 --- a/app/templates/server/components/errors/index.js +++ b/app/templates/server/components/errors/index.js @@ -12,8 +12,10 @@ module.exports[404] = function pageNotFound(req, res) { }; res.status(result.status); - res.render(viewFilePath, function (err) { - if (err) { return res.json(result, result.status); } + res.render(viewFilePath, function(err) { + if (err) { + return res.json(result, result.status); + } res.render(viewFilePath); }); diff --git a/app/templates/server/config/_local.env.js b/app/templates/server/config/_local.env.js index c24fffd3a..12b78192e 100644 --- a/app/templates/server/config/_local.env.js +++ b/app/templates/server/config/_local.env.js @@ -7,7 +7,7 @@ module.exports = { DOMAIN: 'http://localhost:9000/', - SESSION_SECRET: "<%= _.slugify(appname) + '-secret' %>",<% if (filters.facebookAuth) { %> + SESSION_SECRET: '<%= _.slugify(appname) + "-secret" %>',<% if (filters.facebookAuth) { %> FACEBOOK_ID: 'app-id', FACEBOOK_SECRET: 'secret',<% } if (filters.twitterAuth) { %> diff --git a/app/templates/server/config/environment/index.js b/app/templates/server/config/environment/index.js index 11d85f4de..2476a7e8c 100644 --- a/app/templates/server/config/environment/index.js +++ b/app/templates/server/config/environment/index.js @@ -4,7 +4,7 @@ var path = require('path'); var _ = require('lodash'); function requiredProcessEnv(name) { - if(!process.env[name]) { + if (!process.env[name]) { throw new Error('You must set the ' + name + ' environment variable'); } return process.env[name]; @@ -40,19 +40,19 @@ var all = { } } }, -<% if(filters.facebookAuth) { %> +<% if (filters.facebookAuth) { %> facebook: { clientID: process.env.FACEBOOK_ID || 'id', clientSecret: process.env.FACEBOOK_SECRET || 'secret', callbackURL: (process.env.DOMAIN || '') + '/auth/facebook/callback' }, -<% } %><% if(filters.twitterAuth) { %> +<% } %><% if (filters.twitterAuth) { %> twitter: { clientID: process.env.TWITTER_ID || 'id', clientSecret: process.env.TWITTER_SECRET || 'secret', callbackURL: (process.env.DOMAIN || '') + '/auth/twitter/callback' }, -<% } %><% if(filters.googleAuth) { %> +<% } %><% if (filters.googleAuth) { %> google: { clientID: process.env.GOOGLE_ID || 'id', clientSecret: process.env.GOOGLE_SECRET || 'secret', @@ -64,4 +64,4 @@ var all = { // ============================================== module.exports = _.merge( all, - require('./' + process.env.NODE_ENV + '.js') || {}); \ No newline at end of file + require('./' + process.env.NODE_ENV + '.js') || {}); diff --git a/app/templates/server/config/environment/production.js b/app/templates/server/config/environment/production.js index 1704df619..e0b77bf97 100644 --- a/app/templates/server/config/environment/production.js +++ b/app/templates/server/config/environment/production.js @@ -17,7 +17,8 @@ module.exports = { mongo: { uri: process.env.MONGOLAB_URI || process.env.MONGOHQ_URL || - process.env.OPENSHIFT_MONGODB_DB_URL+process.env.OPENSHIFT_APP_NAME || + process.env.OPENSHIFT_MONGODB_DB_URL + + process.env.OPENSHIFT_APP_NAME || 'mongodb://localhost/<%= _.slugify(appname) %>' } -}; \ No newline at end of file +}; diff --git a/app/templates/server/config/environment/test.js b/app/templates/server/config/environment/test.js index 711c98660..6ead6e1aa 100644 --- a/app/templates/server/config/environment/test.js +++ b/app/templates/server/config/environment/test.js @@ -7,4 +7,4 @@ module.exports = { mongo: { uri: 'mongodb://localhost/<%= _.slugify(appname) %>-test' } -}; \ No newline at end of file +}; diff --git a/app/templates/server/config/express.js b/app/templates/server/config/express.js index 2403780f1..463f637fd 100644 --- a/app/templates/server/config/express.js +++ b/app/templates/server/config/express.js @@ -30,8 +30,8 @@ module.exports = function(app) { app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); app.use(methodOverride()); - app.use(cookieParser()); - <% if (filters.auth) { %>app.use(passport.initialize());<% } %><% if (filters.twitterAuth) { %> + app.use(cookieParser());<% if (filters.auth) { %> + app.use(passport.initialize());<% } %><% if (filters.twitterAuth) { %> // Persist sessions with mongoStore // We need to enable sessions for passport twitter because its an oauth 1.0 strategy @@ -41,7 +41,7 @@ module.exports = function(app) { saveUninitialized: true, store: new mongoStore({ mongoose_connection: mongoose.connection }) })); - <% } %> +<% } %> if ('production' === env) { app.use(favicon(path.join(config.root, 'public', 'favicon.ico'))); app.use(express.static(path.join(config.root, 'public'))); diff --git a/app/templates/server/config/seed(mongoose).js b/app/templates/server/config/seed(mongoose).js index 6d56010b6..1f6945d8d 100644 --- a/app/templates/server/config/seed(mongoose).js +++ b/app/templates/server/config/seed(mongoose).js @@ -6,35 +6,40 @@ 'use strict'; var Thing = require('../api/thing/thing.model'); -<% if (filters.auth) { %> -var User = require('../api/user/user.model'); -<% } %> +<% if (filters.auth) { %>var User = require('../api/user/user.model');<% } %> Thing.find({}).removeAsync() .then(function() { Thing.create({ name : 'Development Tools', - info : 'Integration with popular tools such as Bower, Grunt, Karma, Mocha, JSHint, Node Inspector, Livereload, Protractor, Jade, Stylus, Sass, CoffeeScript, and Less.' + info : 'Integration with popular tools such as Bower, Grunt, Karma, ' + + 'Mocha, JSHint, Node Inspector, Livereload, Protractor, Jade, ' + + 'Stylus, Sass, CoffeeScript, and Less.' }, { name : 'Server and Client integration', - info : 'Built with a powerful and fun stack: MongoDB, Express, AngularJS, and Node.' + info : 'Built with a powerful and fun stack: MongoDB, Express, ' + + 'AngularJS, and Node.' }, { name : 'Smart Build System', - info : 'Build system ignores `spec` files, allowing you to keep tests alongside code. Automatic injection of scripts and styles into your index.html' - }, { + info : 'Build system ignores `spec` files, allowing you to keep ' + + 'tests alongside code. Automatic injection of scripts and ' + + 'styles into your index.html' + }, { name : 'Modular Structure', - info : 'Best practice client and server structures allow for more code reusability and maximum scalability' - }, { + info : 'Best practice client and server structures allow for more ' + + 'code reusability and maximum scalability' + }, { name : 'Optimized Build', - info : 'Build process packs up your templates as a single JavaScript payload, minifies your scripts/css/images, and rewrites asset names for caching.' - },{ + info : 'Build process packs up your templates as a single JavaScript ' + + 'payload, minifies your scripts/css/images, and rewrites asset ' + + 'names for caching.' + }, { name : 'Deployment Ready', - info : 'Easily deploy your app to Heroku or Openshift with the heroku and openshift subgenerators' + info : 'Easily deploy your app to Heroku or Openshift with the heroku ' + + 'and openshift subgenerators' }); }); - <% if (filters.auth) { %> - User.find({}).removeAsync() .then(function() { User.create({ @@ -49,8 +54,7 @@ User.find({}).removeAsync() email: 'admin@admin.com', password: 'admin' }, function() { - console.log('finished populating users'); - } - ); + console.log('finished populating users'); + }); }); -<% } %> +<% } %> \ No newline at end of file diff --git a/app/templates/server/config/socketio(socketio).js b/app/templates/server/config/socketio(socketio).js index 2fbbc07d6..446b49dff 100644 --- a/app/templates/server/config/socketio(socketio).js +++ b/app/templates/server/config/socketio(socketio).js @@ -13,7 +13,7 @@ function onDisconnect(socket) { // When the user connects.. perform this function onConnect(socket) { // When the client emits 'info', this listens and executes - socket.on('info', function (data) { + socket.on('info', function(data) { console.info('[%s] %s', socket.address, JSON.stringify(data, null, 2)); }); @@ -21,7 +21,7 @@ function onConnect(socket) { require('../api/thing/thing.socket').register(socket); } -module.exports = function (socketio) { +module.exports = function(socketio) { // socket.io (v1.x.x) is powered by debug. // In order to see all the debug output, set DEBUG (in server/config/local.env.js) to including the desired scope. // @@ -37,15 +37,16 @@ module.exports = function (socketio) { // handshake: true // })); - socketio.on('connection', function (socket) { - socket.address = socket.handshake.address !== null ? - socket.handshake.address.address + ':' + socket.handshake.address.port : - process.env.DOMAIN; + socketio.on('connection', function(socket) { + socket.address = + socket.handshake.address !== null ? + socket.handshake.address.address + ':' + socket.handshake.address.port : + process.env.DOMAIN; socket.connectedAt = new Date(); // Call onDisconnect. - socket.on('disconnect', function () { + socket.on('disconnect', function() { onDisconnect(socket); console.info('[%s] DISCONNECTED', socket.address); }); @@ -54,4 +55,4 @@ module.exports = function (socketio) { onConnect(socket); console.info('[%s] CONNECTED', socket.address); }); -}; \ No newline at end of file +}; diff --git a/app/templates/server/routes.js b/app/templates/server/routes.js index c2b5acb2e..fff0e5416 100644 --- a/app/templates/server/routes.js +++ b/app/templates/server/routes.js @@ -9,11 +9,11 @@ var errors = require('./components/errors'); module.exports = function(app) { // Insert routes below - app.use('/api/things', require('./api/thing')); - <% if (filters.auth) { %>app.use('/api/users', require('./api/user')); + app.use('/api/things', require('./api/thing'));<% if (filters.auth) { %> + app.use('/api/users', require('./api/user')); app.use('/auth', require('./auth')); - <% } %> +<% } %> // All undefined asset or api routes should return a 404 app.route('/:url(http://github.com/api|auth|components|app|bower_components|assets)/*') .get(errors[404]); diff --git a/endpoint/templates/index.js b/endpoint/templates/index.js index 03fdc9779..3f8c592a6 100644 --- a/endpoint/templates/index.js +++ b/endpoint/templates/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/endpoint/templates/index.spec.js b/endpoint/templates/index.spec.js index fd1086b15..ccd15ec7e 100644 --- a/endpoint/templates/index.spec.js +++ b/endpoint/templates/index.spec.js @@ -37,7 +37,9 @@ describe('<%= classedName %> API Router:', function() { describe('GET <%= route %>', function() { it('should route to <%= name %>.controller.index', function() { - routerStub.get.withArgs('/', '<%= name %>Ctrl.index').should.have.been.calledOnce; + routerStub.get + .withArgs('/', '<%= name %>Ctrl.index') + .should.have.been.calledOnce; }); });<% if(filters.mongoose) { %> @@ -45,7 +47,9 @@ describe('<%= classedName %> API Router:', function() { describe('GET <%= route %>/:id', function() { it('should route to <%= name %>.controller.show', function() { - routerStub.get.withArgs('/:id', '<%= name %>Ctrl.show').should.have.been.calledOnce; + routerStub.get + .withArgs('/:id', '<%= name %>Ctrl.show') + .should.have.been.calledOnce; }); }); @@ -53,7 +57,9 @@ describe('<%= classedName %> API Router:', function() { describe('POST <%= route %>', function() { it('should route to <%= name %>.controller.create', function() { - routerStub.post.withArgs('/', '<%= name %>Ctrl.create').should.have.been.calledOnce; + routerStub.post + .withArgs('/', '<%= name %>Ctrl.create') + .should.have.been.calledOnce; }); }); @@ -61,7 +67,9 @@ describe('<%= classedName %> API Router:', function() { describe('PUT <%= route %>/:id', function() { it('should route to <%= name %>.controller.update', function() { - routerStub.put.withArgs('/:id', '<%= name %>Ctrl.update').should.have.been.calledOnce; + routerStub.put + .withArgs('/:id', '<%= name %>Ctrl.update') + .should.have.been.calledOnce; }); }); @@ -69,7 +77,9 @@ describe('<%= classedName %> API Router:', function() { describe('PATCH <%= route %>/:id', function() { it('should route to <%= name %>.controller.update', function() { - routerStub.patch.withArgs('/:id', '<%= name %>Ctrl.update').should.have.been.calledOnce; + routerStub.patch + .withArgs('/:id', '<%= name %>Ctrl.update') + .should.have.been.calledOnce; }); }); @@ -77,7 +87,9 @@ describe('<%= classedName %> API Router:', function() { describe('DELETE <%= route %>/:id', function() { it('should route to <%= name %>.controller.destroy', function() { - routerStub.delete.withArgs('/:id', '<%= name %>Ctrl.destroy').should.have.been.calledOnce; + routerStub.delete + .withArgs('/:id', '<%= name %>Ctrl.destroy') + .should.have.been.calledOnce; }); });<% } %> diff --git a/endpoint/templates/name.controller.js b/endpoint/templates/name.controller.js index 87dd641de..9cdfb0fb0 100644 --- a/endpoint/templates/name.controller.js +++ b/endpoint/templates/name.controller.js @@ -1,27 +1,27 @@ -'use strict';<% if (filters.mongoose) { %> +'use strict';<% if(filters.mongoose) { %> var _ = require('lodash'); var <%= classedName %> = require('./<%= name %>.model'); -function handleError(res, statusCode){ +function handleError(res, statusCode) { statusCode = statusCode || 500; - return function(err){ + return function(err) { res.send(statusCode, err); }; } -function responseWithResult(res, statusCode){ +function responseWithResult(res, statusCode) { statusCode = statusCode || 200; - return function(entity){ - if(entity){ + return function(entity) { + if (entity) { return res.json(statusCode, entity); } }; } -function handleEntityNotFound(res){ - return function(entity){ - if(!entity){ +function handleEntityNotFound(res) { + return function(entity) { + if (!entity) { res.send(404); return null; } @@ -29,19 +29,19 @@ function handleEntityNotFound(res){ }; } -function saveUpdates(updates){ - return function(entity){ +function saveUpdates(updates) { + return function(entity) { var updated = _.merge(entity, updates); return updated.saveAsync() - .spread(function (updated) { + .spread(function(updated) { return updated; }); }; } -function removeEntity(res){ - return function (entity) { - if(entity){ +function removeEntity(res) { + return function(entity) { + if (entity) { return entity.removeAsync() .then(function() { return res.send(204); @@ -51,12 +51,12 @@ function removeEntity(res){ }<% } %> // Gets list of <%= name %>s from the DB. -exports.index = function(req, res) {<% if (!filters.mongoose) { %> +exports.index = function(req, res) {<% if(!filters.mongoose) { %> res.json([]);<% } if (filters.mongoose) { %> <%= classedName %>.findAsync() .then(responseWithResult(res)) .catch(handleError(res));<% } %> -};<% if (filters.mongoose) { %> +};<% if(filters.mongoose) { %> // Gets a single <%= name %> from the DB. exports.show = function(req, res) { @@ -75,7 +75,7 @@ exports.create = function(req, res) { // Updates an existing <%= name %> in the DB. exports.update = function(req, res) { - if(req.body._id) { + if (req.body._id) { delete req.body._id; } <%= classedName %>.findByIdAsync(req.params.id) diff --git a/endpoint/templates/name.integration.js b/endpoint/templates/name.integration.js index f168f1ca9..a377456a4 100644 --- a/endpoint/templates/name.integration.js +++ b/endpoint/templates/name.integration.js @@ -16,7 +16,9 @@ describe('<%= classedName %> API:', function() { .expect(200) .expect('Content-Type', /json/) .end(function(err, res) { - if (err) return done(err); + if (err) { + return done(err); + } <%= cameledName %>s = res.body; done(); }); @@ -39,7 +41,9 @@ describe('<%= classedName %> API:', function() { .expect(201) .expect('Content-Type', /json/) .end(function(err, res) { - if (err) return done(err); + if (err) { + return done(err); + } new<%= classedName %> = res.body; done(); }); @@ -61,7 +65,9 @@ describe('<%= classedName %> API:', function() { .expect(200) .expect('Content-Type', /json/) .end(function(err, res) { - if (err) return done(err); + if (err) { + return done(err); + } <%= cameledName %> = res.body; done(); }); @@ -91,7 +97,9 @@ describe('<%= classedName %> API:', function() { .expect(200) .expect('Content-Type', /json/) .end(function(err, res) { - if (err) return done(err); + if (err) { + return done(err); + } updated<%= classedName %> = res.body; done(); }); @@ -115,7 +123,9 @@ describe('<%= classedName %> API:', function() { .delete('<%= route %>/' + new<%= classedName %>._id) .expect(204) .end(function(err, res) { - if (err) return done(err); + if (err) { + return done(err); + } done(); }); }); @@ -125,7 +135,9 @@ describe('<%= classedName %> API:', function() { .delete('<%= route %>/' + new<%= classedName %>._id) .expect(404) .end(function(err, res) { - if (err) return done(err); + if (err) { + return done(err); + } done(); }); }); diff --git a/endpoint/templates/name.model(mongoose).js b/endpoint/templates/name.model(mongoose).js index 9b23d9d41..ac7f7f72a 100644 --- a/endpoint/templates/name.model(mongoose).js +++ b/endpoint/templates/name.model(mongoose).js @@ -1,7 +1,7 @@ 'use strict'; -var mongoose = require('mongoose-bird')(), - Schema = mongoose.Schema; +var mongoose = require('mongoose-bird')(); +var Schema = mongoose.Schema; var <%= classedName %>Schema = new Schema({ name: String, diff --git a/endpoint/templates/name.socket(socketio).js b/endpoint/templates/name.socket(socketio).js index aabdadeb8..260c80720 100644 --- a/endpoint/templates/name.socket(socketio).js +++ b/endpoint/templates/name.socket(socketio).js @@ -7,10 +7,10 @@ var <%= classedName %> = require('./<%= name %>.model'); exports.register = function(socket) { - <%= classedName %>.schema.post('save', function (doc) { + <%= classedName %>.schema.post('save', function(doc) { onSave(socket, doc); }); - <%= classedName %>.schema.post('remove', function (doc) { + <%= classedName %>.schema.post('remove', function(doc) { onRemove(socket, doc); }); }; @@ -21,4 +21,4 @@ function onSave(socket, doc, cb) { function onRemove(socket, doc, cb) { socket.emit('<%= name %>:remove', doc); -} \ No newline at end of file +} diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 7db1d4afe..9301c9332 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -206,6 +206,7 @@ describe('angular-fullstack generator', function () { '.gitattributes', '.gitignore', '.travis.yml', + '.jscs.json', '.yo-rc.json', 'Gruntfile.js', 'package.json', @@ -339,6 +340,10 @@ describe('angular-fullstack generator', function () { runTest('grunt test:client', this, done); }); + it('should pass jscs', function(done) { + runTest('grunt jscs', this, done); + }); + it('should pass lint', function(done) { runTest('grunt jshint', this, done); }); @@ -347,6 +352,10 @@ describe('angular-fullstack generator', function () { runTest('grunt test:server', this, done); }); + it('should pass jscs with generated endpoint', function(done) { + runTest('grunt jscs', this, done, 'foo'); + }); + it('should pass lint with generated endpoint', function(done) { runTest('grunt jshint', this, done, 'foo'); }); @@ -427,6 +436,10 @@ describe('angular-fullstack generator', function () { runTest('grunt test:client', this, done); }); + it('should pass jscs', function(done) { + runTest('grunt jscs', this, done); + }); + it('should pass lint', function(done) { runTest('grunt jshint', this, done); }); @@ -435,6 +448,10 @@ describe('angular-fullstack generator', function () { runTest('grunt test:server', this, done); }); + it('should pass jscs with generated endpoint', function(done) { + runTest('grunt jscs', this, done, 'foo'); + }); + it('should pass lint with generated snake-case endpoint', function(done) { runTest('grunt jshint', this, done, 'foo-bar'); }); @@ -486,6 +503,10 @@ describe('angular-fullstack generator', function () { runTest('grunt test:client', this, done); }); + it('should pass jscs', function(done) { + runTest('grunt jscs', this, done); + }); + it('should pass lint', function(done) { runTest('grunt jshint', this, done); }); @@ -494,6 +515,10 @@ describe('angular-fullstack generator', function () { runTest('grunt test:server', this, done); }); + it('should pass jscs with generated endpoint', function(done) { + runTest('grunt jscs', this, done, 'foo'); + }); + it('should pass lint with generated endpoint', function(done) { runTest('grunt jshint', this, done, 'foo'); }); @@ -544,6 +569,10 @@ describe('angular-fullstack generator', function () { runTest('grunt test:client', this, done); }); + it('should pass jscs', function(done) { + runTest('grunt jscs', this, done); + }); + it('should pass lint', function(done) { runTest('grunt jshint', this, done); }); From 9cdcc90a19dcef98bd30a1b80ab96c4f47684f2d Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sun, 28 Sep 2014 16:08:58 -0600 Subject: [PATCH 0046/1357] fix(server): server should launch in dev mode if production env var is not specified fixes #590 --- app/templates/Gruntfile.js | 30 +++++++++++++------------- app/templates/server/config/express.js | 6 +++--- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 224e84c66..274aacbb9 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -287,10 +287,10 @@ module.exports = function (grunt) { dist: { files: { src: [ - '<%%= yeoman.dist %>/public/{,*/}*.js', - '<%%= yeoman.dist %>/public/{,*/}*.css', - '<%%= yeoman.dist %>/public/assets/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}', - '<%%= yeoman.dist %>/public/assets/fonts/*' + '<%%= yeoman.dist %>/client/{,*/}*.js', + '<%%= yeoman.dist %>/client/{,*/}*.css', + '<%%= yeoman.dist %>/client/assets/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}', + '<%%= yeoman.dist %>/client/assets/fonts/*' ] } } @@ -302,19 +302,19 @@ module.exports = function (grunt) { useminPrepare: { html: ['<%%= yeoman.client %>/index.html'], options: { - dest: '<%%= yeoman.dist %>/public' + dest: '<%%= yeoman.dist %>/client' } }, // Performs rewrites based on rev and the useminPrepare configuration usemin: { - html: ['<%%= yeoman.dist %>/public/{,*/}*.html'], - css: ['<%%= yeoman.dist %>/public/{,*/}*.css'], - js: ['<%%= yeoman.dist %>/public/{,*/}*.js'], + html: ['<%%= yeoman.dist %>/client/{,*/}*.html'], + css: ['<%%= yeoman.dist %>/client/{,*/}*.css'], + js: ['<%%= yeoman.dist %>/client/{,*/}*.js'], options: { assetsDirs: [ - '<%%= yeoman.dist %>/public', - '<%%= yeoman.dist %>/public/assets/images' + '<%%= yeoman.dist %>/client', + '<%%= yeoman.dist %>/client/assets/images' ], // This is so we update image references in our ng-templates patterns: { @@ -332,7 +332,7 @@ module.exports = function (grunt) { expand: true, cwd: '<%%= yeoman.client %>/assets/images', src: '{,*/}*.{png,jpg,jpeg,gif}', - dest: '<%%= yeoman.dist %>/public/assets/images' + dest: '<%%= yeoman.dist %>/client/assets/images' }] } }, @@ -343,7 +343,7 @@ module.exports = function (grunt) { expand: true, cwd: '<%%= yeoman.client %>/assets/images', src: '{,*/}*.svg', - dest: '<%%= yeoman.dist %>/public/assets/images' + dest: '<%%= yeoman.dist %>/client/assets/images' }] } }, @@ -392,7 +392,7 @@ module.exports = function (grunt) { // Replace Google CDN references cdnify: { dist: { - html: ['<%%= yeoman.dist %>/public/*.html'] + html: ['<%%= yeoman.dist %>/client/*.html'] } }, @@ -403,7 +403,7 @@ module.exports = function (grunt) { expand: true, dot: true, cwd: '<%%= yeoman.client %>', - dest: '<%%= yeoman.dist %>/public', + dest: '<%%= yeoman.dist %>/client', src: [ '*.{ico,png,txt}', '.htaccess', @@ -415,7 +415,7 @@ module.exports = function (grunt) { }, { expand: true, cwd: '.tmp/images', - dest: '<%%= yeoman.dist %>/public/assets/images', + dest: '<%%= yeoman.dist %>/client/assets/images', src: ['generated/*'] }, { expand: true, diff --git a/app/templates/server/config/express.js b/app/templates/server/config/express.js index 463f637fd..67e5398f9 100644 --- a/app/templates/server/config/express.js +++ b/app/templates/server/config/express.js @@ -43,9 +43,9 @@ module.exports = function(app) { })); <% } %> if ('production' === env) { - app.use(favicon(path.join(config.root, 'public', 'favicon.ico'))); - app.use(express.static(path.join(config.root, 'public'))); - app.set('appPath', config.root + '/public'); + app.use(favicon(path.join(config.root, 'client', 'favicon.ico'))); + app.use(express.static(path.join(config.root, 'client'))); + app.set('appPath', config.root + '/client'); app.use(morgan('dev')); } From a5edbcdf1a9a7cbb13511e908fdf8df1abbdacb2 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sun, 28 Sep 2014 16:54:34 -0600 Subject: [PATCH 0047/1357] fix test framework options when scaffolding with existing project --- Gruntfile.js | 1 + app/index.js | 27 +++++++++++++++++++-------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 8edbe3ccd..f204733b5 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -139,6 +139,7 @@ module.exports = function (grunt) { bootstrap: true, uibootstrap: true, mongoose: true, + testing: 'jasmine', auth: true, oauth: ['googleAuth', 'twitterAuth'], socketio: true diff --git a/app/index.js b/app/index.js index 7dcee4d55..81c9e40b7 100644 --- a/app/index.js +++ b/app/index.js @@ -52,15 +52,23 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ }], function (answers) { this.skipConfig = answers.skipConfig; + this.filters = this._.defaults(this.config.get('filters'), { + bootstrap: true, + uibootstrap: true, + jasmine: true + }); + // NOTE: temp(?) fix for #403 - if(typeof this.oauth==='undefined') { + if(typeof this.filters.oauth==='undefined') { var strategies = Object.keys(this.filters).filter(function(key) { return key.match(/Auth$/) && key; }); - if(strategies.length) this.config.set('oauth', true); + if(strategies.length) this.filters.oauth = true; } + this.config.forceSave(); + cb(); }.bind(this)); } else { @@ -228,9 +236,17 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ } }], function (answers) { this.filters[answers.testing] = true; - if (this.filters.mocha) { + if (answers.testing === 'mocha') { + this.filters.jasmine = false; + this.filters.should = false; + this.filters.expect = false; this.filters[answers.chai] = true; } + if (answers.testing === 'jasmine') { + this.filters.mocha = false; + this.filters.should = false; + this.filters.expect = false; + } cb(); }.bind(this)); @@ -289,11 +305,6 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ }, ngModules: function() { - this.filters = this._.defaults(this.config.get('filters'), { - bootstrap: true, - uibootstrap: true - }); - var angModules = [ "'ngCookies'", "'ngResource'", From 639131387ce08032d51d1698c86baab709d1f8a7 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sun, 28 Sep 2014 17:21:53 -0600 Subject: [PATCH 0048/1357] add test for #403 --- test/fixtures/.yo-rc.json | 3 ++- test/test-file-creation.js | 24 +++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/test/fixtures/.yo-rc.json b/test/fixtures/.yo-rc.json index b4b338ac4..9ab655e54 100644 --- a/test/fixtures/.yo-rc.json +++ b/test/fixtures/.yo-rc.json @@ -13,7 +13,8 @@ "uirouter": true, "socketio": true, "mongoose": true, - "auth": true + "auth": true, + "googleAuth": true } } } \ No newline at end of file diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 9301c9332..c8db89456 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -389,12 +389,34 @@ describe('angular-fullstack generator', function () { gen.run({}, function () { helpers.assertFile([ 'client/app/main/main.less', - 'client/app/main/main.coffee' + 'client/app/main/main.coffee', + 'server/auth/google/passport.js' ]); done(); }); }); + it('should add oauth option if existing config had oauth strategy selected', function(done) { + this.timeout(60000); + fs.copySync(__dirname + '/fixtures/.yo-rc.json', __dirname + '/temp/.yo-rc.json'); + var gen = helpers.createGenerator('angular-fullstack:app', [ + '../../app', + [ + helpers.createDummyGenerator(), + 'ng-component:app' + ] + ]); + gen.options['skip-install'] = true; + helpers.mockPrompt(gen, { + skipConfig: true + }); + gen.run({}, function () { + var yoConfig = require(__dirname + '/temp/.yo-rc.json'); + expect(yoConfig['generator-angular-fullstack'].filters.oauth).to.be.true; + done(); + }); + }); + it('should generate expected files', function (done) { gen.run({}, function () { helpers.assertFile(genFiles(defaultOptions)); From 92858565aaa67b95ebd0d082aad308b2956f934c Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sun, 28 Sep 2014 17:46:02 -0600 Subject: [PATCH 0049/1357] test(gen): add tests for running the e2e tests in production mode --- app/templates/Gruntfile.js | 41 +++++++++++++------- app/templates/e2e/main/main.spec(jasmine).js | 2 +- app/templates/e2e/main/main.spec(mocha).js | 2 +- test/test-file-creation.js | 16 ++++++++ 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 224e84c66..5adde704c 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -856,20 +856,33 @@ module.exports = function (grunt) { } else if (target === 'e2e') { - return grunt.task.run([ - 'clean:server', - 'env:all', - 'env:test',<% if (filters.stylus) { %> - 'injector:stylus', <% } %><% if (filters.less) { %> - 'injector:less', <% } %><% if (filters.sass) { %> - 'injector:sass', <% } %> - 'concurrent:test', - 'injector', - 'wiredep', - 'autoprefixer', - 'express:dev', - 'protractor' - ]); + + if (option === 'prod') { + return grunt.task.run([ + 'build', + 'env:all', + 'env:prod', + 'express:prod', + 'protractor' + ]); + } + + else { + return grunt.task.run([ + 'clean:server', + 'env:all', + 'env:test',<% if (filters.stylus) { %> + 'injector:stylus', <% } %><% if (filters.less) { %> + 'injector:less', <% } %><% if (filters.sass) { %> + 'injector:sass', <% } %> + 'concurrent:test', + 'injector', + 'wiredep', + 'autoprefixer', + 'express:dev', + 'protractor' + ]); + } } else if (target === 'coverage') { diff --git a/app/templates/e2e/main/main.spec(jasmine).js b/app/templates/e2e/main/main.spec(jasmine).js index 61745a8de..59456e4e8 100644 --- a/app/templates/e2e/main/main.spec(jasmine).js +++ b/app/templates/e2e/main/main.spec(jasmine).js @@ -10,7 +10,7 @@ describe('Main View', function() { it('should include jumbotron with correct data', function() { expect(page.h1El.getText()).toBe('\'Allo, \'Allo!'); - expect(page.imgEl.getAttribute('src')).toMatch(/assets\/images\/yeoman.png$/); + expect(page.imgEl.getAttribute('src')).toMatch(/yeoman.png$/); expect(page.imgEl.getAttribute('alt')).toBe('I\'m Yeoman'); }); }); diff --git a/app/templates/e2e/main/main.spec(mocha).js b/app/templates/e2e/main/main.spec(mocha).js index 1962ba765..e734af3a0 100644 --- a/app/templates/e2e/main/main.spec(mocha).js +++ b/app/templates/e2e/main/main.spec(mocha).js @@ -10,7 +10,7 @@ describe('Main View', function() { it('should include jumbotron with correct data', function() { <%= does("page.h1El.getText()") %>.eventually.equal('\'Allo, \'Allo!'); - <%= does("page.imgEl.getAttribute('src')") %>.eventually.match(/assets\/images\/yeoman.png$/); + <%= does("page.imgEl.getAttribute('src')") %>.eventually.match(/yeoman.png$/); <%= does("page.imgEl.getAttribute('alt')") %>.eventually.equal('I\'m Yeoman'); }); }); diff --git a/test/test-file-creation.js b/test/test-file-creation.js index c8db89456..c47173f4a 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -433,6 +433,10 @@ describe('angular-fullstack generator', function () { it('should run e2e tests successfully', function(done) { runTest('grunt test:e2e', this, done, 240000); }); + + it('should run e2e tests successfully for production app', function(done) { + runTest('grunt test:e2e:prod', this, done, 240000); + }); }); describe('with other preprocessors and oauth', function() { @@ -498,6 +502,10 @@ describe('angular-fullstack generator', function () { it('should run e2e tests successfully', function(done) { runTest('grunt test:e2e', this, done, 240000); }); + + it('should run e2e tests successfully for production app', function(done) { + runTest('grunt test:e2e:prod', this, done, 240000); + }); }); describe('with other preprocessors and no server options', function() { @@ -565,6 +573,10 @@ describe('angular-fullstack generator', function () { it('should run e2e tests successfully', function(done) { runTest('grunt test:e2e', this, done, 240000); }); + + it('should run e2e tests successfully for production app', function(done) { + runTest('grunt test:e2e:prod', this, done, 240000); + }); }); describe('with no preprocessors and no server options', function() { @@ -619,6 +631,10 @@ describe('angular-fullstack generator', function () { it('should run e2e tests successfully', function(done) { runTest('grunt test:e2e', this, done, 240000); }); + + it('should run e2e tests successfully for production app', function(done) { + runTest('grunt test:e2e:prod', this, done, 240000); + }); }); }); }); From add986f584c0081843db4d6c6966eaebf631e871 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Sun, 28 Sep 2014 18:59:54 -0600 Subject: [PATCH 0050/1357] remove production e2e tests because issues with node 0.11.x --- test/test-file-creation.js | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/test/test-file-creation.js b/test/test-file-creation.js index c47173f4a..5a239790f 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -434,9 +434,9 @@ describe('angular-fullstack generator', function () { runTest('grunt test:e2e', this, done, 240000); }); - it('should run e2e tests successfully for production app', function(done) { - runTest('grunt test:e2e:prod', this, done, 240000); - }); + //it('should run e2e tests successfully for production app', function(done) { + // runTest('grunt test:e2e:prod', this, done, 240000); + //}); }); describe('with other preprocessors and oauth', function() { @@ -503,9 +503,6 @@ describe('angular-fullstack generator', function () { runTest('grunt test:e2e', this, done, 240000); }); - it('should run e2e tests successfully for production app', function(done) { - runTest('grunt test:e2e:prod', this, done, 240000); - }); }); describe('with other preprocessors and no server options', function() { @@ -574,9 +571,6 @@ describe('angular-fullstack generator', function () { runTest('grunt test:e2e', this, done, 240000); }); - it('should run e2e tests successfully for production app', function(done) { - runTest('grunt test:e2e:prod', this, done, 240000); - }); }); describe('with no preprocessors and no server options', function() { @@ -632,9 +626,6 @@ describe('angular-fullstack generator', function () { runTest('grunt test:e2e', this, done, 240000); }); - it('should run e2e tests successfully for production app', function(done) { - runTest('grunt test:e2e:prod', this, done, 240000); - }); }); }); }); From 68b34f3e9333760a7cbdaa8659d43ac3feb6aee2 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Wed, 1 Oct 2014 19:22:05 -0600 Subject: [PATCH 0051/1357] add production e2e tests back in, only test against node 0.10.x closes #604 --- .travis.yml | 1 - test/test-file-creation.js | 18 +++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 598a4b2ae..6646824d6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: node_js node_js: - '0.10' - - '0.11.13' env: global: - SAUCE_USERNAME=fullstack_ci diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 5a239790f..bdb479829 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -434,9 +434,9 @@ describe('angular-fullstack generator', function () { runTest('grunt test:e2e', this, done, 240000); }); - //it('should run e2e tests successfully for production app', function(done) { - // runTest('grunt test:e2e:prod', this, done, 240000); - //}); + it('should run e2e tests successfully for production app', function(done) { + runTest('grunt test:e2e:prod', this, done, 240000); + }); }); describe('with other preprocessors and oauth', function() { @@ -503,6 +503,10 @@ describe('angular-fullstack generator', function () { runTest('grunt test:e2e', this, done, 240000); }); + it('should run e2e tests successfully for production app', function(done) { + runTest('grunt test:e2e:prod', this, done, 240000); + }); + }); describe('with other preprocessors and no server options', function() { @@ -571,6 +575,10 @@ describe('angular-fullstack generator', function () { runTest('grunt test:e2e', this, done, 240000); }); + it('should run e2e tests successfully for production app', function(done) { + runTest('grunt test:e2e:prod', this, done, 240000); + }); + }); describe('with no preprocessors and no server options', function() { @@ -626,6 +634,10 @@ describe('angular-fullstack generator', function () { runTest('grunt test:e2e', this, done, 240000); }); + it('should run e2e tests successfully for production app', function(done) { + runTest('grunt test:e2e:prod', this, done, 240000); + }); + }); }); }); From a84f644dd95b32287e7904efbee3c6cdb624c427 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Wed, 1 Oct 2014 20:34:47 -0600 Subject: [PATCH 0052/1357] test(gen): fix grunt test false positives #closes 606 --- test/test-file-creation.js | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/test/test-file-creation.js b/test/test-file-creation.js index bdb479829..e2fdd0e42 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -90,25 +90,17 @@ describe('angular-fullstack generator', function () { self.timeout(timeout || 60000); var execFn = function() { - exec(cmd, function(error, stdout, stderr) { - switch(cmd) { - case 'grunt jshint': - case 'grunt jscs': - expect(stdout).to.contain('Done, without errors.'); - break; - case 'grunt test:client': - case 'grunt test:e2e': - expect(stdout, 'Client tests failed \n' + stdout).to.contain('Done, without errors.'); - break; - case 'grunt test:server': - expect(stdout, 'Server tests failed (do you have mongoDB running?) \n' + stdout).to.contain('Done, without errors.'); - break; - default: - expect(stderr).to.be.empty; + var cmdCode; + var cp = exec(cmd, function(error, stdout, stderr) { + if(cmdCode !== 0) { + console.error(stdout); + throw new Error('Error running command: ' + cmd); } - cb(); }); + cp.on('exit', function (code) { + cmdCode = code; + }); }; if (endpoint) { From 95152ceb2f20762e2f3a8840f31efb2aa64f81b5 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Wed, 1 Oct 2014 21:01:00 -0600 Subject: [PATCH 0053/1357] test(gen): add grunt test:fast task to generator, for skipping e2e tests --- Gruntfile.js | 18 ++++++++++++ package.json | 1 + test/test-file-creation.js | 56 ++++++++++++++++++++++---------------- 3 files changed, 51 insertions(+), 24 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index f204733b5..c81bffa5c 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -58,6 +58,11 @@ module.exports = function (grunt) { }, all: ['Gruntfile.js', '*/index.js'] }, + env: { + fast: { + SKIP_E2E: true + } + }, mochaTest: { test: { src: [ @@ -252,6 +257,19 @@ module.exports = function (grunt) { 'installFixtures', 'mochaTest' ]); + grunt.registerTask('test', function(target, option) { + if (target === 'fast') { + grunt.task.run([ + 'env:fast' + ]); + } + + return grunt.task.run([ + 'updateFixtures', + 'installFixtures', + 'mochaTest' + ]) + }); grunt.registerTask('demo', [ 'clean:demo', diff --git a/package.json b/package.json index ec61432c7..c9e55b21b 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "grunt-contrib-clean": "^0.6.0", "grunt-contrib-jshint": "^0.10.0", "grunt-conventional-changelog": "~1.0.0", + "grunt-env": "^0.4.1", "grunt-mocha-test": "^0.11.0", "grunt-release": "~0.6.0", "load-grunt-tasks": "~0.2.0", diff --git a/test/test-file-creation.js b/test/test-file-creation.js index e2fdd0e42..bd3a3b146 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -422,13 +422,15 @@ describe('angular-fullstack generator', function () { }); }); - it('should run e2e tests successfully', function(done) { - runTest('grunt test:e2e', this, done, 240000); - }); + if(!process.env.SKIP_E2E) { + it('should run e2e tests successfully', function(done) { + runTest('grunt test:e2e', this, done, 240000); + }); - it('should run e2e tests successfully for production app', function(done) { - runTest('grunt test:e2e:prod', this, done, 240000); - }); + it('should run e2e tests successfully for production app', function(done) { + runTest('grunt test:e2e:prod', this, done, 240000); + }); + } }); describe('with other preprocessors and oauth', function() { @@ -491,13 +493,15 @@ describe('angular-fullstack generator', function () { }); }); - it('should run e2e tests successfully', function(done) { - runTest('grunt test:e2e', this, done, 240000); - }); + if(!process.env.SKIP_E2E) { + it('should run e2e tests successfully', function (done) { + runTest('grunt test:e2e', this, done, 240000); + }); - it('should run e2e tests successfully for production app', function(done) { - runTest('grunt test:e2e:prod', this, done, 240000); - }); + it('should run e2e tests successfully for production app', function (done) { + runTest('grunt test:e2e:prod', this, done, 240000); + }); + } }); @@ -563,13 +567,15 @@ describe('angular-fullstack generator', function () { }); }); - it('should run e2e tests successfully', function(done) { - runTest('grunt test:e2e', this, done, 240000); - }); + if(!process.env.SKIP_E2E) { + it('should run e2e tests successfully', function (done) { + runTest('grunt test:e2e', this, done, 240000); + }); - it('should run e2e tests successfully for production app', function(done) { - runTest('grunt test:e2e:prod', this, done, 240000); - }); + it('should run e2e tests successfully for production app', function (done) { + runTest('grunt test:e2e:prod', this, done, 240000); + }); + } }); @@ -622,13 +628,15 @@ describe('angular-fullstack generator', function () { }); }); - it('should run e2e tests successfully', function(done) { - runTest('grunt test:e2e', this, done, 240000); - }); + if(!process.env.SKIP_E2E) { + it('should run e2e tests successfully', function (done) { + runTest('grunt test:e2e', this, done, 240000); + }); - it('should run e2e tests successfully for production app', function(done) { - runTest('grunt test:e2e:prod', this, done, 240000); - }); + it('should run e2e tests successfully for production app', function (done) { + runTest('grunt test:e2e:prod', this, done, 240000); + }); + } }); }); From 09b4b601b8ddae9d9cd66e0f10ae285210642a56 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Wed, 1 Oct 2014 21:18:18 -0600 Subject: [PATCH 0054/1357] comment out e2e production tests again because of flaky results --- test/test-file-creation.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/test-file-creation.js b/test/test-file-creation.js index bd3a3b146..f9ab7183b 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -498,9 +498,9 @@ describe('angular-fullstack generator', function () { runTest('grunt test:e2e', this, done, 240000); }); - it('should run e2e tests successfully for production app', function (done) { - runTest('grunt test:e2e:prod', this, done, 240000); - }); + //it('should run e2e tests successfully for production app', function (done) { + // runTest('grunt test:e2e:prod', this, done, 240000); + //}); } }); @@ -572,9 +572,9 @@ describe('angular-fullstack generator', function () { runTest('grunt test:e2e', this, done, 240000); }); - it('should run e2e tests successfully for production app', function (done) { - runTest('grunt test:e2e:prod', this, done, 240000); - }); + //it('should run e2e tests successfully for production app', function (done) { + // runTest('grunt test:e2e:prod', this, done, 240000); + //}); } }); @@ -633,9 +633,9 @@ describe('angular-fullstack generator', function () { runTest('grunt test:e2e', this, done, 240000); }); - it('should run e2e tests successfully for production app', function (done) { - runTest('grunt test:e2e:prod', this, done, 240000); - }); + //it('should run e2e tests successfully for production app', function (done) { + // runTest('grunt test:e2e:prod', this, done, 240000); + //}); } }); From 499bc8db0117e8866b021f43b632936f63410b87 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Wed, 1 Oct 2014 21:39:55 -0600 Subject: [PATCH 0055/1357] missed one test that should have been commented out --- test/test-file-creation.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test-file-creation.js b/test/test-file-creation.js index f9ab7183b..99f5c28f8 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -427,9 +427,9 @@ describe('angular-fullstack generator', function () { runTest('grunt test:e2e', this, done, 240000); }); - it('should run e2e tests successfully for production app', function(done) { - runTest('grunt test:e2e:prod', this, done, 240000); - }); + //it('should run e2e tests successfully for production app', function(done) { + // runTest('grunt test:e2e:prod', this, done, 240000); + //}); } }); From f29e907d4388e8a615b61077984c00c9f202820a Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Thu, 2 Oct 2014 21:25:04 -0600 Subject: [PATCH 0056/1357] fix appPath for serving index.html --- app/templates/server/config/express.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/templates/server/config/express.js b/app/templates/server/config/express.js index 67e5398f9..f44999c1e 100644 --- a/app/templates/server/config/express.js +++ b/app/templates/server/config/express.js @@ -42,18 +42,18 @@ module.exports = function(app) { store: new mongoStore({ mongoose_connection: mongoose.connection }) })); <% } %> + app.set('appPath', path.join(config.root, 'client')); + if ('production' === env) { app.use(favicon(path.join(config.root, 'client', 'favicon.ico'))); - app.use(express.static(path.join(config.root, 'client'))); - app.set('appPath', config.root + '/client'); + app.use(express.static(app.get('appPath'))); app.use(morgan('dev')); } if ('development' === env || 'test' === env) { app.use(require('connect-livereload')()); app.use(express.static(path.join(config.root, '.tmp'))); - app.use(express.static(path.join(config.root, 'client'))); - app.set('appPath', 'client'); + app.use(express.static(app.get('appPath'))); app.use(morgan('dev')); app.use(errorHandler()); // Error handler - has to be last } From 8c9f0f934b4567b646ef88578de0c6adfea15eb1 Mon Sep 17 00:00:00 2001 From: gintsgints Date: Sun, 28 Sep 2014 12:33:35 +0300 Subject: [PATCH 0057/1357] test(gen): use path.normalize to be windows aware - change function assertOnlyFiles to use a different local variable from global module name - path. - show expected files when a test fails - use path.normalize before search in the array Closes #601 --- test/test-file-creation.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 99f5c28f8..2fef6a3c9 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -42,20 +42,20 @@ describe('angular-fullstack generator', function () { * * @param {Array} expectedFiles - array of files * @param {Function} done - callback(error{Error}) - * @param {String} path - top level path to assert files at (optional) + * @param {String} topLevelPath - top level path to assert files at (optional) * @param {Array} skip - array of paths to skip/ignore (optional) * */ - function assertOnlyFiles(expectedFiles, done, path, skip) { - path = path || './'; + function assertOnlyFiles(expectedFiles, done, topLevelPath, skip) { + topLevelPath = topLevelPath || './'; skip = skip || ['node_modules', 'client/bower_components']; - recursiveReadDir(path, skip, function(err, actualFiles) { + recursiveReadDir(topLevelPath, skip, function(err, actualFiles) { if (err) { return done(err); } var files = actualFiles.concat(); expectedFiles.forEach(function(file, i) { - var index = files.indexOf(file); + var index = files.indexOf(path.normalize(file)); if (index >= 0) { files.splice(index, 1); } @@ -63,7 +63,7 @@ describe('angular-fullstack generator', function () { if (files.length !== 0) { err = new Error('unexpected files found'); - err.expected = ''; + err.expected = expectedFiles.join('\n'); err.actual = files.join('\n'); return done(err); } From 6a196e21036dead1046794a7be4a309832a552bd Mon Sep 17 00:00:00 2001 From: Thiago Sigrist Date: Wed, 22 Oct 2014 20:03:04 -0200 Subject: [PATCH 0058/1357] fix(deps): use angular ~1.2 before migrated to 1.3 Change angular version spec from ">=1.2.*" to "~1.2" to ensure generator tests run before migration to 1.3 is completed. Closes #654. --- app/templates/_bower.json | 14 +++++++------- test/test-file-creation.js | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/app/templates/_bower.json b/app/templates/_bower.json index 8d2e66a8a..4f9167ed6 100644 --- a/app/templates/_bower.json +++ b/app/templates/_bower.json @@ -2,15 +2,15 @@ "name": "<%= _.slugify(_.humanize(appname)) %>", "version": "0.0.0", "dependencies": { - "angular": ">=1.2.*", + "angular": "~1.2", "json3": "~3.3.1", "es5-shim": "~3.0.1",<% if(filters.bootstrap) { %><% if (filters.sass) { %> "bootstrap-sass-official": "~3.1.1",<% } %> "bootstrap": "~3.1.1",<% } %> - "angular-resource": ">=1.2.*", - "angular-cookies": ">=1.2.*", - "angular-sanitize": ">=1.2.*",<% if (filters.ngroute) { %> - "angular-route": ">=1.2.*",<% } %><% if (filters.uibootstrap) { %> + "angular-resource": "~1.2", + "angular-cookies": "~1.2", + "angular-sanitize": "~1.2",<% if (filters.ngroute) { %> + "angular-route": "~1.2",<% } %><% if (filters.uibootstrap) { %> "angular-bootstrap": "~0.11.0",<% } %> "font-awesome": ">=4.1.0", "lodash": "~2.4.1"<% if (filters.socketio) { %>, @@ -18,7 +18,7 @@ "angular-ui-router": "~0.2.10"<% } %> }, "devDependencies": { - "angular-mocks": ">=1.2.*", - "angular-scenario": ">=1.2.*" + "angular-mocks": "~1.2", + "angular-scenario": "~1.2" } } diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 2fef6a3c9..6164b690b 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -314,6 +314,41 @@ describe('angular-fullstack generator', function () { }.bind(this)); }); + describe('making sure test fixtures are present', function() { + + it('should have package.json in fixtures', function() { + helpers.assertFile([ + path.join(__dirname, 'fixtures', 'package.json') + ]); + }); + + it('should have bower.json in fixtures', function() { + helpers.assertFile([ + path.join(__dirname, 'fixtures', 'bower.json') + ]); + }); + + it('should have all npm packages in fixtures/node_modules', function() { + var packageJson = require('./fixtures/package.json'); + var deps = Object.keys(packageJson.dependencies); + deps = deps.concat(Object.keys(packageJson.devDependencies)); + deps = deps.map(function(dep) { + return path.join(__dirname, 'fixtures', 'node_modules', dep); + }); + helpers.assertFile(deps); + }); + + it('should have all bower packages in fixtures/bower_components', function() { + var bowerJson = require('./fixtures/bower.json'); + var deps = Object.keys(bowerJson.dependencies); + deps = deps.concat(Object.keys(bowerJson.devDependencies)); + deps = deps.map(function(dep) { + return path.join(__dirname, 'fixtures', 'bower_components', dep); + }); + helpers.assertFile(deps); + }); + }); + describe('running app', function() { beforeEach(function() { From c90d7621b8f17f6e74f8a59f02fd78a8fcf628aa Mon Sep 17 00:00:00 2001 From: Jason Travis Date: Mon, 3 Nov 2014 20:38:38 -0700 Subject: [PATCH 0059/1357] fix(app): missing event.preventDefault --- app/templates/client/app/app(js).js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/templates/client/app/app(js).js b/app/templates/client/app/app(js).js index eef485d7c..c8850ed07 100644 --- a/app/templates/client/app/app(js).js +++ b/app/templates/client/app/app(js).js @@ -48,8 +48,9 @@ angular.module('<%= scriptAppName %>', [<%= angularModules %>]) $rootScope.$on(<% if(filters.ngroute) { %>'$routeChangeStart'<% } %><% if(filters.uirouter) { %>'$stateChangeStart'<% } %>, function (event, next) { Auth.isLoggedInAsync(function(loggedIn) { if (next.authenticate && !loggedIn) { + event.preventDefault(); $location.path('/login'); } }); }); - })<% } %>; \ No newline at end of file + })<% } %>; From dedf46c7a0664d5ea5a9f0686cbfa5593fdbc6d1 Mon Sep 17 00:00:00 2001 From: Vasil Velichkov Date: Wed, 26 Nov 2014 02:05:16 +0200 Subject: [PATCH 0060/1357] fix(openshift): fix processing of rhc app show output rhc returns the following text when application is not found $ rhc app show test Application 'test' not found. --- openshift/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openshift/index.js b/openshift/index.js index 518806b08..7929c0e09 100644 --- a/openshift/index.js +++ b/openshift/index.js @@ -107,7 +107,7 @@ Generator.prototype.rhcAppShow = function rhcAppShow() { this.abort = true; } // No remote found - else if (stdout.search('not found.') < 0) { + else if (stdout.search('not found.') >= 0) { console.log('No existing app found.'); } // Error From 943120e04c454abf2e0e6afc7965318d75c006b0 Mon Sep 17 00:00:00 2001 From: Thiago Sigrist Date: Wed, 26 Nov 2014 10:50:22 -0200 Subject: [PATCH 0061/1357] feat(server): add support for sequelize Closes #414. --- app/index.js | 55 +++- app/templates/_package.json | 8 +- .../signup/signup.controller(coffee).coffee | 10 +- .../signup/signup.controller(js).js | 12 +- .../app/main/main.controller(coffee).coffee | 2 +- .../client/app/main/main.controller(js).js | 2 +- .../login/login.spec(jasmine).js | 11 +- .../account(auth)/login/login.spec(mocha).js | 14 +- .../logout/logout.spec(jasmine).js | 11 +- .../logout/logout.spec(mocha).js | 14 +- .../signup/signup.spec(jasmine).js | 8 +- .../signup/signup.spec(mocha).js | 11 +- app/templates/protractor.conf.js | 4 +- app/templates/server/api/thing/index.js | 2 +- app/templates/server/api/thing/index.spec.js | 6 +- ...troller.js => thing.controller(models).js} | 78 +++--- .../api/thing/thing.controller(noModels).js | 38 +++ .../server/api/thing/thing.integration.js | 6 +- ...ose).js => thing.model(mongooseModels).js} | 0 .../api/thing/thing.model(sequelizeModels).js | 15 ++ .../api/thing/thing.socket(socketio).js | 21 +- .../server/api/user(auth)/user.controller.js | 65 ++++- .../server/api/user(auth)/user.integration.js | 25 +- ...model.js => user.model(mongooseModels).js} | 0 .../user(auth)/user.model(sequelizeModels).js | 235 ++++++++++++++++++ ....js => user.model.spec(mongooseModels).js} | 0 .../user.model.spec(sequelizeModels).js | 52 ++++ app/templates/server/app.js | 31 ++- .../server/auth(auth)/auth.service.js | 16 +- .../facebook(facebookAuth)/passport.js | 52 ++-- .../auth(auth)/google(googleAuth)/passport.js | 50 ++-- app/templates/server/auth(auth)/index.js | 5 +- .../server/auth(auth)/local/passport.js | 33 ++- .../twitter(twitterAuth)/passport.js | 49 ++-- .../server/config/environment/development.js | 10 + .../server/config/environment/test.js | 10 + app/templates/server/config/express.js | 10 +- .../{seed(mongoose).js => seed(models).js} | 36 ++- .../server/sqldb(sequelize)/index.js | 35 +++ endpoint/index.js | 42 ++++ endpoint/templates/name.model(sequelize).js | 15 ++ endpoint/templates/name.socket(socketio).js | 21 +- test/test-file-creation.js | 94 ++++++- 43 files changed, 974 insertions(+), 240 deletions(-) rename app/templates/server/api/thing/{thing.controller.js => thing.controller(models).js} (52%) create mode 100644 app/templates/server/api/thing/thing.controller(noModels).js rename app/templates/server/api/thing/{thing.model(mongoose).js => thing.model(mongooseModels).js} (100%) create mode 100644 app/templates/server/api/thing/thing.model(sequelizeModels).js rename app/templates/server/api/user(auth)/{user.model.js => user.model(mongooseModels).js} (100%) create mode 100644 app/templates/server/api/user(auth)/user.model(sequelizeModels).js rename app/templates/server/api/user(auth)/{user.model.spec.js => user.model.spec(mongooseModels).js} (100%) create mode 100644 app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js rename app/templates/server/config/{seed(mongoose).js => seed(models).js} (64%) create mode 100644 app/templates/server/sqldb(sequelize)/index.js create mode 100644 endpoint/templates/name.model(sequelize).js diff --git a/app/index.js b/app/index.js index 81c9e40b7..15aaf737f 100644 --- a/app/index.js +++ b/app/index.js @@ -145,15 +145,38 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ this.log('\n# Server\n'); this.prompt([{ - type: 'confirm', - name: 'mongoose', - message: 'Would you like to use mongoDB with Mongoose for data modeling?' + type: 'checkbox', + name: 'odms', + message: 'What would you like to use for data modeling?', + choices: [ + { + value: 'mongoose', + name: 'Mongoose (MongoDB)', + checked: true + }, + { + value: 'sequelize', + name: 'Sequelize (MySQL, SQLite, MariaDB, PostgreSQL)', + checked: false + } + ] + }, { + type: 'list', + name: 'models', + message: 'What would you like to use for the default models?', + choices: [ 'Mongoose', 'Sequelize' ], + filter: function( val ) { + return val.toLowerCase(); + }, + when: function(answers) { + return answers.odms && answers.odms.length > 1; + } }, { type: 'confirm', name: 'auth', message: 'Would you scaffold out an authentication boilerplate?', when: function (answers) { - return answers.mongoose; + return answers.odms && answers.odms.length !== 0; } }, { type: 'checkbox', @@ -183,15 +206,29 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ type: 'confirm', name: 'socketio', message: 'Would you like to use socket.io?', - // to-do: should not be dependent on mongoose + // to-do: should not be dependent on ODMs when: function (answers) { - return answers.mongoose; + return answers.odms && answers.odms.length !== 0; }, default: true }], function (answers) { if(answers.socketio) this.filters.socketio = true; - if(answers.mongoose) this.filters.mongoose = true; if(answers.auth) this.filters.auth = true; + if(answers.odms.length > 0) { + var models; + if(!answers.models) { + models = answers.odms[0]; + } else { + models = answers.models; + } + this.filters.models = true; + this.filters[models + 'Models'] = true; + answers.odms.forEach(function(odm) { + this.filters[odm] = true; + }.bind(this)); + } else { + this.filters.noModels = true; + } if(answers.oauth) { if(answers.oauth.length) this.filters.oauth = true; answers.oauth.forEach(function(oauthStrategy) { @@ -265,6 +302,10 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ this.config.set('registerSocketsFile', 'server/config/socketio.js'); this.config.set('socketsNeedle', '// Insert sockets below'); + this.config.set('insertModels', true); + this.config.set('registerModelsFile', 'server/sqldb/index.js'); + this.config.set('modelsNeedle', '// Insert models below'); + this.config.set('filters', this.filters); this.config.forceSave(); }, diff --git a/app/templates/_package.json b/app/templates/_package.json index d33133187..1666ea8b0 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -16,7 +16,9 @@ "jade": "~1.2.0",<% } %><% if (filters.html) { %> "ejs": "~0.8.4",<% } %><% if (filters.mongoose) { %> "mongoose": "~3.8.8", - "mongoose-bird": "~0.0.1",<% } %><% if (filters.auth) { %> + "mongoose-bird": "~0.0.1",<% } %><% if (filters.sequelize) { %> + "sequelize": "^2.0.0-rc2", + "sqlite3": "~3.0.2",<% } %><% if (filters.auth) { %> "jsonwebtoken": "^0.3.0", "express-jwt": "^0.1.3", "passport": "~0.2.0", @@ -24,8 +26,8 @@ "passport-facebook": "latest",<% } %><% if (filters.twitterAuth) { %> "passport-twitter": "latest",<% } %><% if (filters.googleAuth) { %> "passport-google-oauth": "latest",<% } %> - "composable-middleware": "^0.3.0", - "connect-mongo": "^0.4.1"<% if (filters.socketio) { %>, + "composable-middleware": "^0.3.0"<% if (filters.mongoose) { %>, + "connect-mongo": "^0.4.1"<% } %><% if (filters.socketio) { %>, "socket.io": "^1.0.6", "socket.io-client": "^1.0.6", "socketio-jwt": "^2.0.2"<% } %> diff --git a/app/templates/client/app/account(auth)/signup/signup.controller(coffee).coffee b/app/templates/client/app/account(auth)/signup/signup.controller(coffee).coffee index 3d96f3bf5..d167b7e30 100644 --- a/app/templates/client/app/account(auth)/signup/signup.controller(coffee).coffee +++ b/app/templates/client/app/account(auth)/signup/signup.controller(coffee).coffee @@ -20,11 +20,17 @@ angular.module '<%= scriptAppName %>' .catch (err) -> err = err.data $scope.errors = {} - +<% if (filters.mongooseModels) { %> # Update validity of form fields that match the mongoose errors angular.forEach err.errors, (error, field) -> form[field].$setValidity 'mongoose', false - $scope.errors[field] = error.message + $scope.errors[field] = error.message<% } + if (filters.sequelizeModels) { %> + # Update validity of form fields that match the sequelize errors + if err.name + angular.forEach err.fields, (field) -> + form[field].$setValidity 'mongoose', false + $scope.errors[field] = err.message<% } %> <% if (filters.oauth) {%> $scope.loginOauth = (provider) -> $window.location.href = '/auth/' + provider<% } %> diff --git a/app/templates/client/app/account(auth)/signup/signup.controller(js).js b/app/templates/client/app/account(auth)/signup/signup.controller(js).js index 7e93a6949..346eb7ea7 100644 --- a/app/templates/client/app/account(auth)/signup/signup.controller(js).js +++ b/app/templates/client/app/account(auth)/signup/signup.controller(js).js @@ -21,12 +21,20 @@ angular.module('<%= scriptAppName %>') .catch(function(err) { err = err.data; $scope.errors = {}; - +<% if (filters.mongooseModels) { %> // Update validity of form fields that match the mongoose errors angular.forEach(err.errors, function(error, field) { form[field].$setValidity('mongoose', false); $scope.errors[field] = error.message; - }); + });<% } + if (filters.sequelizeModels) { %> + // Update validity of form fields that match the sequelize errors + if (err.name) { + angular.forEach(err.fields, function(field) { + form[field].$setValidity('mongoose', false); + $scope.errors[field] = err.message; + }); + }<% } %> }); } }; diff --git a/app/templates/client/app/main/main.controller(coffee).coffee b/app/templates/client/app/main/main.controller(coffee).coffee index 3dffae2f7..4b04a951b 100644 --- a/app/templates/client/app/main/main.controller(coffee).coffee +++ b/app/templates/client/app/main/main.controller(coffee).coffee @@ -7,7 +7,7 @@ angular.module '<%= scriptAppName %>' $http.get('/api/things').success (awesomeThings) -> $scope.awesomeThings = awesomeThings <% if (filters.socketio) { %>socket.syncUpdates 'thing', $scope.awesomeThings<% } %> -<% if (filters.mongoose) { %> +<% if (filters.models) { %> $scope.addThing = -> return if $scope.newThing is '' $http.post '/api/things', diff --git a/app/templates/client/app/main/main.controller(js).js b/app/templates/client/app/main/main.controller(js).js index 8164a90dc..345d9909d 100644 --- a/app/templates/client/app/main/main.controller(js).js +++ b/app/templates/client/app/main/main.controller(js).js @@ -8,7 +8,7 @@ angular.module('<%= scriptAppName %>') $scope.awesomeThings = awesomeThings;<% if (filters.socketio) { %> socket.syncUpdates('thing', $scope.awesomeThings);<% } %> }); -<% if (filters.mongoose) { %> +<% if (filters.models) { %> $scope.addThing = function() { if ($scope.newThing === '') { return; diff --git a/app/templates/e2e/account(auth)/login/login.spec(jasmine).js b/app/templates/e2e/account(auth)/login/login.spec(jasmine).js index d3f0d48ed..e690c2601 100644 --- a/app/templates/e2e/account(auth)/login/login.spec(jasmine).js +++ b/app/templates/e2e/account(auth)/login/login.spec(jasmine).js @@ -1,7 +1,8 @@ 'use strict'; -var config = protractor.getInstance().params; -var UserModel = require(config.serverConfig.root + '/server/api/user/user.model'); +var config = protractor.getInstance().params;<% if (filters.mongooseModels) { %> +var UserModel = require(config.serverConfig.root + '/server/api/user/user.model');<% } %><% if (filters.sequelizeModels) { %> +var UserModel = require(config.serverConfig.root + '/server/sqldb').User;<% } %> describe('Login View', function() { var page; @@ -18,9 +19,11 @@ describe('Login View', function() { }; beforeEach(function(done) { - UserModel.removeAsync() + <% if (filters.mongooseModels) { %>UserModel.removeAsync()<% } + if (filters.sequelizeModels) { %>UserModel.destroy()<% } %> .then(function() { - return UserModel.createAsync(testUser); + <% if (filters.mongooseModels) { %>return UserModel.createAsync(testUser);<% } + if (filters.sequelizeModels) { %>return UserModel.create(testUser);<% } %> }) .then(loadPage) .finally(done); diff --git a/app/templates/e2e/account(auth)/login/login.spec(mocha).js b/app/templates/e2e/account(auth)/login/login.spec(mocha).js index a2c986f32..3335cf3b4 100644 --- a/app/templates/e2e/account(auth)/login/login.spec(mocha).js +++ b/app/templates/e2e/account(auth)/login/login.spec(mocha).js @@ -1,7 +1,8 @@ 'use strict'; -var config = protractor.getInstance().params; -var UserModel = require(config.serverConfig.root + '/server/api/user/user.model'); +var config = protractor.getInstance().params;<% if (filters.mongooseModels) { %> +var UserModel = require(config.serverConfig.root + '/server/api/user/user.model');<% } %><% if (filters.sequelizeModels) { %> +var UserModel = require(config.serverConfig.root + '/server/sqldb').User;<% } %> describe('Login View', function() { var page; @@ -19,15 +20,18 @@ describe('Login View', function() { before(function() { return UserModel - .removeAsync() + <% if (filters.mongooseModels) { %>.removeAsync()<% } + if (filters.sequelizeModels) { %>.destroy()<% } %> .then(function() { - return UserModel.createAsync(testUser); + <% if (filters.mongooseModels) { %>return UserModel.createAsync(testUser);<% } + if (filters.sequelizeModels) { %>return UserModel.create(testUser);<% } %> }) .then(loadPage); }); after(function() { - return UserModel.removeAsync(); + <% if (filters.mongooseModels) { %>return UserModel.removeAsync();<% } + if (filters.sequelizeModels) { %>return UserModel.destroy();<% } %> }); it('should include login form with correct inputs and submit button', function() { diff --git a/app/templates/e2e/account(auth)/logout/logout.spec(jasmine).js b/app/templates/e2e/account(auth)/logout/logout.spec(jasmine).js index f496459d8..f3149865c 100644 --- a/app/templates/e2e/account(auth)/logout/logout.spec(jasmine).js +++ b/app/templates/e2e/account(auth)/logout/logout.spec(jasmine).js @@ -1,7 +1,8 @@ 'use strict'; -var config = protractor.getInstance().params; -var UserModel = require(config.serverConfig.root + '/server/api/user/user.model'); +var config = protractor.getInstance().params;<% if (filters.mongooseModels) { %> +var UserModel = require(config.serverConfig.root + '/server/api/user/user.model');<% } %><% if (filters.sequelizeModels) { %> +var UserModel = require(config.serverConfig.root + '/server/sqldb').User;<% } %> describe('Logout View', function() { var login = function(user) { @@ -16,9 +17,11 @@ describe('Logout View', function() { }; beforeEach(function(done) { - UserModel.removeAsync() + <% if (filters.mongooseModels) { %>UserModel.removeAsync()<% } + if (filters.sequelizeModels) { %>UserModel.destroy()<% } %> .then(function() { - return UserModel.createAsync(testUser); + <% if (filters.mongooseModels) { %>return UserModel.createAsync(testUser);<% } + if (filters.sequelizeModels) { %>return UserModel.create(testUser);<% } %> }) .then(function() { return login(testUser); diff --git a/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js b/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js index 3adba51f8..85d92cf75 100644 --- a/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js +++ b/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js @@ -1,7 +1,8 @@ 'use strict'; -var config = protractor.getInstance().params; -var UserModel = require(config.serverConfig.root + '/server/api/user/user.model'); +var config = protractor.getInstance().params;<% if (filters.mongooseModels) { %> +var UserModel = require(config.serverConfig.root + '/server/api/user/user.model');<% } %><% if (filters.sequelizeModels) { %> +var UserModel = require(config.serverConfig.root + '/server/sqldb').User;<% } %> describe('Logout View', function() { var login = function(user) { @@ -17,9 +18,11 @@ describe('Logout View', function() { beforeEach(function() { return UserModel - .removeAsync() + <% if (filters.mongooseModels) { %>.removeAsync()<% } + if (filters.sequelizeModels) { %>.destroy()<% } %> .then(function() { - return UserModel.createAsync(testUser); + <% if (filters.mongooseModels) { %>return UserModel.createAsync(testUser);<% } + if (filters.sequelizeModels) { %>return UserModel.create(testUser);<% } %> }) .then(function() { return login(testUser); @@ -27,7 +30,8 @@ describe('Logout View', function() { }); after(function() { - return UserModel.removeAsync(); + <% if (filters.mongooseModels) { %>return UserModel.removeAsync();<% } + if (filters.sequelizeModels) { %>return UserModel.destroy();<% } %> }) describe('with local auth', function() { diff --git a/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js b/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js index 856786e4a..abbfc98a4 100644 --- a/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js +++ b/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js @@ -1,7 +1,8 @@ 'use strict'; -var config = protractor.getInstance().params; -var UserModel = require(config.serverConfig.root + '/server/api/user/user.model'); +var config = protractor.getInstance().params;<% if (filters.mongooseModels) { %> +var UserModel = require(config.serverConfig.root + '/server/api/user/user.model');<% } %><% if (filters.sequelizeModels) { %> +var UserModel = require(config.serverConfig.root + '/server/sqldb').User;<% } %> describe('Signup View', function() { var page; @@ -35,7 +36,8 @@ describe('Signup View', function() { describe('with local auth', function() { it('should signup a new user, log them in, and redirecting to "/"', function(done) { - UserModel.remove(function() { + <% if (filters.mongooseModels) { %>UserModel.remove(function() {<% } + if (filters.sequelizeModels) { %>UserModel.destroy().then(function() {<% } %> page.signup(testUser); var navbar = require('../../components/navbar/navbar.po'); diff --git a/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js b/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js index 6a6b0a775..5351ea75d 100644 --- a/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js +++ b/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js @@ -1,7 +1,8 @@ 'use strict'; -var config = protractor.getInstance().params; -var UserModel = require(config.serverConfig.root + '/server/api/user/user.model'); +var config = protractor.getInstance().params;<% if (filters.mongooseModels) { %> +var UserModel = require(config.serverConfig.root + '/server/api/user/user.model');<% } %><% if (filters.sequelizeModels) { %> +var UserModel = require(config.serverConfig.root + '/server/sqldb').User;<% } %> describe('Signup View', function() { var page; @@ -22,7 +23,8 @@ describe('Signup View', function() { }); after(function() { - return UserModel.removeAsync(); + <% if (filters.mongooseModels) { %>return UserModel.removeAsync();<% } + if (filters.sequelizeModels) { %>return UserModel.destroy();<% } %> }); it('should include signup form with correct inputs and submit button', function() { @@ -39,7 +41,8 @@ describe('Signup View', function() { describe('with local auth', function() { it('should signup a new user, log them in, and redirecting to "/"', function(done) { - UserModel.remove(function() { + <% if (filters.mongooseModels) { %>UserModel.remove(function() {<% } + if (filters.sequelizeModels) { %>UserModel.destroy().then(function() {<% } %> page.signup(testUser); var navbar = require('../../components/navbar/navbar.po'); diff --git a/app/templates/protractor.conf.js b/app/templates/protractor.conf.js index f0061ff86..a5c42a390 100644 --- a/app/templates/protractor.conf.js +++ b/app/templates/protractor.conf.js @@ -75,10 +75,10 @@ var config = { ); <% } %> var serverConfig = config.params.serverConfig; - +<% if (filters.mongoose) { %> // Setup mongo for tests var mongoose = require('mongoose-bird')(); - mongoose.connect(serverConfig.mongo.uri, serverConfig.mongo.options); // Connect to database + mongoose.connect(serverConfig.mongo.uri, serverConfig.mongo.options); // Connect to database<% } %> } }; diff --git a/app/templates/server/api/thing/index.js b/app/templates/server/api/thing/index.js index ea697d38b..fde8f3968 100644 --- a/app/templates/server/api/thing/index.js +++ b/app/templates/server/api/thing/index.js @@ -5,7 +5,7 @@ var controller = require('./thing.controller'); var router = express.Router(); -router.get('/', controller.index);<% if (filters.mongoose) { %> +router.get('/', controller.index);<% if (filters.models) { %> router.get('/:id', controller.show); router.post('/', controller.create); router.put('/:id', controller.update); diff --git a/app/templates/server/api/thing/index.spec.js b/app/templates/server/api/thing/index.spec.js index 899b22d79..91f02f6df 100644 --- a/app/templates/server/api/thing/index.spec.js +++ b/app/templates/server/api/thing/index.spec.js @@ -3,7 +3,7 @@ var proxyquire = require('proxyquire').noPreserveCache(); var thingCtrlStub = { - index: 'thingCtrl.index'<% if (filters.mongoose) { %>, + index: 'thingCtrl.index'<% if (filters.models) { %>, show: 'thingCtrl.show', create: 'thingCtrl.create', update: 'thingCtrl.update', @@ -11,7 +11,7 @@ var thingCtrlStub = { }; var routerStub = { - get: sinon.spy()<% if (filters.mongoose) { %>, + get: sinon.spy()<% if (filters.models) { %>, put: sinon.spy(), patch: sinon.spy(), post: sinon.spy(), @@ -42,7 +42,7 @@ describe('Thing API Router:', function() { .should.have.been.calledOnce; }); - });<% if (filters.mongoose) { %> + });<% if (filters.models) { %> describe('GET /api/things/:id', function() { diff --git a/app/templates/server/api/thing/thing.controller.js b/app/templates/server/api/thing/thing.controller(models).js similarity index 52% rename from app/templates/server/api/thing/thing.controller.js rename to app/templates/server/api/thing/thing.controller(models).js index 710c7cd38..a14fbd4b3 100644 --- a/app/templates/server/api/thing/thing.controller.js +++ b/app/templates/server/api/thing/thing.controller(models).js @@ -7,10 +7,12 @@ * DELETE /things/:id -> destroy */ -'use strict';<% if (filters.mongoose) { %> +'use strict'; -var _ = require('lodash'); -var Thing = require('./thing.model'); +var _ = require('lodash');<% if (filters.mongooseModels) { %> +var Thing = require('./thing.model');<% } %><% if (filters.sequelizeModels) { %> +var sqldb = require('../../sqldb') +var Thing = sqldb.Thing;<% } %> function handleError(res, statusCode) { statusCode = statusCode || 500; @@ -40,9 +42,11 @@ function handleEntityNotFound(res) { function saveUpdates(updates) { return function(entity) { - var updated = _.merge(entity, updates); + <% if (filters.mongooseModels) { %>var updated = _.merge(entity, updates); return updated.saveAsync() - .spread(function(updated) { + .spread(function(updated) {<% } + if (filters.sequelizeModels) { %>return entity.updateAttributes(updates) + .then(function(updated) {<% } %> return updated; }); }; @@ -51,48 +55,31 @@ function saveUpdates(updates) { function removeEntity(res) { return function(entity) { if (entity) { - return entity.removeAsync() + <% if (filters.mongooseModels) { %>return entity.removeAsync()<% } + if (filters.sequelizeModels) { %>return entity.destroy()<% } %> .then(function() { return res.send(204); }); } }; -}<% } %> +} // Get list of things -exports.index = function(req, res) {<% if(!filters.mongoose) { %> - res.json([{ - name : 'Development Tools', - info : 'Integration with popular tools such as Bower, Grunt, Karma, Mocha, JSHint, ' + - 'Node Inspector, Livereload, Protractor, Jade, Stylus, Sass, CoffeeScript, and Less.' - }, { - name : 'Server and Client integration', - info : 'Built with a powerful and fun stack: MongoDB, Express, AngularJS, and Node.' - }, { - name : 'Smart Build System', - info : 'Build system ignores `spec` files, allowing you to keep tests alongside code. ' + - 'Automatic injection of scripts and styles into your index.html' - }, { - name : 'Modular Structure', - info : 'Best practice client and server structures allow for more code reusability and ' + - 'maximum scalability' - }, { - name : 'Optimized Build', - info : 'Build process packs up your templates as a single JavaScript payload, minifies ' + - 'your scripts/css/images, and rewrites asset names for caching.' - }, { - name : 'Deployment Ready', - info : 'Easily deploy your app to Heroku or Openshift with the heroku and openshift ' + - 'subgenerators' - }]);<% } if (filters.mongoose) { %> - Thing.findAsync() +exports.index = function(req, res) { + <% if (filters.mongooseModels) { %>Thing.findAsync()<% } + if (filters.sequelizeModels) { %>Thing.findAll()<% } %> .then(responseWithResult(res)) - .catch(handleError(res));<% } %> -};<% if (filters.mongoose) { %> + .catch(handleError(res)); +}; // Get a single thing exports.show = function(req, res) { - Thing.findByIdAsync(req.params.id) + <% if (filters.mongooseModels) { %>Thing.findByIdAsync(req.params.id)<% } + if (filters.sequelizeModels) { %>Thing.find({ + where: { + _id: req.params.id + } + })<% } %> .then(handleEntityNotFound(res)) .then(responseWithResult(res)) .catch(handleError(res)); @@ -100,7 +87,8 @@ exports.show = function(req, res) { // Creates a new thing in the DB. exports.create = function(req, res) { - Thing.createAsync(req.body) + <% if (filters.mongooseModels) { %>Thing.createAsync(req.body)<% } + if (filters.sequelizeModels) { %>Thing.create(req.body)<% } %> .then(responseWithResult(res, 201)) .catch(handleError(res)); }; @@ -110,7 +98,12 @@ exports.update = function(req, res) { if (req.body._id) { delete req.body._id; } - Thing.findByIdAsync(req.params.id) + <% if (filters.mongooseModels) { %>Thing.findByIdAsync(req.params.id)<% } + if (filters.sequelizeModels) { %>Thing.find({ + where: { + _id: req.params.id + } + })<% } %> .then(handleEntityNotFound(res)) .then(saveUpdates(req.body)) .then(responseWithResult(res)) @@ -119,8 +112,13 @@ exports.update = function(req, res) { // Deletes a thing from the DB. exports.destroy = function(req, res) { - Thing.findByIdAsync(req.params.id) + <% if (filters.mongooseModels) { %>Thing.findByIdAsync(req.params.id)<% } + if (filters.sequelizeModels) { %>Thing.find({ + where: { + _id: req.params.id + } + })<% } %> .then(handleEntityNotFound(res)) .then(removeEntity(res)) .catch(handleError(res)); -};<% } %> +}; diff --git a/app/templates/server/api/thing/thing.controller(noModels).js b/app/templates/server/api/thing/thing.controller(noModels).js new file mode 100644 index 000000000..02b2410c5 --- /dev/null +++ b/app/templates/server/api/thing/thing.controller(noModels).js @@ -0,0 +1,38 @@ +/** + * Using Rails-like standard naming convention for endpoints. + * GET /things -> index + * POST /things -> create + * GET /things/:id -> show + * PUT /things/:id -> update + * DELETE /things/:id -> destroy + */ + +'use strict'; + +// Get list of things +exports.index = function(req, res) { + res.json([{ + name : 'Development Tools', + info : 'Integration with popular tools such as Bower, Grunt, Karma, Mocha, JSHint, ' + + 'Node Inspector, Livereload, Protractor, Jade, Stylus, Sass, CoffeeScript, and Less.' + }, { + name : 'Server and Client integration', + info : 'Built with a powerful and fun stack: MongoDB, Express, AngularJS, and Node.' + }, { + name : 'Smart Build System', + info : 'Build system ignores `spec` files, allowing you to keep tests alongside code. ' + + 'Automatic injection of scripts and styles into your index.html' + }, { + name : 'Modular Structure', + info : 'Best practice client and server structures allow for more code reusability and ' + + 'maximum scalability' + }, { + name : 'Optimized Build', + info : 'Build process packs up your templates as a single JavaScript payload, minifies ' + + 'your scripts/css/images, and rewrites asset names for caching.' + }, { + name : 'Deployment Ready', + info : 'Easily deploy your app to Heroku or Openshift with the heroku and openshift ' + + 'subgenerators' + }]); +}; diff --git a/app/templates/server/api/thing/thing.integration.js b/app/templates/server/api/thing/thing.integration.js index de7ed7ff5..3eb5d05d8 100644 --- a/app/templates/server/api/thing/thing.integration.js +++ b/app/templates/server/api/thing/thing.integration.js @@ -1,7 +1,7 @@ 'use strict'; var app = require('../../app'); -var request = require('supertest');<% if (filters.mongoose) { %> +var request = require('supertest');<% if (filters.models) { %> var newThing;<% } %> @@ -28,7 +28,7 @@ describe('Thing API:', function() { things.should.be.instanceOf(Array); }); - });<% if (filters.mongoose) { %> + });<% if (filters.models) { %> describe('POST /api/things', function() { beforeEach(function(done) { @@ -130,7 +130,7 @@ describe('Thing API:', function() { }); }); - it('should respond with 404 when thing does not exsist', function(done) { + it('should respond with 404 when thing does not exist', function(done) { request(app) .delete('/api/things/' + newThing._id) .expect(404) diff --git a/app/templates/server/api/thing/thing.model(mongoose).js b/app/templates/server/api/thing/thing.model(mongooseModels).js similarity index 100% rename from app/templates/server/api/thing/thing.model(mongoose).js rename to app/templates/server/api/thing/thing.model(mongooseModels).js diff --git a/app/templates/server/api/thing/thing.model(sequelizeModels).js b/app/templates/server/api/thing/thing.model(sequelizeModels).js new file mode 100644 index 000000000..8e8072da4 --- /dev/null +++ b/app/templates/server/api/thing/thing.model(sequelizeModels).js @@ -0,0 +1,15 @@ +'use strict'; + +module.exports = function(sequelize, DataTypes) { + return sequelize.define('Thing', { + _id: { + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true, + autoIncrement: true + }, + name: DataTypes.STRING, + info: DataTypes.STRING, + active: DataTypes.BOOLEAN + }); +}; diff --git a/app/templates/server/api/thing/thing.socket(socketio).js b/app/templates/server/api/thing/thing.socket(socketio).js index 2d0171cdc..d0d98a6ca 100644 --- a/app/templates/server/api/thing/thing.socket(socketio).js +++ b/app/templates/server/api/thing/thing.socket(socketio).js @@ -3,15 +3,24 @@ */ 'use strict'; +<% if (filters.mongooseModels) { %> +var thing = require('./thing.model');<% } %><% if (filters.sequelizeModels) { %> +var thing = require('../../sqldb').Thing;<% } %> -var thing = require('./thing.model'); - -exports.register = function(socket) { - thing.schema.post('save', function(doc) { +exports.register = function(socket) {<% if (filters.sequelizeModels) { %> + thing.hook('afterCreate', function(doc, fields, fn) { onSave(socket, doc); + fn(null); + });<% } %> + <% if (filters.mongooseModels) { %>thing.schema.post('save', function(doc) {<% } + if (filters.sequelizeModels) { %>thing.hook('afterUpdate', function(doc, fields, fn) {<% } %> + onSave(socket, doc);<% if (filters.sequelizeModels) { %> + fn(null);<% } %> }); - thing.schema.post('remove', function(doc) { - onRemove(socket, doc); + <% if (filters.mongooseModels) { %>thing.schema.post('remove', function(doc) {<% } + if (filters.sequelizeModels) { %>thing.hook('afterDestroy', function(doc, fields, fn) {<% } %> + onRemove(socket, doc);<% if (filters.sequelizeModels) { %> + fn(null);<% } %> }); }; diff --git a/app/templates/server/api/user(auth)/user.controller.js b/app/templates/server/api/user(auth)/user.controller.js index 793da0255..8b7f4e0b8 100644 --- a/app/templates/server/api/user(auth)/user.controller.js +++ b/app/templates/server/api/user(auth)/user.controller.js @@ -1,6 +1,9 @@ 'use strict'; - -var User = require('./user.model'); +<% if (filters.mongooseModels) { %> +var User = require('./user.model');<% } %><% if (filters.sequelizeModels) { %> +var _ = require('lodash'); +var sqldb = require('../../sqldb'); +var User = sqldb.User;<% } %> var passport = require('passport'); var config = require('../../config/environment'); var jwt = require('jsonwebtoken'); @@ -31,7 +34,16 @@ function respondWith(res, statusCode) { * restriction: 'admin' */ exports.index = function(req, res) { - User.findAsync({}, '-salt -hashedPassword') + <% if (filters.mongooseModels) { %>User.findAsync({}, '-salt -hashedPassword')<% } + if (filters.sequelizeModels) { %>User.findAll({ + attributes: [ + '_id', + 'name', + 'email', + 'role', + 'provider' + ] + })<% } %> .then(function(users) { res.json(200, users); }) @@ -42,11 +54,16 @@ exports.index = function(req, res) { * Creates a new user */ exports.create = function(req, res, next) { - var newUser = new User(req.body); + <% if (filters.mongooseModels) { %>var newUser = new User(req.body); newUser.provider = 'local'; newUser.role = 'user'; - newUser.saveAsync() - .spread(function(user) { + newUser.saveAsync()<% } + if (filters.sequelizeModels) { %>var newUser = User.build(req.body); + newUser.setDataValue('provider', 'local'); + newUser.setDataValue('role', 'user'); + newUser.save()<% } %> + <% if (filters.mongooseModels) { %>.spread(function(user) {<% } + if (filters.sequelizeModels) { %>.then(function(user) {<% } %> var token = jwt.sign({ _id: user._id }, config.secrets.session, { expiresInMinutes: 60 * 5 }); @@ -61,7 +78,12 @@ exports.create = function(req, res, next) { exports.show = function(req, res, next) { var userId = req.params.id; - User.findByIdAsync(userId) + <% if (filters.mongooseModels) { %>User.findByIdAsync(userId)<% } + if (filters.sequelizeModels) { %>User.find({ + where: { + _id: userId + } + })<% } %> .then(function(user) { if (!user) { return res.send(401); @@ -78,7 +100,8 @@ exports.show = function(req, res, next) { * restriction: 'admin' */ exports.destroy = function(req, res) { - User.findByIdAndRemoveAsync(req.params.id) + <% if (filters.mongooseModels) { %>User.findByIdAndRemoveAsync(req.params.id)<% } + if (filters.sequelizeModels) { %>User.destroy({ _id: req.params.id })<% } %> .then(respondWith(res, 204)) .catch(handleError(res)); }; @@ -91,12 +114,18 @@ exports.changePassword = function(req, res, next) { var oldPass = String(req.body.oldPassword); var newPass = String(req.body.newPassword); - User.findByIdAsync(userId) + <% if (filters.mongooseModels) { %>User.findByIdAsync(userId)<% } + if (filters.sequelizeModels) { %>User.find({ + where: { + _id: userId + } + })<% } %> .then(function(user) { if (user.authenticate(oldPass)) { user.password = newPass; - return user.saveAsync() - .spread(respondWith(res, 200)) + <% if (filters.mongooseModels) { %>return user.saveAsync()<% } + if (filters.sequelizeModels) { %>return user.save()<% } %> + .then(respondWith(res, 200)) .catch(validationError(res)); } else { return res.send(403); @@ -110,7 +139,19 @@ exports.changePassword = function(req, res, next) { exports.me = function(req, res, next) { var userId = req.user._id; - User.findOneAsync({ _id: userId }, '-salt -hashedPassword') + <% if (filters.mongooseModels) { %>User.findOneAsync({ _id: userId }, '-salt -hashedPassword')<% } + if (filters.sequelizeModels) { %>User.find({ + where: { + _id: userId + }, + attributes: [ + '_id', + 'name', + 'email', + 'role', + 'provider' + ] + })<% } %> .then(function(user) { // don't ever give out the password or salt if (!user) { return res.json(401); } res.json(user); diff --git a/app/templates/server/api/user(auth)/user.integration.js b/app/templates/server/api/user(auth)/user.integration.js index ee97d3051..35bcdb573 100644 --- a/app/templates/server/api/user(auth)/user.integration.js +++ b/app/templates/server/api/user(auth)/user.integration.js @@ -1,7 +1,8 @@ 'use strict'; -var app = require('../../app'); -var User = require('./user.model'); +var app = require('../../app');<% if (filters.mongooseModels) { %> +var User = require('./user.model');<% } %><% if (filters.sequelizeModels) { %> +var User = require('../../sqldb').User;<% } %> var request = require('supertest'); describe('User API:', function() { @@ -9,25 +10,33 @@ describe('User API:', function() { // Clear users before testing before(function(done) { - User.remove(function() { - user = new User({ + <% if (filters.mongooseModels) { %>User.remove(function() {<% } + if (filters.sequelizeModels) { %>User.destroy().then(function() {<% } %> + <% if (filters.mongooseModels) { %>user = new User({<% } + if (filters.sequelizeModels) { %>user = User.build({<% } %> name: 'Fake User', email: 'test@test.com', password: 'password' }); - user.save(function(err) { + <% if (filters.mongooseModels) { %>user.save(function(err) { if (err) { return done(err); } done(); - }); + });<% } + if (filters.sequelizeModels) { %>user.save().then(function() { + done(); + }, function(err) { + return done(err); + });<% } %> }); }); // Clear users after testing after(function() { - return User.remove().exec(); + <% if (filters.mongooseModels) { %>return User.remove().exec();<% } + if (filters.sequelizeModels) { %>return User.destroy();<% } %> }); describe('GET /api/users/me', function() { @@ -55,7 +64,7 @@ describe('User API:', function() { .expect(200) .expect('Content-Type', /json/) .end(function(err, res) { - res.body._id.should.equal(user._id.toString()); + res.body._id.toString().should.equal(user._id.toString()); done(); }); }); diff --git a/app/templates/server/api/user(auth)/user.model.js b/app/templates/server/api/user(auth)/user.model(mongooseModels).js similarity index 100% rename from app/templates/server/api/user(auth)/user.model.js rename to app/templates/server/api/user(auth)/user.model(mongooseModels).js diff --git a/app/templates/server/api/user(auth)/user.model(sequelizeModels).js b/app/templates/server/api/user(auth)/user.model(sequelizeModels).js new file mode 100644 index 000000000..af593157a --- /dev/null +++ b/app/templates/server/api/user(auth)/user.model(sequelizeModels).js @@ -0,0 +1,235 @@ +'use strict'; + +var crypto = require('crypto');<% if (filters.oauth) { %> +var authTypes = ['github', 'twitter', 'facebook', 'google'];<% } %> + +var validatePresenceOf = function(value) { + return value && value.length; +}; + +module.exports = function(sequelize, DataTypes) { + var User = sequelize.define('User', { + + _id: { + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true, + autoIncrement: true + }, + name: DataTypes.STRING, + email: { + type: DataTypes.STRING, + unique: { + msg: 'The specified email address is already in use.' + }, + validate: { + isEmail: true + } + }, + role: { + type: DataTypes.STRING, + defaultValue: 'user' + }, + password: { + type: DataTypes.STRING, + validate: { + notEmpty: true + } + }, + provider: DataTypes.STRING, + salt: DataTypes.STRING<% if (filters.oauth) { %>,<% if (filters.facebookAuth) { %> + facebook: DataTypes.TEXT,<% } %><% if (filters.twitterAuth) { %> + twitter: DataTypes.TEXT,<% } %><% if (filters.googleAuth) { %> + google: DataTypes.TEXT,<% } %> + github: DataTypes.TEXT<% } %> + + }, { + + /** + * Virtual Getters + */ + getterMethods: { + // Public profile information + profile: function() { + return { + 'name': this.name, + 'role': this.role + }; + }, + + // Non-sensitive info we'll be putting in the token + token: function() { + return { + '_id': this._id, + 'role': this.role + }; + } + }, + + /** + * Pre-save hooks + */ + hooks: { + beforeBulkCreate: function(users, fields, fn) { + var totalUpdated = 0; + users.forEach(function(user) { + user.updatePassword(function(err) { + if (err) { + return fn(err); + } + totalUpdated += 1; + if (totalUpdated === users.length) { + return fn(); + } + }); + }); + }, + beforeCreate: function(user, fields, fn) { + user.updatePassword(fn); + }, + beforeUpdate: function(user, fields, fn) { + if (user.changed('password')) { + user.updatePassword(fn); + } + } + }, + + /** + * Instance Methods + */ + instanceMethods: { + /** + * Authenticate - check if the passwords are the same + * + * @param {String} password + * @param {Function} callback + * @return {Boolean} + * @api public + */ + authenticate: function(password, callback) { + if (!callback) { + return this.password === this.encryptPassword(password); + } + + var _this = this; + this.encryptPassword(password, function(err, pwdGen) { + if (err) { + callback(err); + } + + if (_this.password === pwdGen) { + callback(null, true); + } + else { + callback(null, false); + } + }); + }, + + /** + * Make salt + * + * @param {Number} byteSize Optional salt byte size, default to 16 + * @param {Function} callback + * @return {String} + * @api public + */ + makeSalt: function(byteSize, callback) { + var defaultByteSize = 16; + + if (typeof arguments[0] === 'function') { + callback = arguments[0]; + byteSize = defaultByteSize; + } + else if (typeof arguments[1] === 'function') { + callback = arguments[1]; + } + + if (!byteSize) { + byteSize = defaultByteSize; + } + + if (!callback) { + return crypto.randomBytes(byteSize).toString('base64'); + } + + return crypto.randomBytes(byteSize, function(err, salt) { + if (err) { + callback(err); + } + return callback(null, salt.toString('base64')); + }); + }, + + /** + * Encrypt password + * + * @param {String} password + * @param {Function} callback + * @return {String} + * @api public + */ + encryptPassword: function(password, callback) { + if (!password || !this.salt) { + if (!callback) { + return null; + } + return callback(null); + } + + var defaultIterations = 10000; + var defaultKeyLength = 64; + var salt = new Buffer(this.salt, 'base64'); + + if (!callback) { + return crypto.pbkdf2Sync(password, salt, defaultIterations, defaultKeyLength) + .toString('base64'); + } + + return crypto.pbkdf2(password, salt, defaultIterations, defaultKeyLength, + function(err, key) { + if (err) { + callback(err); + } + return callback(null, key.toString('base64')); + }); + }, + + /** + * Update password field + * + * @param {Function} fn + * @return {String} + * @api public + */ + updatePassword: function(fn) { + // Handle new/update passwords + if (this.password) { + if (!validatePresenceOf(this.password)<% if (filters.oauth) { %> && authTypes.indexOf(this.provider) === -1<% } %>) { + fn(new Error('Invalid password')); + } + + // Make salt with a callback + var _this = this; + this.makeSalt(function(saltErr, salt) { + if (saltErr) { + fn(saltErr); + } + _this.salt = salt; + _this.encryptPassword(_this.password, function(encryptErr, hashedPassword) { + if (encryptErr) { + fn(encryptErr); + } + _this.password = hashedPassword; + fn(null); + }); + }); + } else { + fn(null); + } + } + } + }); + + return User; +}; diff --git a/app/templates/server/api/user(auth)/user.model.spec.js b/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js similarity index 100% rename from app/templates/server/api/user(auth)/user.model.spec.js rename to app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js diff --git a/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js b/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js new file mode 100644 index 000000000..88156151b --- /dev/null +++ b/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js @@ -0,0 +1,52 @@ +'use strict'; + +var app = require('../../app'); +var User = require('../../sqldb').User; + +var userTemplate = { + provider: 'local', + name: 'Fake User', + email: 'test@test.com', + password: 'password' +}; + +var user = User.build(userTemplate); + +describe('User Model', function() { + before(function() { + // Sync and clear users before testing + User.sync().then(function() { + return User.destroy(); + }); + }); + + afterEach(function() { + return User.destroy(); + }); + + it('should begin with no users', function() { + return User.findAll() + .should.eventually.have.length(0); + }); + + it('should fail when saving a duplicate user', function() { + return user.save() + .then(function() { + var userDup = User.build(userTemplate); + return userDup.save(); + }).should.be.rejected; + }); + + it('should fail when saving without an email', function() { + user.email = ''; + return user.save().should.be.rejected; + }); + + it('should authenticate user if password is valid', function() { + user.authenticate('password').should.be.true; + }); + + it('should not authenticate user if password is invalid', function() { + user.authenticate('blah').should.not.be.true; + }); +}); diff --git a/app/templates/server/app.js b/app/templates/server/app.js index 632dd134f..7c668a881 100644 --- a/app/templates/server/app.js +++ b/app/templates/server/app.js @@ -8,16 +8,17 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'development'; var express = require('express');<% if (filters.mongoose) { %> -var mongoose = require('mongoose-bird')();<% } %> +var mongoose = require('mongoose-bird')();<% } %><% if (filters.sequelize) { %> +var sqldb = require('./sqldb');<% } %> var config = require('./config/environment'); <% if (filters.mongoose) { %> -// Connect to database +// Connect to MongoDB mongoose.connect(config.mongo.uri, config.mongo.options); - -// Populate DB with sample data +<% } %><% if (filters.models) { %> +// Populate databases with sample data if (config.seedDB) { require('./config/seed'); } - -<% } %>// Setup server +<% } %> +// Setup server var app = express(); var server = require('http').createServer(app);<% if (filters.socketio) { %> var socketio = require('socket.io')(server, { @@ -29,9 +30,19 @@ require('./config/express')(app); require('./routes')(app); // Start server -server.listen(config.port, config.ip, function() { - console.log('Express server listening on %d, in %s mode', config.port, app.get('env')); -}); - +function startServer() { + server.listen(config.port, config.ip, function() { + console.log('Express server listening on %d, in %s mode', config.port, app.get('env')); + }); +} +<% if (filters.sequelize) { %> +sqldb.sequelize.sync() + .then(startServer) + .catch(function(err) { + console.log('Server failed to start due to error: %s', err); + }); +<% } else { %> +setImmediate(startServer); +<% } %> // Expose app exports = module.exports = app; diff --git a/app/templates/server/auth(auth)/auth.service.js b/app/templates/server/auth(auth)/auth.service.js index 43ea2851f..5b9a6d66f 100644 --- a/app/templates/server/auth(auth)/auth.service.js +++ b/app/templates/server/auth(auth)/auth.service.js @@ -1,12 +1,13 @@ 'use strict'; - -var mongoose = require('mongoose-bird')(); +<% if (filters.mongooseModels) { %> +var mongoose = require('mongoose-bird')();<% } %> var passport = require('passport'); var config = require('../config/environment'); var jwt = require('jsonwebtoken'); var expressJwt = require('express-jwt'); -var compose = require('composable-middleware'); -var User = require('../api/user/user.model'); +var compose = require('composable-middleware');<% if (filters.mongooseModels) { %> +var User = require('../api/user/user.model');<% } %><% if (filters.sequelizeModels) { %> +var User = require('../sqldb').User;<% } %> var validateJwt = expressJwt({ secret: config.secrets.session }); @@ -27,7 +28,12 @@ function isAuthenticated() { }) // Attach user to request .use(function(req, res, next) { - User.findByIdAsync(req.user._id) + <% if (filters.mongooseModels) { %>User.findByIdAsync(req.user._id)<% } + if (filters.sequelizeModels) { %>User.find({ + where: { + _id: req.user._id + } + })<% } %> .then(function(user) { if (!user) { return res.send(401); diff --git a/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js b/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js index b29d74c69..92911b22f 100644 --- a/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js +++ b/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js @@ -8,31 +8,35 @@ exports.setup = function(User, config) { callbackURL: config.facebook.callbackURL }, function(accessToken, refreshToken, profile, done) { - User.findOne({ + <% if (filters.mongooseModels) { %>User.findOneAsync({<% } + if (filters.sequelizeModels) { %>User.find({<% } %> 'facebook.id': profile.id - }, - function(err, user) { - if (err) { - return done(err); - } - if (!user) { - user = new User({ - name: profile.displayName, - email: profile.emails[0].value, - role: 'user', - username: profile.username, - provider: 'facebook', - facebook: profile._json - }); - user.save(function(err) { - if (err) { - done(err); - } - return done(err, user); - }); - } else { - return done(err, user); - } }) + .then(function(user) { + if (!user) { + <% if (filters.mongooseModels) { %>user = new User({<% } + if (filters.sequelizeModels) { %>user = User.build({<% } %> + name: profile.displayName, + email: profile.emails[0].value, + role: 'user', + username: profile.username, + provider: 'facebook', + facebook: profile._json + }); + <% if (filters.mongooseModels) { %>user.saveAsync()<% } + if (filters.sequelizeModels) { %>user.save()<% } %> + .then(function(user) { + return done(null, user); + }) + .catch(function(err) { + return done(err); + }); + } else { + return done(null, user); + } + }) + .catch(function(err) { + return done(err); + }); })); }; diff --git a/app/templates/server/auth(auth)/google(googleAuth)/passport.js b/app/templates/server/auth(auth)/google(googleAuth)/passport.js index 0e7a3602d..0c9462a8d 100644 --- a/app/templates/server/auth(auth)/google(googleAuth)/passport.js +++ b/app/templates/server/auth(auth)/google(googleAuth)/passport.js @@ -8,27 +8,35 @@ exports.setup = function(User, config) { callbackURL: config.google.callbackURL }, function(accessToken, refreshToken, profile, done) { - User.findOne({ + <% if (filters.mongooseModels) { %>User.findOneAsync({<% } + if (filters.sequelizeModels) { %>User.find({<% } %> 'google.id': profile.id - }, function(err, user) { - if (!user) { - user = new User({ - name: profile.displayName, - email: profile.emails[0].value, - role: 'user', - username: profile.username, - provider: 'google', - google: profile._json - }); - user.save(function(err) { - if (err) { - done(err); - } - return done(err, user); - }); - } else { - return done(err, user); - } - }); + }) + .then(function(user) { + if (!user) { + <% if (filters.mongooseModels) { %>user = new User({<% } + if (filters.sequelizeModels) { %>user = User.build({<% } %> + name: profile.displayName, + email: profile.emails[0].value, + role: 'user', + username: profile.username, + provider: 'google', + google: profile._json + }); + <% if (filters.mongooseModels) { %>user.saveAsync()<% } + if (filters.sequelizeModels) { %>user.save()<% } %> + .then(function(user) { + return done(null, user); + }) + .catch(function(err) { + return done(err); + }); + } else { + return done(null, user); + } + }) + .catch(function(err) { + return done(err); + }); })); }; diff --git a/app/templates/server/auth(auth)/index.js b/app/templates/server/auth(auth)/index.js index b930ad93f..75ddfdcb8 100644 --- a/app/templates/server/auth(auth)/index.js +++ b/app/templates/server/auth(auth)/index.js @@ -2,8 +2,9 @@ var express = require('express'); var passport = require('passport'); -var config = require('../config/environment'); -var User = require('../api/user/user.model'); +var config = require('../config/environment');<% if (filters.mongooseModels) { %> +var User = require('../api/user/user.model');<% } %><% if (filters.sequelizeModels) { %> +var User = require('../sqldb').User;<% } %> // Passport Configuration require('./local/passport').setup(User, config);<% if (filters.facebookAuth) { %> diff --git a/app/templates/server/auth(auth)/local/passport.js b/app/templates/server/auth(auth)/local/passport.js index f4898b73a..2bd3366f8 100644 --- a/app/templates/server/auth(auth)/local/passport.js +++ b/app/templates/server/auth(auth)/local/passport.js @@ -1,18 +1,16 @@ var passport = require('passport'); var LocalStrategy = require('passport-local').Strategy; -exports.setup = function(User, config) { - passport.use(new LocalStrategy({ - usernameField: 'email', - passwordField: 'password' // this is the virtual field on the model - }, function(email, password, done) { - User.findOne({ +function localAuthenticate(User, email, password, done) { + <% if (filters.mongooseModels) { %>User.findOneAsync({ + email: email.toLowerCase() + })<% } + if (filters.sequelizeModels) { %>User.find({ + where: { email: email.toLowerCase() - }, function(err, user) { - if (err) { - return done(err); - } - + } + })<% } %> + .then(function(user) { if (!user) { return done(null, false, { message: 'This email is not registered.' @@ -30,6 +28,17 @@ exports.setup = function(User, config) { return done(null, user); } }); + }) + .catch(function(err) { + return done(err); }); - })); +} + +exports.setup = function(User, config) { + passport.use(new LocalStrategy({ + usernameField: 'email', + passwordField: 'password' // this is the virtual field on the model + }, function(email, password, done) {<% if (filters.models) { %> + return localAuthenticate(User, email, password, done); +<% } %> })); }; diff --git a/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js b/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js index 7428e8afd..bf23bd3ba 100644 --- a/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js +++ b/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js @@ -8,29 +8,34 @@ exports.setup = function(User, config) { callbackURL: config.twitter.callbackURL }, function(token, tokenSecret, profile, done) { - User.findOne({ + <% if (filters.mongooseModels) { %>User.findOneAsync({<% } + if (filters.sequelizeModels) { %>User.find({<% } %> 'twitter.id_str': profile.id - }, function(err, user) { - if (err) { + }) + .then(function(user) { + if (!user) { + <% if (filters.mongooseModels) { %>user = new User({<% } + if (filters.sequelizeModels) { %>user = User.build({<% } %> + name: profile.displayName, + username: profile.username, + role: 'user', + provider: 'twitter', + twitter: profile._json + }); + <% if (filters.mongooseModels) { %>user.saveAsync()<% } + if (filters.sequelizeModels) { %>user.save()<% } %> + .then(function(user) { + return done(null, user); + }) + .catch(function(err) { + return done(err); + }); + } else { + return done(null, user); + } + }) + .catch(function(err) { return done(err); - } - if (!user) { - user = new User({ - name: profile.displayName, - username: profile.username, - role: 'user', - provider: 'twitter', - twitter: profile._json - }); - user.save(function(err) { - if (err) { - return done(err); - } - return done(err, user); - }); - } else { - return done(err, user); - } - }); + }); })); }; diff --git a/app/templates/server/config/environment/development.js b/app/templates/server/config/environment/development.js index fb33d6eab..20656595b 100644 --- a/app/templates/server/config/environment/development.js +++ b/app/templates/server/config/environment/development.js @@ -7,6 +7,16 @@ module.exports = { mongo: { uri: 'mongodb://localhost/<%= _.slugify(appname) %>-dev' }, + sequelize: { + uri: 'sqlite://', + options: { + logging: false, + storage: 'dev.sqlite', + define: { + timestamps: false + } + } + }, seedDB: true }; diff --git a/app/templates/server/config/environment/test.js b/app/templates/server/config/environment/test.js index 6ead6e1aa..021938424 100644 --- a/app/templates/server/config/environment/test.js +++ b/app/templates/server/config/environment/test.js @@ -6,5 +6,15 @@ module.exports = { // MongoDB connection options mongo: { uri: 'mongodb://localhost/<%= _.slugify(appname) %>-test' + }, + sequelize: { + uri: 'sqlite://', + options: { + logging: false, + storage: 'test.sqlite', + define: { + timestamps: false + } + } } }; diff --git a/app/templates/server/config/express.js b/app/templates/server/config/express.js index f44999c1e..9a2018263 100644 --- a/app/templates/server/config/express.js +++ b/app/templates/server/config/express.js @@ -15,9 +15,9 @@ var errorHandler = require('errorhandler'); var path = require('path'); var config = require('./environment');<% if (filters.auth) { %> var passport = require('passport');<% } %><% if (filters.twitterAuth) { %> -var session = require('express-session'); +var session = require('express-session');<% if (filters.mongoose) { %> var mongoStore = require('connect-mongo')(session); -var mongoose = require('mongoose-bird')();<% } %> +var mongoose = require('mongoose-bird')();<% } %><% } %> module.exports = function(app) { var env = app.get('env'); @@ -33,13 +33,13 @@ module.exports = function(app) { app.use(cookieParser());<% if (filters.auth) { %> app.use(passport.initialize());<% } %><% if (filters.twitterAuth) { %> - // Persist sessions with mongoStore + // Persist sessions with mongoStore / sequelizeStore // We need to enable sessions for passport twitter because its an oauth 1.0 strategy app.use(session({ secret: config.secrets.session, resave: true, - saveUninitialized: true, - store: new mongoStore({ mongoose_connection: mongoose.connection }) + saveUninitialized: true<% if (filters.mongoose) { %>, + store: new mongoStore({ mongoose_connection: mongoose.connection })<% } %> })); <% } %> app.set('appPath', path.join(config.root, 'client')); diff --git a/app/templates/server/config/seed(mongoose).js b/app/templates/server/config/seed(models).js similarity index 64% rename from app/templates/server/config/seed(mongoose).js rename to app/templates/server/config/seed(models).js index 1f6945d8d..635658010 100644 --- a/app/templates/server/config/seed(mongoose).js +++ b/app/templates/server/config/seed(models).js @@ -4,13 +4,22 @@ */ 'use strict'; - +<% if (filters.mongooseModels) { %> var Thing = require('../api/thing/thing.model'); <% if (filters.auth) { %>var User = require('../api/user/user.model');<% } %> - -Thing.find({}).removeAsync() +<% } %><% if (filters.sequelizeModels) { %> +var sqldb = require('../sqldb'); +var Thing = sqldb.Thing; +<% if (filters.auth) { %>var User = sqldb.User;<% } %> +<% } %> +<% if (filters.mongooseModels) { %>Thing.find({}).removeAsync()<% } + if (filters.sequelizeModels) { %>Thing.sync() + .then(function() { + return Thing.destroy(); + })<% } %> .then(function() { - Thing.create({ + <% if (filters.mongooseModels) { %>Thing.create({<% } + if (filters.sequelizeModels) { %>Thing.bulkCreate([{<% } %> name : 'Development Tools', info : 'Integration with popular tools such as Bower, Grunt, Karma, ' + 'Mocha, JSHint, Node Inspector, Livereload, Protractor, Jade, ' + @@ -37,12 +46,18 @@ Thing.find({}).removeAsync() name : 'Deployment Ready', info : 'Easily deploy your app to Heroku or Openshift with the heroku ' + 'and openshift subgenerators' - }); + <% if (filters.mongooseModels) { %>});<% } + if (filters.sequelizeModels) { %>}]);<% } %> }); <% if (filters.auth) { %> -User.find({}).removeAsync() +<% if (filters.mongooseModels) { %>User.find({}).removeAsync()<% } + if (filters.sequelizeModels) { %>User.sync() + .then(function() { + User.destroy(); + })<% } %> .then(function() { - User.create({ + <% if (filters.mongooseModels) { %>User.createAsync({<% } + if (filters.sequelizeModels) { %>User.bulkCreate([{<% } %> provider: 'local', name: 'Test User', email: 'test@test.com', @@ -53,8 +68,9 @@ User.find({}).removeAsync() name: 'Admin', email: 'admin@admin.com', password: 'admin' - }, function() { + <% if (filters.mongooseModels) { %>})<% } + if (filters.sequelizeModels) { %>}])<% } %> + .then(function() { console.log('finished populating users'); }); - }); -<% } %> \ No newline at end of file + });<% } %> diff --git a/app/templates/server/sqldb(sequelize)/index.js b/app/templates/server/sqldb(sequelize)/index.js new file mode 100644 index 000000000..231db9823 --- /dev/null +++ b/app/templates/server/sqldb(sequelize)/index.js @@ -0,0 +1,35 @@ +/** + * Sequelize initialization module + */ + +'use strict'; + +var path = require('path'); +var config = require('../config/environment'); + +var Sequelize = require('sequelize'); + +var db = { + Sequelize: Sequelize, + sequelize: new Sequelize(config.sequelize.uri, config.sequelize.options) +}; +<% if (filters.sequelizeModels) { %> +db.Thing = db.sequelize.import(path.join( + config.root, + 'server', + 'api', + 'thing', + 'thing.model' +)); +<% if (filters.auth) { %> +db.User = db.sequelize.import(path.join( + config.root, + 'server', + 'api', + 'user', + 'user.model' +)); +<% } %><% } %> +// Insert models below + +module.exports = db; diff --git a/endpoint/index.js b/endpoint/index.js index d67f78e51..f870c265f 100644 --- a/endpoint/index.js +++ b/endpoint/index.js @@ -25,11 +25,24 @@ Generator.prototype.askFor = function askFor() { name = name + 's'; } + var self = this; var prompts = [ { name: 'route', message: 'What will the url of your endpoint to be?', default: base + name + }, + { + type: 'list', + name: 'models', + message: 'What would you like to use for the endpoint\'s models?', + choices: [ 'Mongoose', 'Sequelize' ], + filter: function( val ) { + return val.toLowerCase(); + }, + when: function() { + return self.filters.mongoose && self.filters.sequelize; + } } ]; @@ -39,6 +52,16 @@ Generator.prototype.askFor = function askFor() { } this.route = props.route; + + if (props.models) { + delete this.filters.mongoose; + delete this.filters.mongooseModels; + delete this.filters.sequelize; + delete this.filters.sequelizeModels; + + this.filters[props.models] = true; + this.filters[props.models + 'Models'] = true; + } done(); }.bind(this)); }; @@ -67,6 +90,25 @@ Generator.prototype.registerEndpoint = function registerEndpoint() { ngUtil.rewriteFile(socketConfig); } } + + if (this.filters.sequelize) { + if (this.config.get('insertModels')) { + var modelConfig = { + file: this.config.get('registerModelsFile'), + needle: this.config.get('modelsNeedle'), + splicable: [ + "db." + this.classedName + " = db.sequelize.import(path.join(\n" + + " config.root,\n" + + " 'server',\n" + + " 'api',\n" + + " '" + this.name + "',\n" + + " '" + this.name + ".model'\n" + + "));" + ] + }; + ngUtil.rewriteFile(modelConfig); + } + } }; Generator.prototype.createFiles = function createFiles() { diff --git a/endpoint/templates/name.model(sequelize).js b/endpoint/templates/name.model(sequelize).js new file mode 100644 index 000000000..051c5daf2 --- /dev/null +++ b/endpoint/templates/name.model(sequelize).js @@ -0,0 +1,15 @@ +'use strict'; + +module.exports = function(sequelize, DataTypes) { + return sequelize.define('<%= classedName %>', { + _id: { + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true, + autoIncrement: true + }, + name: DataTypes.STRING, + info: DataTypes.STRING, + active: DataTypes.BOOLEAN + }); +}; diff --git a/endpoint/templates/name.socket(socketio).js b/endpoint/templates/name.socket(socketio).js index 260c80720..e55dfcac0 100644 --- a/endpoint/templates/name.socket(socketio).js +++ b/endpoint/templates/name.socket(socketio).js @@ -3,15 +3,24 @@ */ 'use strict'; +<% if (filters.mongoose) { %> +var <%= classedName %> = require('./<%= name %>.model');<% } %><% if (filters.sequelize) { %> +var <%= classedName %> = require('../../sqldb').<%= classedName %>;<% } %> -var <%= classedName %> = require('./<%= name %>.model'); - -exports.register = function(socket) { - <%= classedName %>.schema.post('save', function(doc) { +exports.register = function(socket) {<% if (filters.sequelize) { %> + <%= classedName %>.hook('afterCreate', function(doc, fields, fn) { onSave(socket, doc); + fn(null); + });<% } %> + <% if (filters.mongoose) { %><%= classedName %>.schema.post('save', function(doc) {<% } + if (filters.sequelize) { %><%= classedName %>.hook('afterUpdate', function(doc, fields, fn) {<% } %> + onSave(socket, doc);<% if (filters.sequelize) { %> + fn(null);<% } %> }); - <%= classedName %>.schema.post('remove', function(doc) { - onRemove(socket, doc); + <% if (filters.mongoose) { %><%= classedName %>.schema.post('remove', function(doc) {<% } + if (filters.sequelize) { %><%= classedName %>.hook('afterDestroy', function(doc, fields, fn) {<% } %> + onRemove(socket, doc);<% if (filters.sequelize) { %> + fn(null);<% } %> }); }; diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 6164b690b..0e227efef 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -18,7 +18,7 @@ describe('angular-fullstack generator', function () { chai: 'expect', bootstrap: true, uibootstrap: true, - mongoose: true, + odms: [ 'mongoose' ], auth: true, oauth: [], socketio: true @@ -153,7 +153,8 @@ describe('angular-fullstack generator', function () { var script = mapping.script[ops.script], markup = mapping.markup[ops.markup], - stylesheet = mapping.stylesheet[ops.stylesheet]; + stylesheet = mapping.stylesheet[ops.stylesheet], + models = ops.models ? ops.models : ops.odms[0]; /* Core Files */ files = files.concat([ @@ -224,14 +225,21 @@ describe('angular-fullstack generator', function () { ]); } - /* Mongoose */ - if (ops.mongoose) { + /* Models - Mongoose or Sequelize */ + if (models) { files = files.concat([ 'server/api/thing/thing.model.js', 'server/config/seed.js' ]); } + /* Sequelize */ + if (ops.odms.indexOf('sequelize') !== -1) { + files = files.concat([ + 'server/sqldb/index.js' + ]); + } + /* Authentication */ if (ops.auth) { files = files.concat([ @@ -475,7 +483,79 @@ describe('angular-fullstack generator', function () { stylesheet: 'less', router: 'uirouter', testing: 'jasmine', - mongoose: true, + odms: [ 'mongoose' ], + auth: true, + oauth: ['twitterAuth', 'facebookAuth', 'googleAuth'], + socketio: true, + bootstrap: true, + uibootstrap: true + }; + + beforeEach(function() { + helpers.mockPrompt(gen, testOptions); + }); + + it('should run client tests successfully', function(done) { + runTest('grunt test:client', this, done); + }); + + it('should pass jscs', function(done) { + runTest('grunt jscs', this, done); + }); + + it('should pass lint', function(done) { + runTest('grunt jshint', this, done); + }); + + it('should run server tests successfully', function(done) { + runTest('grunt test:server', this, done); + }); + + it('should pass jscs with generated endpoint', function(done) { + runTest('grunt jscs', this, done, 'foo'); + }); + + it('should pass lint with generated snake-case endpoint', function(done) { + runTest('grunt jshint', this, done, 'foo-bar'); + }); + + it('should run server tests successfully with generated snake-case endpoint', function(done) { + runTest('grunt test:server', this, done, 'foo-bar'); + }); + + it('should generate expected files', function (done) { + gen.run({}, function () { + helpers.assertFile(genFiles(testOptions)); + done(); + }); + }); + + it('should not generate unexpected files', function (done) { + gen.run({}, function () { + assertOnlyFiles(genFiles(testOptions), done); + }); + }); + + if(!process.env.SKIP_E2E) { + it('should run e2e tests successfully', function (done) { + runTest('grunt test:e2e', this, done, 240000); + }); + + //it('should run e2e tests successfully for production app', function (done) { + // runTest('grunt test:e2e:prod', this, done, 240000); + //}); + } + + }); + + describe('with sequelize models, auth', function() { + var testOptions = { + script: 'js', + markup: 'jade', + stylesheet: 'stylus', + router: 'uirouter', + testing: 'jasmine', + odms: [ 'sequelize' ], auth: true, oauth: ['twitterAuth', 'facebookAuth', 'googleAuth'], socketio: true, @@ -548,7 +628,7 @@ describe('angular-fullstack generator', function () { router: 'ngroute', testing: 'mocha', chai: 'should', - mongoose: false, + odms: [], auth: false, oauth: [], socketio: false, @@ -621,7 +701,7 @@ describe('angular-fullstack generator', function () { stylesheet: 'css', router: 'ngroute', testing: 'jasmine', - mongoose: false, + odms: [], auth: false, oauth: [], socketio: false, From 38c0d7cf68a74bc7f2bcf8b43697a30b695e2066 Mon Sep 17 00:00:00 2001 From: dotch Date: Thu, 27 Nov 2014 14:07:02 +0100 Subject: [PATCH 0062/1357] fix: return a 404 when no user is found fixes #711 --- app/templates/server/api/user(auth)/user.controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/server/api/user(auth)/user.controller.js b/app/templates/server/api/user(auth)/user.controller.js index 793da0255..8c25c85f6 100644 --- a/app/templates/server/api/user(auth)/user.controller.js +++ b/app/templates/server/api/user(auth)/user.controller.js @@ -64,7 +64,7 @@ exports.show = function(req, res, next) { User.findByIdAsync(userId) .then(function(user) { if (!user) { - return res.send(401); + return res.send(404); } res.json(user.profile); }) From 00bb37c5f9a07b37a5331c0dee8f4d288dc7747c Mon Sep 17 00:00:00 2001 From: Rusty Green Date: Sun, 28 Dec 2014 13:44:20 -0500 Subject: [PATCH 0063/1357] Fixed typo in Modal service comments. Fixed missing "r" in word "straight" in comment. --- .../client/components/modal(uibootstrap)/modal.service(js).js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/client/components/modal(uibootstrap)/modal.service(js).js b/app/templates/client/components/modal(uibootstrap)/modal.service(js).js index f01200174..1de615d73 100644 --- a/app/templates/client/components/modal(uibootstrap)/modal.service(js).js +++ b/app/templates/client/components/modal(uibootstrap)/modal.service(js).js @@ -39,7 +39,7 @@ angular.module('<%= scriptAppName %>') /** * Open a delete confirmation modal * @param {String} name - name or info to show on modal - * @param {All} - any additional args are passed staight to del callback + * @param {All} - any additional args are passed straight to del callback */ return function() { var args = Array.prototype.slice.call(arguments), From bb4d92e3050c2ca08a571f32632dab50ac430b5b Mon Sep 17 00:00:00 2001 From: Mark Chapman Date: Wed, 31 Dec 2014 16:31:11 +0000 Subject: [PATCH 0064/1357] fix(gen:build): Adds missing slash fix(gen:build): Adds missing slash Adds missing slash --- app/templates/Gruntfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 6755db958..6cf80f394 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -137,7 +137,7 @@ module.exports = function (grunt) { '{.tmp,<%%= yeoman.client %>}/{app,components}/**/*.css', '{.tmp,<%%= yeoman.client %>}/{app,components}/**/*.html', '{.tmp,<%%= yeoman.client %>}/{app,components}/**/*.js', - '!{.tmp,<%%= yeoman.client %>}{app,components}/**/*.spec.js', + '!{.tmp,<%%= yeoman.client %>}/{app,components}/**/*.spec.js', '!{.tmp,<%%= yeoman.client %>}/{app,components}/**/*.mock.js', '<%%= yeoman.client %>/assets/images/{,*//*}*.{png,jpg,jpeg,gif,webp,svg}' ], From af69a682f60daf9842df388877f4876d4fae9178 Mon Sep 17 00:00:00 2001 From: Tyler Henkel Date: Fri, 23 Jan 2015 00:10:58 -0700 Subject: [PATCH 0065/1357] style(jscs): update jscs definition to use settings closer to the angular repo --- app/templates/.jscs.json | 42 ++++++++++++++++--- .../api/thing/thing.controller(noModels).js | 34 +++++++-------- .../server/config/environment/index.js | 12 +++--- app/templates/server/config/seed(models).js | 24 +++++------ 4 files changed, 72 insertions(+), 40 deletions(-) diff --git a/app/templates/.jscs.json b/app/templates/.jscs.json index 1c278d0c4..31df3b6cb 100644 --- a/app/templates/.jscs.json +++ b/app/templates/.jscs.json @@ -1,12 +1,44 @@ { - "preset": "google", "maximumLineLength": { "value": 100, "allowComments": true, "allowRegex": true }, - "requireCamelCaseOrUpperCaseIdentifiers": "ignoreProperties", - "requireSpacesInsideObjectBrackets": "all", - "disallowSpacesInsideObjectBrackets": "nested", - "requireSpacesInConditionalExpression": true + "disallowMixedSpacesAndTabs": true, + "disallowMultipleLineStrings": true, + "disallowNewlineBeforeBlockStatements": true, + "disallowSpaceAfterObjectKeys": true, + "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"], + "disallowSpaceBeforeBinaryOperators": [","], + "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"], + "disallowSpacesInAnonymousFunctionExpression": { + "beforeOpeningRoundBrace": true + }, + "disallowSpacesInFunctionDeclaration": { + "beforeOpeningRoundBrace": true + }, + "disallowSpacesInNamedFunctionExpression": { + "beforeOpeningRoundBrace": true + }, + "disallowSpacesInsideArrayBrackets": true, + "disallowSpacesInsideParentheses": true, + "disallowTrailingComma": true, + "disallowTrailingWhitespace": true, + "requireCommaBeforeLineBreak": true, + "requireLineFeedAtFileEnd": true, + "requireSpaceAfterBinaryOperators": ["?", ":", "+", "-", "/", "*", "%", "==", "===", "!=", "!==", ">", ">=", "<", "<=", "&&", "||"], + "requireSpaceBeforeBinaryOperators": ["?", ":", "+", "-", "/", "*", "%", "==", "===", "!=", "!==", ">", ">=", "<", "<=", "&&", "||"], + "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"], + "requireSpaceBeforeBlockStatements": true, + "requireSpacesInConditionalExpression": { + "afterTest": true, + "beforeConsequent": true, + "afterConsequent": true, + "beforeAlternate": true + }, + "requireSpacesInFunction": { + "beforeOpeningCurlyBrace": true + }, + "validateLineBreaks": "LF", + "validateParameterSeparator": ", " } \ No newline at end of file diff --git a/app/templates/server/api/thing/thing.controller(noModels).js b/app/templates/server/api/thing/thing.controller(noModels).js index 02b2410c5..a39041258 100644 --- a/app/templates/server/api/thing/thing.controller(noModels).js +++ b/app/templates/server/api/thing/thing.controller(noModels).js @@ -12,27 +12,27 @@ // Get list of things exports.index = function(req, res) { res.json([{ - name : 'Development Tools', - info : 'Integration with popular tools such as Bower, Grunt, Karma, Mocha, JSHint, ' + - 'Node Inspector, Livereload, Protractor, Jade, Stylus, Sass, CoffeeScript, and Less.' + name: 'Development Tools', + info: 'Integration with popular tools such as Bower, Grunt, Karma, Mocha, JSHint, ' + + 'Node Inspector, Livereload, Protractor, Jade, Stylus, Sass, CoffeeScript, and Less.' }, { - name : 'Server and Client integration', - info : 'Built with a powerful and fun stack: MongoDB, Express, AngularJS, and Node.' + name: 'Server and Client integration', + info: 'Built with a powerful and fun stack: MongoDB, Express, AngularJS, and Node.' }, { - name : 'Smart Build System', - info : 'Build system ignores `spec` files, allowing you to keep tests alongside code. ' + - 'Automatic injection of scripts and styles into your index.html' + name: 'Smart Build System', + info: 'Build system ignores `spec` files, allowing you to keep tests alongside code. ' + + 'Automatic injection of scripts and styles into your index.html' }, { - name : 'Modular Structure', - info : 'Best practice client and server structures allow for more code reusability and ' + - 'maximum scalability' + name: 'Modular Structure', + info: 'Best practice client and server structures allow for more code reusability and ' + + 'maximum scalability' }, { - name : 'Optimized Build', - info : 'Build process packs up your templates as a single JavaScript payload, minifies ' + - 'your scripts/css/images, and rewrites asset names for caching.' + name: 'Optimized Build', + info: 'Build process packs up your templates as a single JavaScript payload, minifies ' + + 'your scripts/css/images, and rewrites asset names for caching.' }, { - name : 'Deployment Ready', - info : 'Easily deploy your app to Heroku or Openshift with the heroku and openshift ' + - 'subgenerators' + name: 'Deployment Ready', + info: 'Easily deploy your app to Heroku or Openshift with the heroku and openshift ' + + 'sub-generators' }]); }; diff --git a/app/templates/server/config/environment/index.js b/app/templates/server/config/environment/index.js index 2476a7e8c..fa98bbe03 100644 --- a/app/templates/server/config/environment/index.js +++ b/app/templates/server/config/environment/index.js @@ -39,20 +39,20 @@ var all = { safe: true } } - }, -<% if (filters.facebookAuth) { %> + }<% if (filters.facebookAuth) { %>, + facebook: { clientID: process.env.FACEBOOK_ID || 'id', clientSecret: process.env.FACEBOOK_SECRET || 'secret', callbackURL: (process.env.DOMAIN || '') + '/auth/facebook/callback' - }, -<% } %><% if (filters.twitterAuth) { %> + }<% } %><% if (filters.twitterAuth) { %>, + twitter: { clientID: process.env.TWITTER_ID || 'id', clientSecret: process.env.TWITTER_SECRET || 'secret', callbackURL: (process.env.DOMAIN || '') + '/auth/twitter/callback' - }, -<% } %><% if (filters.googleAuth) { %> + }<% } %><% if (filters.googleAuth) { %>, + google: { clientID: process.env.GOOGLE_ID || 'id', clientSecret: process.env.GOOGLE_SECRET || 'secret', diff --git a/app/templates/server/config/seed(models).js b/app/templates/server/config/seed(models).js index 635658010..6591f16bc 100644 --- a/app/templates/server/config/seed(models).js +++ b/app/templates/server/config/seed(models).js @@ -20,31 +20,31 @@ var Thing = sqldb.Thing; .then(function() { <% if (filters.mongooseModels) { %>Thing.create({<% } if (filters.sequelizeModels) { %>Thing.bulkCreate([{<% } %> - name : 'Development Tools', - info : 'Integration with popular tools such as Bower, Grunt, Karma, ' + + name: 'Development Tools', + info: 'Integration with popular tools such as Bower, Grunt, Karma, ' + 'Mocha, JSHint, Node Inspector, Livereload, Protractor, Jade, ' + 'Stylus, Sass, CoffeeScript, and Less.' }, { - name : 'Server and Client integration', - info : 'Built with a powerful and fun stack: MongoDB, Express, ' + + name: 'Server and Client integration', + info: 'Built with a powerful and fun stack: MongoDB, Express, ' + 'AngularJS, and Node.' }, { - name : 'Smart Build System', - info : 'Build system ignores `spec` files, allowing you to keep ' + + name: 'Smart Build System', + info: 'Build system ignores `spec` files, allowing you to keep ' + 'tests alongside code. Automatic injection of scripts and ' + 'styles into your index.html' }, { - name : 'Modular Structure', - info : 'Best practice client and server structures allow for more ' + + name: 'Modular Structure', + info: 'Best practice client and server structures allow for more ' + 'code reusability and maximum scalability' }, { - name : 'Optimized Build', - info : 'Build process packs up your templates as a single JavaScript ' + + name: 'Optimized Build', + info: 'Build process packs up your templates as a single JavaScript ' + 'payload, minifies your scripts/css/images, and rewrites asset ' + 'names for caching.' }, { - name : 'Deployment Ready', - info : 'Easily deploy your app to Heroku or Openshift with the heroku ' + + name: 'Deployment Ready', + info: 'Easily deploy your app to Heroku or Openshift with the heroku ' + 'and openshift subgenerators' <% if (filters.mongooseModels) { %>});<% } if (filters.sequelizeModels) { %>}]);<% } %> From c97df6c7175956b3a34ba94b7d3ee562e2161be4 Mon Sep 17 00:00:00 2001 From: Michael Whitley Date: Thu, 29 Jan 2015 15:24:16 -0600 Subject: [PATCH 0066/1357] docs: changing from mongohq to mongolab MongoHQ has removed their free plan from heroku. Executing the current add results in a recurring monthly charge. MongoLab has a free sandbox plan --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 209a6356b..0ab578ad8 100644 --- a/readme.md +++ b/readme.md @@ -261,7 +261,7 @@ To work with your new heroku app using the command line, you will need to run an If you're using mongoDB you will need to add a database to your app: - heroku addons:add mongohq + heroku addons:add mongolab Your app should now be live. To view it run `heroku open`. From e02f09405de2423d7be92e5ca0f9be740becb693 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 3 Mar 2015 21:10:52 -0500 Subject: [PATCH 0067/1357] fix(jshint): Removed 'regexp' from server and client jshintrc (I couldn't find it in the docs anywhere), and removed deprecated 'indent' option from client jshintrc JSCS should be used for code style checking --- app/templates/client/.jshintrc | 2 -- app/templates/server/.jshintrc | 1 - 2 files changed, 3 deletions(-) diff --git a/app/templates/client/.jshintrc b/app/templates/client/.jshintrc index 52c6a6d79..8c5c42c0a 100644 --- a/app/templates/client/.jshintrc +++ b/app/templates/client/.jshintrc @@ -7,12 +7,10 @@ "curly": true, "eqeqeq": true, "immed": true, - "indent": 2, "latedef": true, "newcap": true, "noarg": true, "quotmark": "single", - "regexp": true, "undef": true, "unused": true, "strict": true, diff --git a/app/templates/server/.jshintrc b/app/templates/server/.jshintrc index d7b958e7c..66d1af7c9 100644 --- a/app/templates/server/.jshintrc +++ b/app/templates/server/.jshintrc @@ -7,7 +7,6 @@ "latedef": "nofunc", "newcap": true, "noarg": true, - "regexp": true, "undef": true, "smarttabs": true, "asi": true, From be22d744aab6cba8e837a6bf120719d576dda400 Mon Sep 17 00:00:00 2001 From: Andrew Ryabinin Date: Mon, 23 Mar 2015 15:07:34 +0200 Subject: [PATCH 0068/1357] Update passport.js In default variant if we have an error the code will continue executing --- .../server/auth(auth)/google(googleAuth)/passport.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/server/auth(auth)/google(googleAuth)/passport.js b/app/templates/server/auth(auth)/google(googleAuth)/passport.js index d304e8ac9..c9754c83a 100644 --- a/app/templates/server/auth(auth)/google(googleAuth)/passport.js +++ b/app/templates/server/auth(auth)/google(googleAuth)/passport.js @@ -21,8 +21,8 @@ exports.setup = function (User, config) { google: profile._json }); user.save(function(err) { - if (err) done(err); - return done(err, user); + if (err) return done(err); + done(err, user); }); } else { return done(err, user); From 97f01cfb4774a1506fc40069bf49a132bcc1e705 Mon Sep 17 00:00:00 2001 From: Andrew Ryabinin Date: Mon, 23 Mar 2015 15:09:00 +0200 Subject: [PATCH 0069/1357] Update passport.js In default variant if we have an error the code will continue executing --- .../server/auth(auth)/facebook(facebookAuth)/passport.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js b/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js index 90ae48939..54574efb6 100644 --- a/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js +++ b/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js @@ -25,8 +25,8 @@ exports.setup = function (User, config) { facebook: profile._json }); user.save(function(err) { - if (err) done(err); - return done(err, user); + if (err) return done(err); + done(err, user); }); } else { return done(err, user); @@ -34,4 +34,4 @@ exports.setup = function (User, config) { }) } )); -}; \ No newline at end of file +}; From 2a4434e34e4f334b1f92a71e924b91fdb6263212 Mon Sep 17 00:00:00 2001 From: Andrew Ryabinin Date: Mon, 23 Mar 2015 15:09:51 +0200 Subject: [PATCH 0070/1357] Update passport.js --- .../server/auth(auth)/twitter(twitterAuth)/passport.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js b/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js index a2eb4a537..4544ce186 100644 --- a/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js +++ b/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js @@ -24,7 +24,7 @@ exports.setup = function (User, config) { }); user.save(function(err) { if (err) return done(err); - return done(err, user); + done(err, user); }); } else { return done(err, user); @@ -32,4 +32,4 @@ exports.setup = function (User, config) { }); } )); -}; \ No newline at end of file +}; From 40e3d028bf59bc1308a3072a5108d4036c189da0 Mon Sep 17 00:00:00 2001 From: Simon Egersand Date: Sun, 5 Apr 2015 19:56:13 +0200 Subject: [PATCH 0071/1357] fix css bug --- app/templates/client/app/main/main(css).css | 4 ++++ app/templates/client/app/main/main(less).less | 4 ++++ app/templates/client/app/main/main(sass).scss | 4 ++++ app/templates/client/app/main/main(stylus).styl | 5 ++++- 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/app/templates/client/app/main/main(css).css b/app/templates/client/app/main/main(css).css index ba3408a00..c396852d6 100644 --- a/app/templates/client/app/main/main(css).css +++ b/app/templates/client/app/main/main(css).css @@ -27,4 +27,8 @@ padding: 30px 0; margin-top: 70px; border-top: 1px solid #E5E5E5; +} + +.navbar-text { + margin-left: 15px; } \ No newline at end of file diff --git a/app/templates/client/app/main/main(less).less b/app/templates/client/app/main/main(less).less index a289bac64..39636ab2d 100644 --- a/app/templates/client/app/main/main(less).less +++ b/app/templates/client/app/main/main(less).less @@ -27,4 +27,8 @@ padding: 30px 0; margin-top: 70px; border-top: 1px solid #E5E5E5; +} + +.navbar-text { + margin-left: 15px; } \ No newline at end of file diff --git a/app/templates/client/app/main/main(sass).scss b/app/templates/client/app/main/main(sass).scss index ba3408a00..aa19c3649 100644 --- a/app/templates/client/app/main/main(sass).scss +++ b/app/templates/client/app/main/main(sass).scss @@ -27,4 +27,8 @@ padding: 30px 0; margin-top: 70px; border-top: 1px solid #E5E5E5; +} + +.navbar-text { + margin-left: 15px; } \ No newline at end of file diff --git a/app/templates/client/app/main/main(stylus).styl b/app/templates/client/app/main/main(stylus).styl index 5cd9e4761..9ba91c3a3 100644 --- a/app/templates/client/app/main/main(stylus).styl +++ b/app/templates/client/app/main/main(stylus).styl @@ -22,4 +22,7 @@ border-top 1px solid #E5E5E5 margin-top 70px padding 30px 0 - text-align center \ No newline at end of file + text-align center + +.navbar-text + margin-left 15px \ No newline at end of file From 9af319ef8e099ce478c2dcfcebd28fd0de0b57ac Mon Sep 17 00:00:00 2001 From: Liran Tal Date: Sun, 12 Apr 2015 14:46:53 +0300 Subject: [PATCH 0072/1357] adding support for a default configuration paremeter for all environments to specify IP address, just like there's a port configuration by default (production.js env configuration file already references this config parameter) --- app/templates/server/config/environment/index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/templates/server/config/environment/index.js b/app/templates/server/config/environment/index.js index 11d85f4de..895d91534 100644 --- a/app/templates/server/config/environment/index.js +++ b/app/templates/server/config/environment/index.js @@ -21,6 +21,9 @@ var all = { // Server port port: process.env.PORT || 9000, + // Server IP + ip: process.env.IP || 'localhost', + // Should we populate the DB with sample data? seedDB: false, From 77cf34805311303af2ab1294566f4c92e2311c0e Mon Sep 17 00:00:00 2001 From: Yinzer Date: Sat, 18 Apr 2015 02:35:19 -0400 Subject: [PATCH 0073/1357] update jwt packages jwt packages have been updated due to security vulnerabilities --- app/templates/_package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index b19b58813..1a54b336b 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -16,8 +16,8 @@ "jade": "~1.2.0",<% } %><% if(filters.html) { %> "ejs": "~0.8.4",<% } %><% if(filters.mongoose) { %> "mongoose": "~3.8.8",<% } %><% if(filters.auth) { %> - "jsonwebtoken": "^0.3.0", - "express-jwt": "^0.1.3", + "jsonwebtoken": "^5.0.0", + "express-jwt": "^3.0.0", "passport": "~0.2.0", "passport-local": "~0.1.6",<% } %><% if(filters.facebookAuth) { %> "passport-facebook": "latest",<% } %><% if(filters.twitterAuth) { %> @@ -27,7 +27,7 @@ "connect-mongo": "^0.4.1"<% if(filters.socketio) { %>, "socket.io": "^1.0.6", "socket.io-client": "^1.0.6", - "socketio-jwt": "^2.0.2"<% } %> + "socketio-jwt": "^3.0.0"<% } %> }, "devDependencies": { "grunt": "~0.4.4", From 67a06cd565c45ea195545aaf845a2bfe540385b1 Mon Sep 17 00:00:00 2001 From: Kevin Woo Date: Sat, 11 Apr 2015 00:28:43 -0700 Subject: [PATCH 0074/1357] feat:app: grunt-build-control to v0.4.0 Update grunt-build-control to v0.4.0 --- app/templates/_package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index b19b58813..18b0990e4 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -60,7 +60,7 @@ "grunt-protractor-runner": "^1.1.0", "grunt-injector": "~0.5.4", "grunt-karma": "~0.8.2", - "grunt-build-control": "DaftMonk/grunt-build-control", + "grunt-build-control": "~0.4.0", "grunt-mocha-test": "~0.10.2",<% if(filters.sass) { %> "grunt-contrib-sass": "^0.7.3",<% } %><% if(filters.stylus) { %> "grunt-contrib-stylus": "latest",<% } %> From 061c2d148819dff66da9abe8f8f25dd476cefe05 Mon Sep 17 00:00:00 2001 From: Kevin Woo Date: Sat, 11 Apr 2015 00:31:12 -0700 Subject: [PATCH 0075/1357] feat:app: grunt-build-control to v0.4.0 Update grunt-build-control to v0.4.0 --- app/templates/_package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 1666ea8b0..98cd616ac 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -64,7 +64,7 @@ "grunt-protractor-runner": "^1.1.0", "grunt-injector": "~0.5.4", "grunt-karma": "~0.8.2", - "grunt-build-control": "DaftMonk/grunt-build-control",<% if (filters.sass) { %> + "grunt-build-control": "~0.4.0",<% if (filters.sass) { %> "grunt-contrib-sass": "^0.7.3",<% } %><% if (filters.stylus) { %> "grunt-contrib-stylus": "latest",<% } %> "jit-grunt": "^0.5.0", From 8ed83896703663eebe0479432f1c8e16766a3723 Mon Sep 17 00:00:00 2001 From: Frederic Le Feurmou Date: Thu, 7 May 2015 12:17:54 +0200 Subject: [PATCH 0076/1357] Update readme.md Some rhc commands were wrong --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 209a6356b..52a54f95b 100644 --- a/readme.md +++ b/readme.md @@ -230,11 +230,11 @@ A live application URL will be available in the output. > > You will also need to set `DOMAIN` environment variable: > -> rhc config:set DOMAIN=.rhcloud.com +> rhc set-env DOMAIN=.rhcloud.com > > # or (if you're using it): > -> rhc config:set DOMAIN= +> rhc set-env DOMAIN= > > After you've set the required environment variables, restart the server: > From 7b289d896f88efe414994657140814b0bbe51cd9 Mon Sep 17 00:00:00 2001 From: nleir Date: Mon, 25 May 2015 19:09:12 -0400 Subject: [PATCH 0077/1357] Update _bower.json so you can use the app client as a github page --- app/templates/_bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/_bower.json b/app/templates/_bower.json index ce22650fb..156d04b32 100644 --- a/app/templates/_bower.json +++ b/app/templates/_bower.json @@ -15,7 +15,7 @@ "font-awesome": ">=4.1.0", "lodash": "~2.4.1"<% if(filters.socketio) { %>, "angular-socket-io": "~0.6.0"<% } %><% if(filters.uirouter) { %>, - "angular-ui-router": "~0.2.10"<% } %> + "angular-ui-router": "~0.2.15"<% } %> }, "devDependencies": { "angular-mocks": ">=1.2.*", From 366d03297e3cc76928a7fa7aaac0e209baad2221 Mon Sep 17 00:00:00 2001 From: Denis Ciccale Date: Tue, 2 Jun 2015 11:28:46 +0200 Subject: [PATCH 0078/1357] chore(admin): splice user without iteration --- .../client/app/admin(auth)/admin.controller(coffee).coffee | 2 +- .../client/app/admin(auth)/admin.controller(js).js | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/app/templates/client/app/admin(auth)/admin.controller(coffee).coffee b/app/templates/client/app/admin(auth)/admin.controller(coffee).coffee index 7a16032da..5183df059 100644 --- a/app/templates/client/app/admin(auth)/admin.controller(coffee).coffee +++ b/app/templates/client/app/admin(auth)/admin.controller(coffee).coffee @@ -9,4 +9,4 @@ angular.module '<%= scriptAppName %>' $scope.delete = (user) -> User.remove id: user._id - _.remove $scope.users, user \ No newline at end of file + $scope.users.splice @$index, 1 diff --git a/app/templates/client/app/admin(auth)/admin.controller(js).js b/app/templates/client/app/admin(auth)/admin.controller(js).js index 51a52b759..3cbfd4b7f 100644 --- a/app/templates/client/app/admin(auth)/admin.controller(js).js +++ b/app/templates/client/app/admin(auth)/admin.controller(js).js @@ -8,10 +8,6 @@ angular.module('<%= scriptAppName %>') $scope.delete = function(user) { User.remove({ id: user._id }); - angular.forEach($scope.users, function(u, i) { - if (u === user) { - $scope.users.splice(i, 1); - } - }); + $scope.users.splice(this.$index, 1); }; }); From bc03aba9ee82812f29f4ec9f86daf3b8d1c531b8 Mon Sep 17 00:00:00 2001 From: Carson Bruce Date: Wed, 22 Apr 2015 15:57:24 +1200 Subject: [PATCH 0079/1357] feat(app): additional app generator option for ES6 preprocessing using babel Added a follow up question to the first language selection question to enable ES6 client support with Babel. Related issue: Any plans for es6 and traceur support? #684 --- app/index.js | 11 +++++++ app/templates/Gruntfile.js | 52 ++++++++++++++++++++++++++++----- app/templates/_package.json | 3 +- app/templates/client/index.html | 4 +++ test/test-file-creation.js | 43 +++++++++++++++++++++++++++ 5 files changed, 105 insertions(+), 8 deletions(-) diff --git a/app/index.js b/app/index.js index 6e4724801..194b337a6 100644 --- a/app/index.js +++ b/app/index.js @@ -78,6 +78,13 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ return filterMap[val]; } + }, { + type: "confirm", + name: "babel", + message: "Would you like to use Javascript ES6 in your client by preprocessing it with Babel?", + when: function (answers) { + return answers.script === 'js'; + } }, { type: "list", name: "markup", @@ -110,6 +117,9 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ return answers.bootstrap; } }], function (answers) { + + this.filters.babel = !!answers.babel; + if(this.filters.babel){ this.filters.js = true; } this.filters[answers.script] = true; this.filters[answers.markup] = true; this.filters[answers.stylesheet] = true; @@ -211,6 +221,7 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ if(this.filters.ngroute) filters.push('ngroute'); if(this.filters.uirouter) filters.push('uirouter'); + if(this.filters.babel) extensions.push('babel'); if(this.filters.coffee) extensions.push('coffee'); if(this.filters.js) extensions.push('js'); if(this.filters.html) extensions.push('html'); diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index a0267aaa4..96a662066 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -127,6 +127,13 @@ module.exports = function (grunt) { '<%%= yeoman.client %>/{app,components}/**/*.spec.{coffee,litcoffee,coffee.md}' ], tasks: ['karma'] + },<% } %><% if(filters.babel) { %> + babel: { + files: [ + '<%%= yeoman.client %>/{app,components}/**/*.js', + '!<%%= yeoman.client %>/{app,components}/**/*.spec.js' + ], + tasks: ['babel'] },<% } %> gruntfile: { files: ['Gruntfile.js'] @@ -135,7 +142,11 @@ module.exports = function (grunt) { files: [ '{.tmp,<%%= yeoman.client %>}/{app,components}/**/*.css', '{.tmp,<%%= yeoman.client %>}/{app,components}/**/*.html', + <% if(filters.babel) { %> + '.tmp/{app,components}/**/*.js', + <% } else { %> '{.tmp,<%%= yeoman.client %>}/{app,components}/**/*.js', + <% } %> '!{.tmp,<%%= yeoman.client %>}{app,components}/**/*.spec.js', '!{.tmp,<%%= yeoman.client %>}/{app,components}/**/*.mock.js', '<%%= yeoman.client %>/assets/images/{,*//*}*.{png,jpg,jpeg,gif,webp,svg}' @@ -442,14 +453,16 @@ module.exports = function (grunt) { // Run some tasks in parallel to speed up the build process concurrent: { server: [<% if(filters.coffee) { %> - 'coffee',<% } %><% if(filters.jade) { %> + 'coffee',<% } %><% if(filters.babel) { %> + 'babel',<% } %><% if(filters.jade) { %> 'jade',<% } %><% if(filters.stylus) { %> 'stylus',<% } %><% if(filters.sass) { %> 'sass',<% } %><% if(filters.less) { %> 'less',<% } %> ], test: [<% if(filters.coffee) { %> - 'coffee',<% } %><% if(filters.jade) { %> + 'coffee',<% } %><% if(filters.babel) { %> + 'babel',<% } %><% if(filters.jade) { %> 'jade',<% } %><% if(filters.stylus) { %> 'stylus',<% } %><% if(filters.sass) { %> 'sass',<% } %><% if(filters.less) { %> @@ -465,7 +478,8 @@ module.exports = function (grunt) { } }, dist: [<% if(filters.coffee) { %> - 'coffee',<% } %><% if(filters.jade) { %> + 'coffee',<% } %><% if(filters.babel) { %> + 'babel',<% } %><% if(filters.jade) { %> 'jade',<% } %><% if(filters.stylus) { %> 'stylus',<% } %><% if(filters.sass) { %> 'sass',<% } %><% if(filters.less) { %> @@ -551,6 +565,24 @@ module.exports = function (grunt) { ext: '.js' }] } + },<% } %><% if(filters.babel) { %> + + // Compiles ES6 to JavaScript using Babel + babel: { + options: { + sourceMap: true + }, + server: { + files: [{ + expand: true, + cwd: 'client', + src: [ + '{app,components}/**/*.js', + '!{app,components}/**/*.spec.js' + ], + dest: '.tmp' + }] + } },<% } %><% if(filters.stylus) { %> // Compiles Stylus to CSS @@ -620,10 +652,16 @@ module.exports = function (grunt) { }, files: { '<%%= yeoman.client %>/index.html': [ - ['{.tmp,<%%= yeoman.client %>}/{app,components}/**/*.js', - '!{.tmp,<%%= yeoman.client %>}/app/app.js', - '!{.tmp,<%%= yeoman.client %>}/{app,components}/**/*.spec.js', - '!{.tmp,<%%= yeoman.client %>}/{app,components}/**/*.mock.js'] + [ + <% if(filters.babel) { %> + '.tmp/{app,components}/**/*.js', + <% } else { %> + '{.tmp,<%%= yeoman.client %>}/{app,components}/**/*.js', + <% } %> + '!{.tmp,<%%= yeoman.client %>}/app/app.js', + '!{.tmp,<%%= yeoman.client %>}/{app,components}/**/*.spec.js', + '!{.tmp,<%%= yeoman.client %>}/{app,components}/**/*.mock.js' + ] ] } },<% if(filters.stylus) { %> diff --git a/app/templates/_package.json b/app/templates/_package.json index e8c64559b..5d0592941 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -45,7 +45,8 @@ "grunt-contrib-watch": "~0.6.1",<% if(filters.coffee) { %> "grunt-contrib-coffee": "^0.10.1",<% } %><% if(filters.jade) { %> "grunt-contrib-jade": "^0.11.0",<% } %><% if(filters.less) { %> - "grunt-contrib-less": "^0.11.0",<% } %> + "grunt-contrib-less": "^0.11.0",<% } %><% if(filters.babel) { %> + "grunt-babel": "~5.0.0",<% } %> "grunt-google-cdn": "~0.4.0", "grunt-newer": "~0.7.0", "grunt-ng-annotate": "^0.2.3", diff --git a/app/templates/client/index.html b/app/templates/client/index.html index e823e372d..e9dcd5729 100644 --- a/app/templates/client/index.html +++ b/app/templates/client/index.html @@ -50,7 +50,11 @@ <% } %> + <% if(filters.babel) { %> + + <% } else { %> + <% } %> diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 774a6f658..beb8b14b8 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -145,6 +145,49 @@ describe('angular-fullstack generator', function () { // }); }); + describe('with Babel ES6 preprocessor', function() { + beforeEach(function() { + helpers.mockPrompt(gen, { + script: 'js', + babel: true, + markup: 'jade', + stylesheet: 'less', + router: 'uirouter' + }); + }); + + it('should run client tests successfully', function(done) { + this.timeout(60000); + gen.run({}, function () { + exec('grunt test:client', function (error, stdout, stderr) { + expect(stdout, 'Client tests failed \n' + stdout ).to.contain('Executed 1 of 1\u001b[32m SUCCESS\u001b'); + done(); + }); + }); + }); + + it('should pass jshint', function(done) { + this.timeout(60000); + gen.run({}, function () { + exec('grunt jshint', function (error, stdout, stderr) { + expect(stdout).to.contain('Done, without errors.'); + done(); + }); + }); + }); + + it('should run server tests successfully', function(done) { + this.timeout(60000); + gen.run({}, function () { + exec('grunt test:server', function (error, stdout, stderr) { + expect(stdout, 'Server tests failed (do you have mongoDB running?) \n' + stdout).to.contain('Done, without errors.'); + done(); + }); + }); + }); + }); + + describe('with other preprocessors and oauth', function() { beforeEach(function() { helpers.mockPrompt(gen, { From 7a3b6d4b0d5c30803f1716568f02b9111cb9ace4 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 16 Jun 2015 16:32:38 -0400 Subject: [PATCH 0080/1357] docs(readme): Add Babel to list of available scripting languages --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index cca4ac419..5d11f17aa 100644 --- a/readme.md +++ b/readme.md @@ -35,7 +35,7 @@ Run `grunt` for building, `grunt serve` for preview, and `grunt serve:dist` for **Client** -* Scripts: `JavaScript`, `CoffeeScript` +* Scripts: `JavaScript`, `CoffeeScript`, `Babel` * Markup: `HTML`, `Jade` * Stylesheets: `CSS`, `Stylus`, `Sass`, `Less`, * Angular Routers: `ngRoute`, `ui-router` From cbb06a48e28c594a53f61e49857cbb711bd74ce9 Mon Sep 17 00:00:00 2001 From: Carson Bruce Date: Wed, 17 Jun 2015 09:58:45 +1200 Subject: [PATCH 0081/1357] feat(app): additional app generator option for ES6 preprocessing using babel Building on from the ES6 client preprocessor have added karma config and related karma-babel-preprocessor module for ES6 client tests for complete ES6 client support Related issue: Any plans for es6 and traceur support? #684 --- app/templates/_package.json | 1 + app/templates/karma.conf.js | 17 ++++++++++++++++- test/fixtures/bower.json | 1 - test/fixtures/package.json | 4 +++- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 5d0592941..fc374be27 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -46,6 +46,7 @@ "grunt-contrib-coffee": "^0.10.1",<% } %><% if(filters.jade) { %> "grunt-contrib-jade": "^0.11.0",<% } %><% if(filters.less) { %> "grunt-contrib-less": "^0.11.0",<% } %><% if(filters.babel) { %> + "karma-babel-preprocessor": "^5.2.1", "grunt-babel": "~5.0.0",<% } %> "grunt-google-cdn": "~0.4.0", "grunt-newer": "~0.7.0", diff --git a/app/templates/karma.conf.js b/app/templates/karma.conf.js index 57b3fa6f2..e7307a90a 100644 --- a/app/templates/karma.conf.js +++ b/app/templates/karma.conf.js @@ -36,7 +36,8 @@ module.exports = function(config) { preprocessors: { '**/*.jade': 'ng-jade2js', - '**/*.html': 'html2js', + '**/*.html': 'html2js',<% if(filters.babel) { %> + 'client/app/**/*.js': 'babel',<% } %> '**/*.coffee': 'coffee', }, @@ -48,6 +49,20 @@ module.exports = function(config) { stripPrefix: 'client/' }, + <% if(filters.babel) { %> + babelPreprocessor: { + options: { + sourceMap: 'inline' + }, + filename: function (file) { + return file.originalPath.replace(/\.js$/, '.es5.js'); + }, + sourceFileName: function (file) { + return file.originalPath; + } + }, + <% } %> + // list of files / patterns to exclude exclude: [], diff --git a/test/fixtures/bower.json b/test/fixtures/bower.json index 7d9aae354..10dff6513 100644 --- a/test/fixtures/bower.json +++ b/test/fixtures/bower.json @@ -5,7 +5,6 @@ "angular": ">=1.2.*", "json3": "~3.3.1", "es5-shim": "~3.0.1", - "jquery": "~1.11.0", "bootstrap-sass-official": "~3.1.1", "bootstrap": "~3.1.1", "angular-resource": ">=1.2.*", diff --git a/test/fixtures/package.json b/test/fixtures/package.json index 856e4fcc2..c110f7838 100644 --- a/test/fixtures/package.json +++ b/test/fixtures/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "main": "server/app.js", "dependencies": { - "express": "~4.0.0", + "express": "~4.9.0", "morgan": "~1.0.0", "body-parser": "~1.5.0", "method-override": "~1.0.0", @@ -46,6 +46,8 @@ "grunt-contrib-coffee": "^0.10.1", "grunt-contrib-jade": "^0.11.0", "grunt-contrib-less": "^0.11.0", + "karma-babel-preprocessor": "^5.2.1", + "grunt-babel": "~5.0.0", "grunt-google-cdn": "~0.4.0", "grunt-newer": "~0.7.0", "grunt-ng-annotate": "^0.2.3", From acecde9d0e02b579d4b0a2a33d7c0f24067258ec Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 17 Jun 2015 00:45:10 -0400 Subject: [PATCH 0082/1357] fix(travis): Add nodejs 12 to travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 85fbe4a6b..5434c4542 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ language: node_js node_js: - '0.10' - '0.11' + - '0.12' before_install: - gem update --system - gem install sass --version "=3.3.7" From 498d7516b3d171c36e001330acbe2b2b9de6fd38 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 17 Jun 2015 00:54:06 -0400 Subject: [PATCH 0083/1357] Revert "fix(travis): Add nodejs 12 to travis.yml" This reverts commit acecde9d0e02b579d4b0a2a33d7c0f24067258ec. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5434c4542..85fbe4a6b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ language: node_js node_js: - '0.10' - '0.11' - - '0.12' before_install: - gem update --system - gem install sass --version "=3.3.7" From bf9a9737721d1ea72f3f7b9689d6781e78b4c606 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 17 Jun 2015 00:58:48 -0400 Subject: [PATCH 0084/1357] fix(travis): Remove unicode stuff from file creation test expectations, and add nodejs 0.12 target --- .travis.yml | 1 + test/test-file-creation.js | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 85fbe4a6b..5434c4542 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ language: node_js node_js: - '0.10' - '0.11' + - '0.12' before_install: - gem update --system - gem install sass --version "=3.3.7" diff --git a/test/test-file-creation.js b/test/test-file-creation.js index beb8b14b8..594dab05a 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -73,7 +73,7 @@ describe('angular-fullstack generator', function () { this.timeout(60000); gen.run({}, function () { exec('grunt test:client', function (error, stdout, stderr) { - expect(stdout, 'Client tests failed \n' + stdout ).to.contain('Executed 1 of 1\u001b[32m SUCCESS\u001b'); + expect(stdout, 'Client tests failed \n' + stdout ).to.contain('Executed 1 of 1 SUCCESS'); done(); }); }); @@ -160,7 +160,7 @@ describe('angular-fullstack generator', function () { this.timeout(60000); gen.run({}, function () { exec('grunt test:client', function (error, stdout, stderr) { - expect(stdout, 'Client tests failed \n' + stdout ).to.contain('Executed 1 of 1\u001b[32m SUCCESS\u001b'); + expect(stdout, 'Client tests failed \n' + stdout ).to.contain('Executed 1 of 1 SUCCESS'); done(); }); }); @@ -206,7 +206,7 @@ describe('angular-fullstack generator', function () { this.timeout(60000); gen.run({}, function () { exec('grunt test:client', function (error, stdout, stderr) { - expect(stdout, 'Client tests failed \n' + stdout ).to.contain('Executed 1 of 1\u001b[32m SUCCESS\u001b'); + expect(stdout, 'Client tests failed \n' + stdout ).to.contain('Executed 1 of 1 SUCCESS'); done(); }); }); @@ -252,7 +252,7 @@ describe('angular-fullstack generator', function () { this.timeout(60000); gen.run({}, function () { exec('grunt test:client', function (error, stdout, stderr) { - expect(stdout, 'Client tests failed \n' + stdout ).to.contain('Executed 1 of 1\u001b[32m SUCCESS\u001b'); + expect(stdout, 'Client tests failed \n' + stdout ).to.contain('Executed 1 of 1 SUCCESS'); done(); }); }); @@ -298,7 +298,7 @@ describe('angular-fullstack generator', function () { this.timeout(60000); gen.run({}, function () { exec('grunt test:client', function (error, stdout, stderr) { - expect(stdout, 'Client tests failed \n' + stdout ).to.contain('Executed 1 of 1\u001b[32m SUCCESS\u001b'); + expect(stdout, 'Client tests failed \n' + stdout ).to.contain('Executed 1 of 1 SUCCESS'); done(); }); }); From d2811661fbaba81e9c33a9837f7c1828c225a5af Mon Sep 17 00:00:00 2001 From: kingcody Date: Sat, 20 Jun 2015 04:57:05 -0400 Subject: [PATCH 0085/1357] chore(test): update chai related test libs --- app/templates/_package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 98cd616ac..8549daba0 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -76,11 +76,11 @@ "connect-livereload": "~0.4.0", "grunt-mocha-test": "~0.10.2", "grunt-mocha-istanbul": "^2.0.0", - "chai-as-promised": "^4.1.1", + "chai-as-promised": "^5.1.0", "chai-things": "^0.2.0", - "sinon-chai": "^2.5.0",<% if (filters.mocha) { %> + "sinon-chai": "^2.8.0",<% if (filters.mocha) { %> "karma-mocha": "^0.1.9", - "karma-chai-plugins": "^0.2.3",<% } if (filters.jasmine) { %> + "karma-chai-plugins": "^0.6.0",<% } if (filters.jasmine) { %> "karma-jasmine": "~0.1.5",<% } %> "karma-ng-scenario": "~0.1.0", "karma-firefox-launcher": "~0.1.3", From 8df999229c5984b33fcccddd5335f2aeffc4e8c9 Mon Sep 17 00:00:00 2001 From: kingcody Date: Sat, 20 Jun 2015 05:42:40 -0400 Subject: [PATCH 0086/1357] fix(test): update sequelize destroy usage --- .../login/login.spec(jasmine).js | 2 +- .../account(auth)/login/login.spec(mocha).js | 4 ++-- .../logout/logout.spec(jasmine).js | 2 +- .../logout/logout.spec(mocha).js | 4 ++-- .../signup/signup.spec(jasmine).js | 2 +- .../signup/signup.spec(mocha).js | 4 ++-- .../server/api/user(auth)/user.integration.js | 23 ++++++------------- .../user.model.spec(sequelizeModels).js | 6 ++--- 8 files changed, 19 insertions(+), 28 deletions(-) diff --git a/app/templates/e2e/account(auth)/login/login.spec(jasmine).js b/app/templates/e2e/account(auth)/login/login.spec(jasmine).js index e690c2601..c738f9370 100644 --- a/app/templates/e2e/account(auth)/login/login.spec(jasmine).js +++ b/app/templates/e2e/account(auth)/login/login.spec(jasmine).js @@ -20,7 +20,7 @@ describe('Login View', function() { beforeEach(function(done) { <% if (filters.mongooseModels) { %>UserModel.removeAsync()<% } - if (filters.sequelizeModels) { %>UserModel.destroy()<% } %> + if (filters.sequelizeModels) { %>UserModel.destroy({ where: {} })<% } %> .then(function() { <% if (filters.mongooseModels) { %>return UserModel.createAsync(testUser);<% } if (filters.sequelizeModels) { %>return UserModel.create(testUser);<% } %> diff --git a/app/templates/e2e/account(auth)/login/login.spec(mocha).js b/app/templates/e2e/account(auth)/login/login.spec(mocha).js index 3335cf3b4..6b3158726 100644 --- a/app/templates/e2e/account(auth)/login/login.spec(mocha).js +++ b/app/templates/e2e/account(auth)/login/login.spec(mocha).js @@ -21,7 +21,7 @@ describe('Login View', function() { before(function() { return UserModel <% if (filters.mongooseModels) { %>.removeAsync()<% } - if (filters.sequelizeModels) { %>.destroy()<% } %> + if (filters.sequelizeModels) { %>.destroy({ where: {} })<% } %> .then(function() { <% if (filters.mongooseModels) { %>return UserModel.createAsync(testUser);<% } if (filters.sequelizeModels) { %>return UserModel.create(testUser);<% } %> @@ -31,7 +31,7 @@ describe('Login View', function() { after(function() { <% if (filters.mongooseModels) { %>return UserModel.removeAsync();<% } - if (filters.sequelizeModels) { %>return UserModel.destroy();<% } %> + if (filters.sequelizeModels) { %>return UserModel.destroy({ where: {} });<% } %> }); it('should include login form with correct inputs and submit button', function() { diff --git a/app/templates/e2e/account(auth)/logout/logout.spec(jasmine).js b/app/templates/e2e/account(auth)/logout/logout.spec(jasmine).js index f3149865c..ae4bb23a0 100644 --- a/app/templates/e2e/account(auth)/logout/logout.spec(jasmine).js +++ b/app/templates/e2e/account(auth)/logout/logout.spec(jasmine).js @@ -18,7 +18,7 @@ describe('Logout View', function() { beforeEach(function(done) { <% if (filters.mongooseModels) { %>UserModel.removeAsync()<% } - if (filters.sequelizeModels) { %>UserModel.destroy()<% } %> + if (filters.sequelizeModels) { %>UserModel.destroy({ where: {} })<% } %> .then(function() { <% if (filters.mongooseModels) { %>return UserModel.createAsync(testUser);<% } if (filters.sequelizeModels) { %>return UserModel.create(testUser);<% } %> diff --git a/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js b/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js index 85d92cf75..ef9f6d4da 100644 --- a/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js +++ b/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js @@ -19,7 +19,7 @@ describe('Logout View', function() { beforeEach(function() { return UserModel <% if (filters.mongooseModels) { %>.removeAsync()<% } - if (filters.sequelizeModels) { %>.destroy()<% } %> + if (filters.sequelizeModels) { %>.destroy({ where: {} })<% } %> .then(function() { <% if (filters.mongooseModels) { %>return UserModel.createAsync(testUser);<% } if (filters.sequelizeModels) { %>return UserModel.create(testUser);<% } %> @@ -31,7 +31,7 @@ describe('Logout View', function() { after(function() { <% if (filters.mongooseModels) { %>return UserModel.removeAsync();<% } - if (filters.sequelizeModels) { %>return UserModel.destroy();<% } %> + if (filters.sequelizeModels) { %>return UserModel.destroy({ where: {} });<% } %> }) describe('with local auth', function() { diff --git a/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js b/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js index abbfc98a4..511a84933 100644 --- a/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js +++ b/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js @@ -37,7 +37,7 @@ describe('Signup View', function() { it('should signup a new user, log them in, and redirecting to "/"', function(done) { <% if (filters.mongooseModels) { %>UserModel.remove(function() {<% } - if (filters.sequelizeModels) { %>UserModel.destroy().then(function() {<% } %> + if (filters.sequelizeModels) { %>UserModel.destroy({ where: {} }).then(function() {<% } %> page.signup(testUser); var navbar = require('../../components/navbar/navbar.po'); diff --git a/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js b/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js index 5351ea75d..852a3cb71 100644 --- a/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js +++ b/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js @@ -24,7 +24,7 @@ describe('Signup View', function() { after(function() { <% if (filters.mongooseModels) { %>return UserModel.removeAsync();<% } - if (filters.sequelizeModels) { %>return UserModel.destroy();<% } %> + if (filters.sequelizeModels) { %>return UserModel.destroy({ where: {} });<% } %> }); it('should include signup form with correct inputs and submit button', function() { @@ -42,7 +42,7 @@ describe('Signup View', function() { it('should signup a new user, log them in, and redirecting to "/"', function(done) { <% if (filters.mongooseModels) { %>UserModel.remove(function() {<% } - if (filters.sequelizeModels) { %>UserModel.destroy().then(function() {<% } %> + if (filters.sequelizeModels) { %>UserModel.destroy({ where: {} }).then(function() {<% } %> page.signup(testUser); var navbar = require('../../components/navbar/navbar.po'); diff --git a/app/templates/server/api/user(auth)/user.integration.js b/app/templates/server/api/user(auth)/user.integration.js index 35bcdb573..5273be72a 100644 --- a/app/templates/server/api/user(auth)/user.integration.js +++ b/app/templates/server/api/user(auth)/user.integration.js @@ -9,9 +9,9 @@ describe('User API:', function() { var user; // Clear users before testing - before(function(done) { - <% if (filters.mongooseModels) { %>User.remove(function() {<% } - if (filters.sequelizeModels) { %>User.destroy().then(function() {<% } %> + before(function() { + return <% if (filters.mongooseModels) { %>User.removeAsync().then(function() {<% } + if (filters.sequelizeModels) { %>User.destroy({ where: {} }).then(function() {<% } %> <% if (filters.mongooseModels) { %>user = new User({<% } if (filters.sequelizeModels) { %>user = User.build({<% } %> name: 'Fake User', @@ -19,24 +19,15 @@ describe('User API:', function() { password: 'password' }); - <% if (filters.mongooseModels) { %>user.save(function(err) { - if (err) { - return done(err); - } - done(); - });<% } - if (filters.sequelizeModels) { %>user.save().then(function() { - done(); - }, function(err) { - return done(err); - });<% } %> + return <% if (filters.mongooseModels) { %>user.saveAsync();<% } + if (filters.sequelizeModels) { %>user.save();<% } %> }); }); // Clear users after testing after(function() { - <% if (filters.mongooseModels) { %>return User.remove().exec();<% } - if (filters.sequelizeModels) { %>return User.destroy();<% } %> + <% if (filters.mongooseModels) { %>return User.removeAsync();<% } + if (filters.sequelizeModels) { %>return User.destroy({ where: {} });<% } %> }); describe('GET /api/users/me', function() { diff --git a/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js b/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js index 88156151b..f499667cd 100644 --- a/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js +++ b/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js @@ -15,13 +15,13 @@ var user = User.build(userTemplate); describe('User Model', function() { before(function() { // Sync and clear users before testing - User.sync().then(function() { - return User.destroy(); + return User.sync().then(function() { + return User.destroy({ where: {} }); }); }); afterEach(function() { - return User.destroy(); + return User.destroy({ where: {} }); }); it('should begin with no users', function() { From c7f6c360dca99c7741695158a5b6cfda969e3594 Mon Sep 17 00:00:00 2001 From: kingcody Date: Sat, 20 Jun 2015 06:41:12 -0400 Subject: [PATCH 0087/1357] fix(test): change `protractor.getInstance` to `browser` --- app/templates/e2e/account(auth)/login/login.spec(jasmine).js | 2 +- app/templates/e2e/account(auth)/login/login.spec(mocha).js | 2 +- app/templates/e2e/account(auth)/logout/logout.spec(jasmine).js | 2 +- app/templates/e2e/account(auth)/logout/logout.spec(mocha).js | 2 +- app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js | 2 +- app/templates/e2e/account(auth)/signup/signup.spec(mocha).js | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/templates/e2e/account(auth)/login/login.spec(jasmine).js b/app/templates/e2e/account(auth)/login/login.spec(jasmine).js index c738f9370..8b31d4d6b 100644 --- a/app/templates/e2e/account(auth)/login/login.spec(jasmine).js +++ b/app/templates/e2e/account(auth)/login/login.spec(jasmine).js @@ -1,6 +1,6 @@ 'use strict'; -var config = protractor.getInstance().params;<% if (filters.mongooseModels) { %> +var config = browser.params;<% if (filters.mongooseModels) { %> var UserModel = require(config.serverConfig.root + '/server/api/user/user.model');<% } %><% if (filters.sequelizeModels) { %> var UserModel = require(config.serverConfig.root + '/server/sqldb').User;<% } %> diff --git a/app/templates/e2e/account(auth)/login/login.spec(mocha).js b/app/templates/e2e/account(auth)/login/login.spec(mocha).js index 6b3158726..57222c1e4 100644 --- a/app/templates/e2e/account(auth)/login/login.spec(mocha).js +++ b/app/templates/e2e/account(auth)/login/login.spec(mocha).js @@ -1,6 +1,6 @@ 'use strict'; -var config = protractor.getInstance().params;<% if (filters.mongooseModels) { %> +var config = browser.params;<% if (filters.mongooseModels) { %> var UserModel = require(config.serverConfig.root + '/server/api/user/user.model');<% } %><% if (filters.sequelizeModels) { %> var UserModel = require(config.serverConfig.root + '/server/sqldb').User;<% } %> diff --git a/app/templates/e2e/account(auth)/logout/logout.spec(jasmine).js b/app/templates/e2e/account(auth)/logout/logout.spec(jasmine).js index ae4bb23a0..fc10a1684 100644 --- a/app/templates/e2e/account(auth)/logout/logout.spec(jasmine).js +++ b/app/templates/e2e/account(auth)/logout/logout.spec(jasmine).js @@ -1,6 +1,6 @@ 'use strict'; -var config = protractor.getInstance().params;<% if (filters.mongooseModels) { %> +var config = browser.params;<% if (filters.mongooseModels) { %> var UserModel = require(config.serverConfig.root + '/server/api/user/user.model');<% } %><% if (filters.sequelizeModels) { %> var UserModel = require(config.serverConfig.root + '/server/sqldb').User;<% } %> diff --git a/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js b/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js index ef9f6d4da..5268456de 100644 --- a/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js +++ b/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js @@ -1,6 +1,6 @@ 'use strict'; -var config = protractor.getInstance().params;<% if (filters.mongooseModels) { %> +var config = browser.params;<% if (filters.mongooseModels) { %> var UserModel = require(config.serverConfig.root + '/server/api/user/user.model');<% } %><% if (filters.sequelizeModels) { %> var UserModel = require(config.serverConfig.root + '/server/sqldb').User;<% } %> diff --git a/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js b/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js index 511a84933..1613d3ae8 100644 --- a/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js +++ b/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js @@ -1,6 +1,6 @@ 'use strict'; -var config = protractor.getInstance().params;<% if (filters.mongooseModels) { %> +var config = browser.params;<% if (filters.mongooseModels) { %> var UserModel = require(config.serverConfig.root + '/server/api/user/user.model');<% } %><% if (filters.sequelizeModels) { %> var UserModel = require(config.serverConfig.root + '/server/sqldb').User;<% } %> diff --git a/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js b/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js index 852a3cb71..e4855cc11 100644 --- a/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js +++ b/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js @@ -1,6 +1,6 @@ 'use strict'; -var config = protractor.getInstance().params;<% if (filters.mongooseModels) { %> +var config = browser.params;<% if (filters.mongooseModels) { %> var UserModel = require(config.serverConfig.root + '/server/api/user/user.model');<% } %><% if (filters.sequelizeModels) { %> var UserModel = require(config.serverConfig.root + '/server/sqldb').User;<% } %> From df481888dd9300762c7a817ec29d47f24b924cdd Mon Sep 17 00:00:00 2001 From: kingcody Date: Sat, 20 Jun 2015 01:53:27 -0400 Subject: [PATCH 0088/1357] test(model): refactor tests to expose model update bugs Both mongoose and sequelize user model implementations have undesired effects when performing an update. --- .../user.model.spec(mongooseModels).js | 60 +++++++++++++------ .../user.model.spec(sequelizeModels).js | 56 +++++++++++------ 2 files changed, 81 insertions(+), 35 deletions(-) diff --git a/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js b/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js index 16de6e2de..1aad3b25e 100644 --- a/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js +++ b/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js @@ -2,22 +2,29 @@ var app = require('../../app'); var User = require('./user.model'); - -var user = new User({ - provider: 'local', - name: 'Fake User', - email: 'test@test.com', - password: 'password' -}); +var user; +var genUser = function() { + user = new User({ + provider: 'local', + name: 'Fake User', + email: 'test@test.com', + password: 'password' + }); + return user; +}; describe('User Model', function() { before(function() { // Clear users before testing - return User.remove().exec(); + return User.removeAsync(); + }); + + beforeEach(function() { + genUser(); }); afterEach(function() { - return User.remove().exec(); + return User.removeAsync(); }); it('should begin with no users', function() { @@ -28,21 +35,38 @@ describe('User Model', function() { it('should fail when saving a duplicate user', function() { return user.saveAsync() .then(function() { - var userDup = new User(user); + var userDup = genUser(); return userDup.saveAsync(); }).should.be.rejected; }); - it('should fail when saving without an email', function() { - user.email = ''; - return user.saveAsync().should.be.rejected; + describe('#email', function() { + it('should fail when saving without an email', function() { + user.email = ''; + return user.saveAsync().should.be.rejected; + }); }); - it('should authenticate user if password is valid', function() { - user.authenticate('password').should.be.true; - }); + describe('#password', function() { + beforeEach(function() { + return user.saveAsync(); + }); + + it('should authenticate user if valid', function() { + user.authenticate('password').should.be.true; + }); - it('should not authenticate user if password is invalid', function() { - user.authenticate('blah').should.not.be.true; + it('should not authenticate user if invalid', function() { + user.authenticate('blah').should.not.be.true; + }); + + it('should remain the same hash unless the password is updated', function() { + user.name = 'Test User'; + return user.saveAsync() + .spread(function(u) { + return u.authenticate('password'); + }).should.eventually.be.true; + }); }); + }); diff --git a/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js b/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js index f499667cd..a7af1bd38 100644 --- a/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js +++ b/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js @@ -2,16 +2,17 @@ var app = require('../../app'); var User = require('../../sqldb').User; - -var userTemplate = { - provider: 'local', - name: 'Fake User', - email: 'test@test.com', - password: 'password' +var user; +var genUser = function() { + user = User.build({ + provider: 'local', + name: 'Fake User', + email: 'test@test.com', + password: 'password' + }); + return user; }; -var user = User.build(userTemplate); - describe('User Model', function() { before(function() { // Sync and clear users before testing @@ -20,6 +21,10 @@ describe('User Model', function() { }); }); + beforeEach(function() { + genUser(); + }); + afterEach(function() { return User.destroy({ where: {} }); }); @@ -32,21 +37,38 @@ describe('User Model', function() { it('should fail when saving a duplicate user', function() { return user.save() .then(function() { - var userDup = User.build(userTemplate); + var userDup = genUser(); return userDup.save(); }).should.be.rejected; }); - it('should fail when saving without an email', function() { - user.email = ''; - return user.save().should.be.rejected; + describe('#email', function() { + it('should fail when saving without an email', function() { + user.email = ''; + return user.save().should.be.rejected; + }); }); - it('should authenticate user if password is valid', function() { - user.authenticate('password').should.be.true; - }); + describe('#password', function() { + beforeEach(function() { + return user.save(); + }); + + it('should authenticate user if valid', function() { + user.authenticate('password').should.be.true; + }); - it('should not authenticate user if password is invalid', function() { - user.authenticate('blah').should.not.be.true; + it('should not authenticate user if invalid', function() { + user.authenticate('blah').should.not.be.true; + }); + + it('should remain the same hash unless the password is updated', function() { + user.name = 'Test User'; + return user.save() + .then(function(u) { + return u.authenticate('password'); + }).should.eventually.be.true; + }); }); + }); From 1805975d3a7bdd1b9a409813d3fc0d2777f492bf Mon Sep 17 00:00:00 2001 From: kingcody Date: Mon, 22 Jun 2015 02:04:38 -0400 Subject: [PATCH 0089/1357] fix(model): fix update bugs with mongoose and sequelize --- .../server/api/user(auth)/user.model(mongooseModels).js | 2 +- .../server/api/user(auth)/user.model(sequelizeModels).js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/templates/server/api/user(auth)/user.model(mongooseModels).js b/app/templates/server/api/user(auth)/user.model(mongooseModels).js index 201afb4bc..008412eaf 100644 --- a/app/templates/server/api/user(auth)/user.model(mongooseModels).js +++ b/app/templates/server/api/user(auth)/user.model(mongooseModels).js @@ -102,7 +102,7 @@ var validatePresenceOf = function(value) { UserSchema .pre('save', function(next) { // Handle new/update passwords - if (this.password) { + if (this.isModified('password')) { if (!validatePresenceOf(this.password)<% if (filters.oauth) { %> && authTypes.indexOf(this.provider) === -1<% } %>) { next(new Error('Invalid password')); } diff --git a/app/templates/server/api/user(auth)/user.model(sequelizeModels).js b/app/templates/server/api/user(auth)/user.model(sequelizeModels).js index af593157a..776eafc3e 100644 --- a/app/templates/server/api/user(auth)/user.model(sequelizeModels).js +++ b/app/templates/server/api/user(auth)/user.model(sequelizeModels).js @@ -89,8 +89,9 @@ module.exports = function(sequelize, DataTypes) { }, beforeUpdate: function(user, fields, fn) { if (user.changed('password')) { - user.updatePassword(fn); + return user.updatePassword(fn); } + fn(); } }, From e7087e6ce906ffa3c2f96ed4ba29b5b782f20b3b Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Mon, 22 Jun 2015 10:42:13 -0400 Subject: [PATCH 0090/1357] docs(readme): Add babel injection note --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index 5d11f17aa..21169c3fb 100644 --- a/readme.md +++ b/readme.md @@ -57,6 +57,7 @@ A grunt task looks for new files in your `client/app` and `client/components` fo * `css` files into `client/index.html` * `js` files into `client/index.html` * `coffeescript` temp `js` files into `client/index.html` +* `babel` temp `js` files into `client/index.html` ## Generators From 349b6d3e5ca01e2d44342f0d952953f30dd322e9 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Mon, 22 Jun 2015 13:43:15 -0400 Subject: [PATCH 0091/1357] fix(npm): Remove git diff comment Crap.... --- app/templates/_package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 870408f92..346ec2078 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -45,7 +45,6 @@ "grunt-contrib-imagemin": "~0.7.1", "grunt-contrib-jshint": "~0.10.0", "grunt-contrib-uglify": "~0.4.0", -<<<<<<< HEAD "grunt-contrib-watch": "~0.6.1",<% if (filters.coffee) { %> "grunt-contrib-coffee": "^0.10.1",<% } %><% if (filters.jade) { %> "grunt-contrib-jade": "^0.11.0",<% } %><% if (filters.less) { %> From 1bcffd674c776453732a242e8106f51090a9447c Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Mon, 22 Jun 2015 14:14:40 -0400 Subject: [PATCH 0092/1357] fix(gen:endpoint): Fix JSCS stuff and use Express 4 syntax --- endpoint/templates/name.controller.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/endpoint/templates/name.controller.js b/endpoint/templates/name.controller.js index 6a63a7ba8..4b5d985e4 100644 --- a/endpoint/templates/name.controller.js +++ b/endpoint/templates/name.controller.js @@ -11,7 +11,7 @@ function responseWithResult(res, statusCode) { statusCode = statusCode || 200; return function(entity) { if (entity) { - return res.json(statusCode, entity); + return res.status(statusCode).json(entity); } }; } @@ -41,7 +41,7 @@ function removeEntity(res) { if (entity) { return entity.removeAsync() .then(function() { - return res.send(204); + return res.status(204); }); } }; @@ -50,8 +50,8 @@ function removeEntity(res) { // Get list of <%= name %>s exports.index = function(req, res) {<% if (!filters.mongoose) { %> res.json([]);<% } %><% if (filters.mongoose) { %> - <%= classedName %>.find(function (err, <%= name %>s) { - if(err) { return handleError(res, err); } + <%= classedName %>.find(function(err, <%= name %>s) { + if (err) { return handleError(res, err); } return res.status(200).json(<%= name %>s); });<% } %> };<% if (filters.mongoose) { %> From 0af7c3ebb95edb41b1b82014d5e1501d8f4164ce Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 23 Jun 2015 06:40:39 -0400 Subject: [PATCH 0093/1357] fix(endpoint): refactor handleError for promise use --- endpoint/templates/name.controller.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/endpoint/templates/name.controller.js b/endpoint/templates/name.controller.js index 4b5d985e4..7d03a42ee 100644 --- a/endpoint/templates/name.controller.js +++ b/endpoint/templates/name.controller.js @@ -3,8 +3,11 @@ var _ = require('lodash'); var <%= classedName %> = require('./<%= name %>.model'); -function handleError(res, err) { - return res.status(500).send(err); +function handleError(res, statusCode) { + statusCode = statusCode || 500; + return function(err) { + res.status(statusCode).send(err); + }; } function responseWithResult(res, statusCode) { @@ -19,7 +22,7 @@ function responseWithResult(res, statusCode) { function handleEntityNotFound(res) { return function(entity) { if (!entity) { - res.send(404); + res.status(404).end(); return null; } return entity; @@ -41,7 +44,7 @@ function removeEntity(res) { if (entity) { return entity.removeAsync() .then(function() { - return res.status(204); + res.status(204).end(); }); } }; @@ -50,10 +53,9 @@ function removeEntity(res) { // Get list of <%= name %>s exports.index = function(req, res) {<% if (!filters.mongoose) { %> res.json([]);<% } %><% if (filters.mongoose) { %> - <%= classedName %>.find(function(err, <%= name %>s) { - if (err) { return handleError(res, err); } - return res.status(200).json(<%= name %>s); - });<% } %> + <%= classedName %>.findAsync() + .then(responseWithResult(res)) + .catch(handleError(res));<% } %> };<% if (filters.mongoose) { %> // Gets a single <%= name %> from the DB. From 0ec2e1808ec15755786b7144b99fcdc5704738a6 Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 23 Jun 2015 06:47:24 -0400 Subject: [PATCH 0094/1357] fix(test): remove package.json and bower.json --- test/fixtures/bower.json | 24 --------- test/fixtures/package.json | 102 ------------------------------------- 2 files changed, 126 deletions(-) delete mode 100644 test/fixtures/bower.json delete mode 100644 test/fixtures/package.json diff --git a/test/fixtures/bower.json b/test/fixtures/bower.json deleted file mode 100644 index 10dff6513..000000000 --- a/test/fixtures/bower.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "tempApp", - "version": "0.0.0", - "dependencies": { - "angular": ">=1.2.*", - "json3": "~3.3.1", - "es5-shim": "~3.0.1", - "bootstrap-sass-official": "~3.1.1", - "bootstrap": "~3.1.1", - "angular-resource": ">=1.2.*", - "angular-cookies": ">=1.2.*", - "angular-sanitize": ">=1.2.*", - "angular-route": ">=1.2.*", - "angular-bootstrap": "~0.11.0", - "font-awesome": ">=4.1.0", - "lodash": "~2.4.1", - "angular-socket-io": "~0.6.0", - "angular-ui-router": "~0.2.10" - }, - "devDependencies": { - "angular-mocks": ">=1.2.*", - "angular-scenario": ">=1.2.*" - } -} diff --git a/test/fixtures/package.json b/test/fixtures/package.json deleted file mode 100644 index c110f7838..000000000 --- a/test/fixtures/package.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "name": "tempApp", - "version": "0.0.0", - "main": "server/app.js", - "dependencies": { - "express": "~4.9.0", - "morgan": "~1.0.0", - "body-parser": "~1.5.0", - "method-override": "~1.0.0", - "serve-favicon": "~2.0.1", - "cookie-parser": "~1.0.1", - "express-session": "~1.0.2", - "errorhandler": "~1.0.0", - "compression": "~1.0.1", - "lodash": "~2.4.1", - "jade": "~1.2.0", - "ejs": "~0.8.4", - "mongoose": "~3.8.8", - "jsonwebtoken": "^0.3.0", - "express-jwt": "^0.1.3", - "passport": "~0.2.0", - "passport-local": "~0.1.6", - "passport-facebook": "latest", - "passport-twitter": "latest", - "passport-google-oauth": "latest", - "composable-middleware": "^0.3.0", - "connect-mongo": "^0.4.1", - "socket.io": "^1.0.6", - "socket.io-client": "^1.0.6", - "socketio-jwt": "^2.0.2" - }, - "devDependencies": { - "grunt": "~0.4.4", - "grunt-autoprefixer": "~0.7.2", - "grunt-wiredep": "~1.8.0", - "grunt-concurrent": "~0.5.0", - "grunt-contrib-clean": "~0.5.0", - "grunt-contrib-concat": "~0.4.0", - "grunt-contrib-copy": "~0.5.0", - "grunt-contrib-cssmin": "~0.9.0", - "grunt-contrib-htmlmin": "~0.2.0", - "grunt-contrib-imagemin": "~0.7.1", - "grunt-contrib-jshint": "~0.10.0", - "grunt-contrib-uglify": "~0.4.0", - "grunt-contrib-watch": "~0.6.1", - "grunt-contrib-coffee": "^0.10.1", - "grunt-contrib-jade": "^0.11.0", - "grunt-contrib-less": "^0.11.0", - "karma-babel-preprocessor": "^5.2.1", - "grunt-babel": "~5.0.0", - "grunt-google-cdn": "~0.4.0", - "grunt-newer": "~0.7.0", - "grunt-ng-annotate": "^0.2.3", - "grunt-rev": "~0.1.0", - "grunt-svgmin": "~0.4.0", - "grunt-usemin": "~2.1.1", - "grunt-env": "~0.4.1", - "grunt-node-inspector": "~0.1.5", - "grunt-nodemon": "~0.2.0", - "grunt-angular-templates": "^0.5.4", - "grunt-dom-munger": "^3.4.0", - "grunt-protractor-runner": "^1.1.0", - "grunt-injector": "~0.5.4", - "grunt-karma": "~0.8.2", - "grunt-build-control": "DaftMonk/grunt-build-control", - "grunt-mocha-test": "~0.10.2", - "grunt-contrib-sass": "^0.7.3", - "grunt-contrib-stylus": "latest", - "jit-grunt": "^0.5.0", - "time-grunt": "~0.3.1", - "grunt-express-server": "~0.4.17", - "grunt-open": "~0.2.3", - "open": "~0.0.4", - "jshint-stylish": "~0.1.5", - "connect-livereload": "~0.4.0", - "karma-ng-scenario": "~0.1.0", - "karma-firefox-launcher": "~0.1.3", - "karma-script-launcher": "~0.1.0", - "karma-html2js-preprocessor": "~0.1.0", - "karma-ng-jade2js-preprocessor": "^0.1.2", - "karma-jasmine": "~0.1.5", - "karma-chrome-launcher": "~0.1.3", - "requirejs": "~2.1.11", - "karma-requirejs": "~0.2.1", - "karma-coffee-preprocessor": "~0.2.1", - "karma-jade-preprocessor": "0.0.11", - "karma-phantomjs-launcher": "~0.1.4", - "karma": "~0.12.9", - "karma-ng-html2js-preprocessor": "~0.1.0", - "supertest": "~0.11.0", - "should": "~3.3.1" - }, - "engines": { - "node": ">=0.10.0" - }, - "scripts": { - "start": "node server/app.js", - "test": "grunt test", - "update-webdriver": "node node_modules/grunt-protractor-runner/node_modules/protractor/bin/webdriver-manager update" - }, - "private": true -} From 552bf993592c42f99ec0f3f6afcf4ef1906c51a6 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 23 Jun 2015 11:46:18 -0400 Subject: [PATCH 0095/1357] Update .gitattributes --- app/templates/.gitattributes | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/templates/.gitattributes b/app/templates/.gitattributes index 212566614..735361404 100644 --- a/app/templates/.gitattributes +++ b/app/templates/.gitattributes @@ -1 +1,2 @@ -* text=auto \ No newline at end of file +* text=auto +* text eol=lf From e0350ccb662853f98458e5f0997aed2555c6cc67 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 23 Jun 2015 12:04:32 -0400 Subject: [PATCH 0096/1357] fix(git): Remove old text=auto --- app/templates/.gitattributes | 1 - 1 file changed, 1 deletion(-) diff --git a/app/templates/.gitattributes b/app/templates/.gitattributes index 735361404..fcadb2cf9 100644 --- a/app/templates/.gitattributes +++ b/app/templates/.gitattributes @@ -1,2 +1 @@ -* text=auto * text eol=lf From 342606c4a3447e4c12561c4b2752a89d47c99527 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 23 Jun 2015 12:15:25 -0400 Subject: [PATCH 0097/1357] fix(gen): Check that answers.odms exists --- app/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/index.js b/app/index.js index 29289881e..15f8f3b95 100644 --- a/app/index.js +++ b/app/index.js @@ -224,7 +224,7 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ }], function (answers) { if(answers.socketio) this.filters.socketio = true; if(answers.auth) this.filters.auth = true; - if(answers.odms.length > 0) { + if(answers.odms && answers.odms.length > 0) { var models; if(!answers.models) { models = answers.odms[0]; From 163249f2c11ea0210c937c6889c57f9567b6ca09 Mon Sep 17 00:00:00 2001 From: Yoshioka Tsuneo Date: Wed, 24 Jun 2015 14:23:24 +0900 Subject: [PATCH 0098/1357] Update mongoose/connect-mongo to latest to deploy on Heroku On default package.json, heroku deployment fails. Just updating mongoose/connect-mongo package solves the issue for Heroku deployment. --- app/templates/_package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index fc374be27..88541b924 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -15,7 +15,7 @@ "lodash": "~2.4.1",<% if(filters.jade) { %> "jade": "~1.2.0",<% } %><% if(filters.html) { %> "ejs": "~0.8.4",<% } %><% if(filters.mongoose) { %> - "mongoose": "~3.8.8",<% } %><% if(filters.auth) { %> + "mongoose": "~4.0.3",<% } %><% if(filters.auth) { %> "jsonwebtoken": "^5.0.0", "express-jwt": "^3.0.0", "passport": "~0.2.0", @@ -24,7 +24,7 @@ "passport-twitter": "latest",<% } %><% if(filters.googleAuth) { %> "passport-google-oauth": "latest",<% } %> "composable-middleware": "^0.3.0", - "connect-mongo": "^0.4.1"<% if(filters.socketio) { %>, + "connect-mongo": "^0.8.1"<% if(filters.socketio) { %>, "socket.io": "^1.0.6", "socket.io-client": "^1.0.6", "socketio-jwt": "^3.0.0"<% } %> From dae69cff73b615b92839cc2c7014f1a96d334544 Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 24 Jun 2015 06:58:52 -0400 Subject: [PATCH 0099/1357] fix(travis): remove node v0.11 from testing --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 36b85dcc5..cdaee3885 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: node_js node_js: - '0.10' - - '0.11' - '0.12' env: global: From c98cb5d3606ddd47d44cb8a5b366124bde04328c Mon Sep 17 00:00:00 2001 From: kingcody Date: Sat, 27 Jun 2015 02:13:17 -0400 Subject: [PATCH 0100/1357] fix(endpoint:user): refactor validationError for promise use --- .../server/api/user(auth)/user.controller.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/app/templates/server/api/user(auth)/user.controller.js b/app/templates/server/api/user(auth)/user.controller.js index 0286b5415..d074c666b 100644 --- a/app/templates/server/api/user(auth)/user.controller.js +++ b/app/templates/server/api/user(auth)/user.controller.js @@ -8,21 +8,24 @@ var passport = require('passport'); var config = require('../../config/environment'); var jwt = require('jsonwebtoken'); -var validationError = function(res, err) { - return res.status(422).json(err); -}; +function validationError(res, statusCode) { + statusCode = statusCode || 422; + return function(err) { + res.status(statusCode).json(err); + } +} function handleError(res, statusCode) { statusCode = statusCode || 500; return function(err) { - res.send(statusCode, err); + res.status(statusCode).send(err); }; } function respondWith(res, statusCode) { statusCode = statusCode || 200; return function() { - res.send(statusCode); + res.status(statusCode).end(); }; } From c7b48a5b6bb54968ed690d600f496ef032ee7869 Mon Sep 17 00:00:00 2001 From: kingcody Date: Sat, 27 Jun 2015 02:25:22 -0400 Subject: [PATCH 0101/1357] fix(endpoint:thing): use Express 4 syntax --- .../server/api/thing/thing.controller(models).js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/templates/server/api/thing/thing.controller(models).js b/app/templates/server/api/thing/thing.controller(models).js index a14fbd4b3..c7874b515 100644 --- a/app/templates/server/api/thing/thing.controller(models).js +++ b/app/templates/server/api/thing/thing.controller(models).js @@ -17,7 +17,7 @@ var Thing = sqldb.Thing;<% } %> function handleError(res, statusCode) { statusCode = statusCode || 500; return function(err) { - res.send(statusCode, err); + res.status(statusCode).send(err); }; } @@ -25,7 +25,7 @@ function responseWithResult(res, statusCode) { statusCode = statusCode || 200; return function(entity) { if (entity) { - return res.json(statusCode, entity); + return res.status(statusCode).json(entity); } }; } @@ -33,7 +33,7 @@ function responseWithResult(res, statusCode) { function handleEntityNotFound(res) { return function(entity) { if (!entity) { - res.send(404); + res.status(404).end(); return null; } return entity; @@ -58,7 +58,7 @@ function removeEntity(res) { <% if (filters.mongooseModels) { %>return entity.removeAsync()<% } if (filters.sequelizeModels) { %>return entity.destroy()<% } %> .then(function() { - return res.send(204); + return res.status(204).end(); }); } }; From 60334a8d43c2d53a4e994dad5ba201590982ae91 Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 24 Jun 2015 05:41:37 -0400 Subject: [PATCH 0102/1357] feat(server): implement server-side ES6 via babel --- app/templates/Gruntfile.js | 29 +++++++--------------- app/templates/_package.json | 5 ++-- app/templates/mocha.conf.js | 5 +++- app/templates/server/index.js | 7 ++++++ test/test-file-creation.js | 45 ++--------------------------------- 5 files changed, 25 insertions(+), 66 deletions(-) create mode 100644 app/templates/server/index.js diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 028300e68..8d2ef6c96 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -39,13 +39,13 @@ module.exports = function (grunt) { }, dev: { options: { - script: 'server/app.js', + script: 'server', debug: true } }, prod: { options: { - script: 'dist/server/app.js' + script: 'dist/server' } } }, @@ -61,7 +61,7 @@ module.exports = function (grunt) { '!<%%= yeoman.client %>/{app,components}/**/*.spec.js', '!<%%= yeoman.client %>/{app,components}/**/*.mock.js', '!<%%= yeoman.client %>/app/app.js'], - tasks: ['injector:scripts'] + tasks: [<% if(filters.babel) { %>'newer:babel:client', <% } %>'injector:scripts'] }, injectCss: { files: [ @@ -128,13 +128,6 @@ module.exports = function (grunt) { '<%%= yeoman.client %>/{app,components}/**/*.spec.{coffee,litcoffee,coffee.md}' ], tasks: ['karma'] - },<% } %><% if(filters.babel) { %> - babel: { - files: [ - '<%%= yeoman.client %>/{app,components}/**/*.js', - '!<%%= yeoman.client %>/{app,components}/**/*.spec.js' - ], - tasks: ['babel'] },<% } %> gruntfile: { files: ['Gruntfile.js'] @@ -143,11 +136,7 @@ module.exports = function (grunt) { files: [ '{.tmp,<%%= yeoman.client %>}/{app,components}/**/*.css', '{.tmp,<%%= yeoman.client %>}/{app,components}/**/*.html', - <% if(filters.babel) { %> - '.tmp/{app,components}/**/*.js', - <% } else { %> '{.tmp,<%%= yeoman.client %>}/{app,components}/**/*.js', - <% } %> '!{.tmp,<%%= yeoman.client %>}{app,components}/**/*.spec.js', '!{.tmp,<%%= yeoman.client %>}/{app,components}/**/*.mock.js', '<%%= yeoman.client %>/assets/images/{,*//*}*.{png,jpg,jpeg,gif,webp,svg}' @@ -261,7 +250,7 @@ module.exports = function (grunt) { // Use nodemon to run server in debug mode with an initial breakpoint nodemon: { debug: { - script: 'server/app.js', + script: 'server', options: { nodeArgs: ['--debug-brk'], env: { @@ -470,7 +459,7 @@ module.exports = function (grunt) { concurrent: { server: [<% if(filters.coffee) { %> 'coffee',<% } %><% if(filters.babel) { %> - 'babel',<% } %><% if(filters.jade) { %> + 'newer:babel:client',<% } %><% if(filters.jade) { %> 'jade',<% } %><% if(filters.stylus) { %> 'stylus',<% } %><% if(filters.sass) { %> 'sass',<% } %><% if(filters.less) { %> @@ -478,7 +467,7 @@ module.exports = function (grunt) { ], test: [<% if(filters.coffee) { %> 'coffee',<% } %><% if(filters.babel) { %> - 'babel',<% } %><% if(filters.jade) { %> + 'newer:babel:client',<% } %><% if(filters.jade) { %> 'jade',<% } %><% if(filters.stylus) { %> 'stylus',<% } %><% if(filters.sass) { %> 'sass',<% } %><% if(filters.less) { %> @@ -495,7 +484,7 @@ module.exports = function (grunt) { }, dist: [<% if(filters.coffee) { %> 'coffee',<% } %><% if(filters.babel) { %> - 'babel',<% } %><% if(filters.jade) { %> + 'newer:babel:client',<% } %><% if(filters.jade) { %> 'jade',<% } %><% if(filters.stylus) { %> 'stylus',<% } %><% if(filters.sass) { %> 'sass',<% } %><% if(filters.less) { %> @@ -639,10 +628,10 @@ module.exports = function (grunt) { options: { sourceMap: true }, - server: { + client: { files: [{ expand: true, - cwd: 'client', + cwd: '<%%= yeoman.client %>', src: [ '{app,components}/**/*.js', '!{app,components}/**/*.spec.js' diff --git a/app/templates/_package.json b/app/templates/_package.json index 346ec2078..1356bab64 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -12,7 +12,8 @@ "express-session": "~1.0.2", "errorhandler": "~1.0.0", "compression": "~1.0.1", - "lodash": "~2.4.1",<% if (filters.jade) { %> + "lodash": "~2.4.1",<% if(filters.babel) { %> + "babel-core": "^5.6.4",<% } %><% if (filters.jade) { %> "jade": "~1.2.0",<% } %><% if (filters.html) { %> "ejs": "~0.8.4",<% } %><% if (filters.mongoose) { %> "mongoose": "~3.8.8", @@ -106,7 +107,7 @@ "node": ">=0.10.0" }, "scripts": { - "start": "node server/app.js", + "start": "node server", "test": "grunt test", "update-webdriver": "node node_modules/grunt-protractor-runner/node_modules/protractor/bin/webdriver-manager update" }, diff --git a/app/templates/mocha.conf.js b/app/templates/mocha.conf.js index 54e33bb6f..6b1504e9c 100644 --- a/app/templates/mocha.conf.js +++ b/app/templates/mocha.conf.js @@ -1,4 +1,7 @@ -'use strict'; +'use strict';<% if(filters.babel) { %> + +// Register the Babel require hook +require('babel-core/register');<% } %> var chai = require('chai'); diff --git a/app/templates/server/index.js b/app/templates/server/index.js new file mode 100644 index 000000000..7722a0e6c --- /dev/null +++ b/app/templates/server/index.js @@ -0,0 +1,7 @@ +'use strict';<% if (filters.babel) { %> + +// Register the Babel require hook +require('babel-core/register');<% } %> + +// Export the application +exports = module.exports = require('./app'); diff --git a/test/test-file-creation.js b/test/test-file-creation.js index a863700be..ec794c7ab 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -11,6 +11,7 @@ var recursiveReadDir = require('recursive-readdir'); describe('angular-fullstack generator', function () { var gen, defaultOptions = { script: 'js', + babel: true, markup: 'html', stylesheet: 'sass', router: 'uirouter', @@ -176,6 +177,7 @@ describe('angular-fullstack generator', function () { 'server/.jshintrc', 'server/.jshintrc-spec', 'server/app.js', + 'server/index.js', 'server/routes.js', 'server/api/thing/index.js', 'server/api/thing/index.spec.js', @@ -476,49 +478,6 @@ describe('angular-fullstack generator', function () { } }); - describe('with Babel ES6 preprocessor', function() { - beforeEach(function() { - helpers.mockPrompt(gen, { - script: 'js', - babel: true, - markup: 'jade', - stylesheet: 'less', - router: 'uirouter' - }); - }); - - it('should run client tests successfully', function(done) { - this.timeout(60000); - gen.run({}, function () { - exec('grunt test:client', function (error, stdout, stderr) { - expect(stdout, 'Client tests failed \n' + stdout ).to.contain('Executed 1 of 1 SUCCESS'); - done(); - }); - }); - }); - - it('should pass jshint', function(done) { - this.timeout(60000); - gen.run({}, function () { - exec('grunt jshint', function (error, stdout, stderr) { - expect(stdout).to.contain('Done, without errors.'); - done(); - }); - }); - }); - - it('should run server tests successfully', function(done) { - this.timeout(60000); - gen.run({}, function () { - exec('grunt test:server', function (error, stdout, stderr) { - expect(stdout, 'Server tests failed (do you have mongoDB running?) \n' + stdout).to.contain('Done, without errors.'); - done(); - }); - }); - }); - }); - - describe('with other preprocessors and oauth', function() { var testOptions = { script: 'coffee', From f87b34c005566026bfce07c9d283719706b675fc Mon Sep 17 00:00:00 2001 From: kingcody Date: Sun, 28 Jun 2015 01:50:32 -0400 Subject: [PATCH 0103/1357] chore(dependencies): remove unused dependency wiredep --- app/index.js | 1 - package.json | 1 - 2 files changed, 2 deletions(-) diff --git a/app/index.js b/app/index.js index 15f8f3b95..b987d44ce 100644 --- a/app/index.js +++ b/app/index.js @@ -5,7 +5,6 @@ var util = require('util'); var genUtils = require('../util.js'); var yeoman = require('yeoman-generator'); var chalk = require('chalk'); -var wiredep = require('wiredep'); var AngularFullstackGenerator = yeoman.generators.Base.extend({ diff --git a/package.json b/package.json index c9e55b21b..0f35ef723 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,6 @@ "dependencies": { "yeoman-generator": "~0.17.0", "chalk": "~0.4.0", - "wiredep": "~0.4.2", "generator-ng-component": "~0.0.4" }, "peerDependencies": { From 3a63454beb96249339af557698f6f54d71202f46 Mon Sep 17 00:00:00 2001 From: Antoine Pairet Date: Tue, 30 Jun 2015 20:28:46 +0200 Subject: [PATCH 0104/1357] Fix Grunfile.js ngAnnotate task src Fix Grunfile.js ngAnnotate task src from `*/**.js` to `**/*.js` --- app/templates/Gruntfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 96a662066..6685f5108 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -349,7 +349,7 @@ module.exports = function (grunt) { files: [{ expand: true, cwd: '.tmp/concat', - src: '*/**.js', + src: '**/*.js', dest: '.tmp/concat' }] } From df82d171488fcff5fdbc19ba255cc6f942b3e593 Mon Sep 17 00:00:00 2001 From: kingcody Date: Sun, 5 Jul 2015 07:49:10 -0400 Subject: [PATCH 0105/1357] fix(endpoint): fully support sequelize models --- endpoint/templates/index.js | 2 +- endpoint/templates/index.spec.js | 6 +- endpoint/templates/name.controller.js | 71 +++++++++++++------ endpoint/templates/name.integration.js | 6 +- ...oose).js => name.model(mongooseModels).js} | 0 ...ize).js => name.model(sequelizeModels).js} | 0 6 files changed, 58 insertions(+), 27 deletions(-) rename endpoint/templates/{name.model(mongoose).js => name.model(mongooseModels).js} (100%) rename endpoint/templates/{name.model(sequelize).js => name.model(sequelizeModels).js} (100%) diff --git a/endpoint/templates/index.js b/endpoint/templates/index.js index 3f8c592a6..60198d142 100644 --- a/endpoint/templates/index.js +++ b/endpoint/templates/index.js @@ -5,7 +5,7 @@ var controller = require('./<%= name %>.controller'); var router = express.Router(); -router.get('/', controller.index);<% if(filters.mongoose) { %> +router.get('/', controller.index);<% if (filters.models) { %> router.get('/:id', controller.show); router.post('/', controller.create); router.put('/:id', controller.update); diff --git a/endpoint/templates/index.spec.js b/endpoint/templates/index.spec.js index ccd15ec7e..291a04662 100644 --- a/endpoint/templates/index.spec.js +++ b/endpoint/templates/index.spec.js @@ -3,7 +3,7 @@ var proxyquire = require('proxyquire').noPreserveCache(); var <%= cameledName %>CtrlStub = { - index: '<%= name %>Ctrl.index'<% if(filters.mongoose) { %>, + index: '<%= name %>Ctrl.index'<% if(filters.models) { %>, show: '<%= name %>Ctrl.show', create: '<%= name %>Ctrl.create', update: '<%= name %>Ctrl.update', @@ -11,7 +11,7 @@ var <%= cameledName %>CtrlStub = { }; var routerStub = { - get: sinon.spy()<% if(filters.mongoose) { %>, + get: sinon.spy()<% if(filters.models) { %>, put: sinon.spy(), patch: sinon.spy(), post: sinon.spy(), @@ -42,7 +42,7 @@ describe('<%= classedName %> API Router:', function() { .should.have.been.calledOnce; }); - });<% if(filters.mongoose) { %> + });<% if(filters.models) { %> describe('GET <%= route %>/:id', function() { diff --git a/endpoint/templates/name.controller.js b/endpoint/templates/name.controller.js index 7d03a42ee..abcc5f34b 100644 --- a/endpoint/templates/name.controller.js +++ b/endpoint/templates/name.controller.js @@ -1,7 +1,18 @@ -'use strict';<% if(filters.mongoose) { %> +/** + * Using Rails-like standard naming convention for endpoints. + * GET <%= route %> -> index<% if (filters.models) { %> + * POST <%= route %> -> create + * GET <%= route %>/:id -> show + * PUT <%= route %>/:id -> update + * DELETE <%= route %>/:id -> destroy<% } %> + */ -var _ = require('lodash'); -var <%= classedName %> = require('./<%= name %>.model'); +'use strict';<% if (filters.models) { %> + +var _ = require('lodash');<% if (filters.mongooseModels) { %> +var <%= classedName %> = require('./<%= name %>.model');<% } if (filters.sequelizeModels) { %> +var sqldb = require('../../sqldb'); +var <%= classedName %> = sqldb.<%= classedName %>;<% } %> function handleError(res, statusCode) { statusCode = statusCode || 500; @@ -14,7 +25,7 @@ function responseWithResult(res, statusCode) { statusCode = statusCode || 200; return function(entity) { if (entity) { - return res.status(statusCode).json(entity); + res.status(statusCode).json(entity); } }; } @@ -31,9 +42,11 @@ function handleEntityNotFound(res) { function saveUpdates(updates) { return function(entity) { - var updated = _.merge(entity, updates); + <% if (filters.mongooseModels) { %>var updated = _.merge(entity, updates); return updated.saveAsync() - .spread(function(updated) { + .spread(function(updated) {<% } + if (filters.sequelizeModels) { %>return entity.updateAttributes(updates) + .then(function(updated) {<% } %> return updated; }); }; @@ -42,7 +55,8 @@ function saveUpdates(updates) { function removeEntity(res) { return function(entity) { if (entity) { - return entity.removeAsync() + <% if (filters.mongooseModels) { %>return entity.removeAsync()<% } + if (filters.sequelizeModels) { %>return entity.destroy()<% } %> .then(function() { res.status(204).end(); }); @@ -50,44 +64,61 @@ function removeEntity(res) { }; }<% } %> -// Get list of <%= name %>s -exports.index = function(req, res) {<% if (!filters.mongoose) { %> - res.json([]);<% } %><% if (filters.mongoose) { %> - <%= classedName %>.findAsync() +// Gets a list of <%= name %>s +exports.index = function(req, res) {<% if (!filters.models) { %> + res.json([]);<% } else { %> + <% if (filters.mongooseModels) { %><%= classedName %>.findAsync()<% } + if (filters.sequelizeModels) { %><%= classedName %>.findAll()<% } %> .then(responseWithResult(res)) .catch(handleError(res));<% } %> -};<% if (filters.mongoose) { %> +};<% if (filters.models) { %> -// Gets a single <%= name %> from the DB. +// Gets a single <%= name %> from the DB exports.show = function(req, res) { - <%= classedName %>.findByIdAsync(req.params.id) + <% if (filters.mongooseModels) { %><%= classedName %>.findByIdAsync(req.params.id)<% } + if (filters.sequelizeModels) { %><%= classedName %>.find({ + where: { + _id: req.params.id + } + })<% } %> .then(handleEntityNotFound(res)) .then(responseWithResult(res)) .catch(handleError(res)); }; -// Creates a new <%= name %> in the DB. +// Creates a new <%= name %> in the DB exports.create = function(req, res) { - <%= classedName %>.createAsync(req.body) + <% if (filters.mongooseModels) { %><%= classedName %>.createAsync(req.body)<% } + if (filters.sequelizeModels) { %><%= classedName %>.create(req.body)<% } %> .then(responseWithResult(res, 201)) .catch(handleError(res)); }; -// Updates an existing <%= name %> in the DB. +// Updates an existing <%= name %> in the DB exports.update = function(req, res) { if (req.body._id) { delete req.body._id; } - <%= classedName %>.findByIdAsync(req.params.id) + <% if (filters.mongooseModels) { %><%= classedName %>.findByIdAsync(req.params.id)<% } + if (filters.sequelizeModels) { %><%= classedName %>.find({ + where: { + _id: req.params.id + } + })<% } %> .then(handleEntityNotFound(res)) .then(saveUpdates(req.body)) .then(responseWithResult(res)) .catch(handleError(res)); }; -// Deletes a <%= name %> from the DB. +// Deletes a <%= name %> from the DB exports.destroy = function(req, res) { - <%= classedName %>.findByIdAsync(req.params.id) + <% if (filters.mongooseModels) { %><%= classedName %>.findByIdAsync(req.params.id)<% } + if (filters.sequelizeModels) { %><%= classedName %>.find({ + where: { + _id: req.params.id + } + })<% } %> .then(handleEntityNotFound(res)) .then(removeEntity(res)) .catch(handleError(res)); diff --git a/endpoint/templates/name.integration.js b/endpoint/templates/name.integration.js index a377456a4..160cdedfa 100644 --- a/endpoint/templates/name.integration.js +++ b/endpoint/templates/name.integration.js @@ -1,7 +1,7 @@ 'use strict'; var app = require('../../app'); -var request = require('supertest');<% if(filters.mongoose) { %> +var request = require('supertest');<% if(filters.models) { %> var new<%= classedName %>;<% } %> @@ -28,7 +28,7 @@ describe('<%= classedName %> API:', function() { <%= cameledName %>s.should.be.instanceOf(Array); }); - });<% if(filters.mongoose) { %> + });<% if(filters.models) { %> describe('POST <%= route %>', function() { beforeEach(function(done) { @@ -130,7 +130,7 @@ describe('<%= classedName %> API:', function() { }); }); - it('should respond with 404 when <%= name %> does not exsist', function(done) { + it('should respond with 404 when <%= name %> does not exist', function(done) { request(app) .delete('<%= route %>/' + new<%= classedName %>._id) .expect(404) diff --git a/endpoint/templates/name.model(mongoose).js b/endpoint/templates/name.model(mongooseModels).js similarity index 100% rename from endpoint/templates/name.model(mongoose).js rename to endpoint/templates/name.model(mongooseModels).js diff --git a/endpoint/templates/name.model(sequelize).js b/endpoint/templates/name.model(sequelizeModels).js similarity index 100% rename from endpoint/templates/name.model(sequelize).js rename to endpoint/templates/name.model(sequelizeModels).js From f8f32f4f67938a5f7416e2a07d7b24d71a12585f Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 7 Jul 2015 10:41:54 -0400 Subject: [PATCH 0106/1357] feat(readme): add david-dm badge & move badges to new line --- readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 21169c3fb..1fa4c1899 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,5 @@ -# AngularJS Full-Stack generator [![Build Status](https://travis-ci.org/DaftMonk/generator-angular-fullstack.svg?branch=master)](http://travis-ci.org/DaftMonk/generator-angular-fullstack) [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/DaftMonk/generator-angular-fullstack) +# AngularJS Full-Stack generator +[![Build Status](https://travis-ci.org/DaftMonk/generator-angular-fullstack.svg?branch=master)](http://travis-ci.org/DaftMonk/generator-angular-fullstack) ![](https://david-dm.org/daftmonk/generator-angular-fullstack.png) [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/DaftMonk/generator-angular-fullstack) > Yeoman generator for creating MEAN stack applications, using MongoDB, Express, AngularJS, and Node - lets you quickly set up a project following best practices. From 6dc81306fea1abcf57f293f91776e00e9d50ad26 Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 7 Jul 2015 19:36:50 -0400 Subject: [PATCH 0107/1357] feat(gen): use common endpoint templates for thing route --- app/index.js | 685 +++++++++--------- app/templates/server/api/thing/index.js | 15 - app/templates/server/api/thing/index.spec.js | 97 --- .../api/thing/thing.controller(models).js | 124 ---- .../api/thing/thing.controller(noModels).js | 38 - .../server/api/thing/thing.integration.js | 147 ---- .../api/thing/thing.model(mongooseModels).js | 12 - .../api/thing/thing.model(sequelizeModels).js | 15 - .../api/thing/thing.socket(socketio).js | 33 - 9 files changed, 359 insertions(+), 807 deletions(-) delete mode 100644 app/templates/server/api/thing/index.js delete mode 100644 app/templates/server/api/thing/index.spec.js delete mode 100644 app/templates/server/api/thing/thing.controller(models).js delete mode 100644 app/templates/server/api/thing/thing.controller(noModels).js delete mode 100644 app/templates/server/api/thing/thing.integration.js delete mode 100644 app/templates/server/api/thing/thing.model(mongooseModels).js delete mode 100644 app/templates/server/api/thing/thing.model(sequelizeModels).js delete mode 100644 app/templates/server/api/thing/thing.socket(socketio).js diff --git a/app/index.js b/app/index.js index b987d44ce..5c3ef0673 100644 --- a/app/index.js +++ b/app/index.js @@ -8,379 +8,412 @@ var chalk = require('chalk'); var AngularFullstackGenerator = yeoman.generators.Base.extend({ - init: function () { - this.argument('name', { type: String, required: false }); - this.appname = this.name || path.basename(process.cwd()); - this.appname = this._.camelize(this._.slugify(this._.humanize(this.appname))); - - this.option('app-suffix', { - desc: 'Allow a custom suffix to be added to the module name', - type: String, - required: 'false' - }); - this.scriptAppName = this.appname + genUtils.appName(this); - this.appPath = this.env.options.appPath; - this.pkg = require('../package.json'); - - this.filters = {}; - - // dynamic assertion statement - this.does = this.is = function(foo) { - if (this.filters.should) { - return foo + '.should'; + initializing: { + + init: function () { + this.argument('name', { type: String, required: false }); + this.appname = this.name || path.basename(process.cwd()); + this.appname = this._.camelize(this._.slugify(this._.humanize(this.appname))); + + this.option('app-suffix', { + desc: 'Allow a custom suffix to be added to the module name', + type: String, + required: 'false' + }); + this.scriptAppName = this.appname + genUtils.appName(this); + this.appPath = this.env.options.appPath; + this.pkg = require('../package.json'); + + this.filters = {}; + + // dynamic assertion statement + this.does = this.is = function(foo) { + if (this.filters.should) { + return foo + '.should'; + } else { + return 'expect(' + foo + ').to'; + } + }.bind(this); + }, + + info: function () { + this.log(this.yeoman); + this.log('Out of the box I create an AngularJS app with an Express server.\n'); + }, + + checkForConfig: function() { + var cb = this.async(); + + if(this.config.get('filters')) { + this.prompt([{ + type: 'confirm', + name: 'skipConfig', + message: 'Existing .yo-rc configuration found, would you like to use it?', + default: true, + }], function (answers) { + this.skipConfig = answers.skipConfig; + + this.filters = this._.defaults(this.config.get('filters'), { + bootstrap: true, + uibootstrap: true, + jasmine: true + }); + + // NOTE: temp(?) fix for #403 + if(typeof this.filters.oauth==='undefined') { + var strategies = Object.keys(this.filters).filter(function(key) { + return key.match(/Auth$/) && key; + }); + + if(strategies.length) this.filters.oauth = true; + } + + this.config.forceSave(); + + cb(); + }.bind(this)); } else { - return 'expect(' + foo + ').to'; + cb(); } - }.bind(this); - }, + } - info: function () { - this.log(this.yeoman); - this.log('Out of the box I create an AngularJS app with an Express server.\n'); }, - checkForConfig: function() { - var cb = this.async(); + prompting: { - if(this.config.get('filters')) { - this.prompt([{ - type: 'confirm', - name: 'skipConfig', - message: 'Existing .yo-rc configuration found, would you like to use it?', - default: true, - }], function (answers) { - this.skipConfig = answers.skipConfig; - - this.filters = this._.defaults(this.config.get('filters'), { - bootstrap: true, - uibootstrap: true, - jasmine: true - }); - - // NOTE: temp(?) fix for #403 - if(typeof this.filters.oauth==='undefined') { - var strategies = Object.keys(this.filters).filter(function(key) { - return key.match(/Auth$/) && key; - }); - - if(strategies.length) this.filters.oauth = true; - } + clientPrompts: function() { + if(this.skipConfig) return; + var cb = this.async(); - this.config.forceSave(); + this.log('# Client\n'); - cb(); - }.bind(this)); - } else { - cb(); - } - }, + this.prompt([{ + type: 'list', + name: 'script', + message: 'What would you like to write scripts with?', + choices: [ 'JavaScript', 'CoffeeScript'], + filter: function( val ) { + var filterMap = { + 'JavaScript': 'js', + 'CoffeeScript': 'coffee' + }; + + return filterMap[val]; + } + }, { + type: 'confirm', + name: 'babel', + message: 'Would you like to use Javascript ES6 in your client by preprocessing it with Babel?', + when: function (answers) { + return answers.script === 'js'; + } + }, { + type: 'list', + name: 'markup', + message: 'What would you like to write markup with?', + choices: ['HTML', 'Jade'], + filter: function( val ) { return val.toLowerCase(); } + }, { + type: 'list', + name: 'stylesheet', + default: 1, + message: 'What would you like to write stylesheets with?', + choices: [ 'CSS', 'Sass', 'Stylus', 'Less'], + filter: function( val ) { return val.toLowerCase(); } + }, { + type: 'list', + name: 'router', + default: 1, + message: 'What Angular router would you like to use?', + choices: [ 'ngRoute', 'uiRouter'], + filter: function( val ) { return val.toLowerCase(); } + }, { + type: 'confirm', + name: 'bootstrap', + message: 'Would you like to include Bootstrap?' + }, { + type: 'confirm', + name: 'uibootstrap', + message: 'Would you like to include UI Bootstrap?', + when: function (answers) { + return answers.bootstrap; + } + }], function (answers) { + + this.filters.babel = !!answers.babel; + if(this.filters.babel){ this.filters.js = true; } + this.filters[answers.script] = true; + this.filters[answers.markup] = true; + this.filters[answers.stylesheet] = true; + this.filters[answers.router] = true; + this.filters.bootstrap = !!answers.bootstrap; + this.filters.uibootstrap = !!answers.uibootstrap; + cb(); + }.bind(this)); + }, - clientPrompts: function() { - if(this.skipConfig) return; - var cb = this.async(); + serverPrompts: function() { + if(this.skipConfig) return; + var cb = this.async(); + var self = this; - this.log('# Client\n'); + this.log('\n# Server\n'); - this.prompt([{ + this.prompt([{ + type: 'checkbox', + name: 'odms', + message: 'What would you like to use for data modeling?', + choices: [ + { + value: 'mongoose', + name: 'Mongoose (MongoDB)', + checked: true + }, + { + value: 'sequelize', + name: 'Sequelize (MySQL, SQLite, MariaDB, PostgreSQL)', + checked: false + } + ] + }, { type: 'list', - name: 'script', - message: 'What would you like to write scripts with?', - choices: [ 'JavaScript', 'CoffeeScript'], + name: 'models', + message: 'What would you like to use for the default models?', + choices: [ 'Mongoose', 'Sequelize' ], filter: function( val ) { - var filterMap = { - 'JavaScript': 'js', - 'CoffeeScript': 'coffee' - }; - - return filterMap[val]; + return val.toLowerCase(); + }, + when: function(answers) { + return answers.odms && answers.odms.length > 1; } }, { type: 'confirm', - name: 'babel', - message: 'Would you like to use Javascript ES6 in your client by preprocessing it with Babel?', + name: 'auth', + message: 'Would you scaffold out an authentication boilerplate?', when: function (answers) { - return answers.script === 'js'; + return answers.odms && answers.odms.length !== 0; } }, { - type: 'list', - name: 'markup', - message: 'What would you like to write markup with?', - choices: ['HTML', 'Jade'], - filter: function( val ) { return val.toLowerCase(); } - }, { - type: 'list', - name: 'stylesheet', - default: 1, - message: 'What would you like to write stylesheets with?', - choices: [ 'CSS', 'Sass', 'Stylus', 'Less'], - filter: function( val ) { return val.toLowerCase(); } - }, { - type: 'list', - name: 'router', - default: 1, - message: 'What Angular router would you like to use?', - choices: [ 'ngRoute', 'uiRouter'], - filter: function( val ) { return val.toLowerCase(); } - }, { - type: 'confirm', - name: 'bootstrap', - message: 'Would you like to include Bootstrap?' + type: 'checkbox', + name: 'oauth', + message: 'Would you like to include additional oAuth strategies?', + when: function (answers) { + return answers.auth; + }, + choices: [ + { + value: 'googleAuth', + name: 'Google', + checked: false + }, + { + value: 'facebookAuth', + name: 'Facebook', + checked: false + }, + { + value: 'twitterAuth', + name: 'Twitter', + checked: false + } + ] }, { type: 'confirm', - name: 'uibootstrap', - message: 'Would you like to include UI Bootstrap?', + name: 'socketio', + message: 'Would you like to use socket.io?', + // to-do: should not be dependent on ODMs when: function (answers) { - return answers.bootstrap; - } + return answers.odms && answers.odms.length !== 0; + }, + default: true }], function (answers) { + if(answers.socketio) this.filters.socketio = true; + if(answers.auth) this.filters.auth = true; + if(answers.odms && answers.odms.length > 0) { + var models; + if(!answers.models) { + models = answers.odms[0]; + } else { + models = answers.models; + } + this.filters.models = true; + this.filters[models + 'Models'] = true; + answers.odms.forEach(function(odm) { + this.filters[odm] = true; + }.bind(this)); + } else { + this.filters.noModels = true; + } + if(answers.oauth) { + if(answers.oauth.length) this.filters.oauth = true; + answers.oauth.forEach(function(oauthStrategy) { + this.filters[oauthStrategy] = true; + }.bind(this)); + } - this.filters.babel = !!answers.babel; - if(this.filters.babel){ this.filters.js = true; } - this.filters[answers.script] = true; - this.filters[answers.markup] = true; - this.filters[answers.stylesheet] = true; - this.filters[answers.router] = true; - this.filters.bootstrap = !!answers.bootstrap; - this.filters.uibootstrap = !!answers.uibootstrap; cb(); }.bind(this)); - }, + }, - serverPrompts: function() { - if(this.skipConfig) return; - var cb = this.async(); - var self = this; - - this.log('\n# Server\n'); - - this.prompt([{ - type: 'checkbox', - name: 'odms', - message: 'What would you like to use for data modeling?', - choices: [ - { - value: 'mongoose', - name: 'Mongoose (MongoDB)', - checked: true - }, - { - value: 'sequelize', - name: 'Sequelize (MySQL, SQLite, MariaDB, PostgreSQL)', - checked: false + projectPrompts: function() { + if(this.skipConfig) return; + var cb = this.async(); + var self = this; + + this.log('\n# Project\n'); + + this.prompt([{ + type: 'list', + name: 'testing', + message: 'What would you like to write tests with?', + choices: [ 'Jasmine', 'Mocha + Chai + Sinon'], + filter: function( val ) { + var filterMap = { + 'Jasmine': 'jasmine', + 'Mocha + Chai + Sinon': 'mocha' + }; + + return filterMap[val]; } - ] - }, { - type: 'list', - name: 'models', - message: 'What would you like to use for the default models?', - choices: [ 'Mongoose', 'Sequelize' ], - filter: function( val ) { - return val.toLowerCase(); - }, - when: function(answers) { - return answers.odms && answers.odms.length > 1; - } - }, { - type: 'confirm', - name: 'auth', - message: 'Would you scaffold out an authentication boilerplate?', - when: function (answers) { - return answers.odms && answers.odms.length !== 0; - } - }, { - type: 'checkbox', - name: 'oauth', - message: 'Would you like to include additional oAuth strategies?', - when: function (answers) { - return answers.auth; - }, - choices: [ - { - value: 'googleAuth', - name: 'Google', - checked: false - }, - { - value: 'facebookAuth', - name: 'Facebook', - checked: false + }, { + type: 'list', + name: 'chai', + message: 'What would you like to write Chai assertions with?', + choices: ['Expect', 'Should'], + filter: function( val ) { + return val.toLowerCase(); }, - { - value: 'twitterAuth', - name: 'Twitter', - checked: false + when: function( answers ) { + return answers.testing === 'mocha'; } - ] - }, { - type: 'confirm', - name: 'socketio', - message: 'Would you like to use socket.io?', - // to-do: should not be dependent on ODMs - when: function (answers) { - return answers.odms && answers.odms.length !== 0; - }, - default: true - }], function (answers) { - if(answers.socketio) this.filters.socketio = true; - if(answers.auth) this.filters.auth = true; - if(answers.odms && answers.odms.length > 0) { - var models; - if(!answers.models) { - models = answers.odms[0]; - } else { - models = answers.models; + }], function (answers) { + this.filters[answers.testing] = true; + if (answers.testing === 'mocha') { + this.filters.jasmine = false; + this.filters.should = false; + this.filters.expect = false; + this.filters[answers.chai] = true; + } + if (answers.testing === 'jasmine') { + this.filters.mocha = false; + this.filters.should = false; + this.filters.expect = false; } - this.filters.models = true; - this.filters[models + 'Models'] = true; - answers.odms.forEach(function(odm) { - this.filters[odm] = true; - }.bind(this)); - } else { - this.filters.noModels = true; - } - if(answers.oauth) { - if(answers.oauth.length) this.filters.oauth = true; - answers.oauth.forEach(function(oauthStrategy) { - this.filters[oauthStrategy] = true; - }.bind(this)); - } - cb(); - }.bind(this)); + cb(); + }.bind(this)); + } + }, - projectPrompts: function() { - if(this.skipConfig) return; - var cb = this.async(); - var self = this; - - this.log('\n# Project\n'); - - this.prompt([{ - type: 'list', - name: 'testing', - message: 'What would you like to write tests with?', - choices: [ 'Jasmine', 'Mocha + Chai + Sinon'], - filter: function( val ) { - var filterMap = { - 'Jasmine': 'jasmine', - 'Mocha + Chai + Sinon': 'mocha' - }; - - return filterMap[val]; - } - }, { - type: 'list', - name: 'chai', - message: 'What would you like to write Chai assertions with?', - choices: ['Expect', 'Should'], - filter: function( val ) { - return val.toLowerCase(); - }, - when: function( answers ) { - return answers.testing === 'mocha'; - } - }], function (answers) { - this.filters[answers.testing] = true; - if (answers.testing === 'mocha') { - this.filters.jasmine = false; - this.filters.should = false; - this.filters.expect = false; - this.filters[answers.chai] = true; - } - if (answers.testing === 'jasmine') { - this.filters.mocha = false; - this.filters.should = false; - this.filters.expect = false; - } + configuring: { + + saveSettings: function() { + if(this.skipConfig) return; + this.config.set('insertRoutes', true); + this.config.set('registerRoutesFile', 'server/routes.js'); + this.config.set('routesNeedle', '// Insert routes below'); + + this.config.set('routesBase', '/api/'); + this.config.set('pluralizeRoutes', true); + + this.config.set('insertSockets', true); + this.config.set('registerSocketsFile', 'server/config/socketio.js'); + this.config.set('socketsNeedle', '// Insert sockets below'); + + this.config.set('insertModels', true); + this.config.set('registerModelsFile', 'server/sqldb/index.js'); + this.config.set('modelsNeedle', '// Insert models below'); + + this.config.set('filters', this.filters); + this.config.forceSave(); + }, + + ngComponent: function() { + if(this.skipConfig) return; + var appPath = 'client/app/'; + var extensions = []; + var filters = [ + 'ngroute', + 'uirouter', + 'jasmine', + 'mocha', + 'expect', + 'should' + ].filter(function(v) {return this.filters[v];}, this); + + if(this.filters.ngroute) filters.push('ngroute'); + if(this.filters.uirouter) filters.push('uirouter'); + if(this.filters.babel) extensions.push('babel'); + if(this.filters.coffee) extensions.push('coffee'); + if(this.filters.js) extensions.push('js'); + if(this.filters.html) extensions.push('html'); + if(this.filters.jade) extensions.push('jade'); + if(this.filters.css) extensions.push('css'); + if(this.filters.stylus) extensions.push('styl'); + if(this.filters.sass) extensions.push('scss'); + if(this.filters.less) extensions.push('less'); + + this.composeWith('ng-component', { + options: { + 'routeDirectory': appPath, + 'directiveDirectory': appPath, + 'filterDirectory': appPath, + 'serviceDirectory': appPath, + 'filters': filters, + 'extensions': extensions, + 'basePath': 'client' + } + }, { local: require.resolve('generator-ng-component/app/index.js') }); + }, + + ngModules: function() { + var angModules = [ + "'ngCookies'", + "'ngResource'", + "'ngSanitize'" + ]; + if(this.filters.ngroute) angModules.push("'ngRoute'"); + if(this.filters.socketio) angModules.push("'btford.socket-io'"); + if(this.filters.uirouter) angModules.push("'ui.router'"); + if(this.filters.uibootstrap) angModules.push("'ui.bootstrap'"); + + this.angularModules = '\n ' + angModules.join(',\n ') +'\n'; + } - cb(); - }.bind(this)); }, - saveSettings: function() { - if(this.skipConfig) return; - this.config.set('insertRoutes', true); - this.config.set('registerRoutesFile', 'server/routes.js'); - this.config.set('routesNeedle', '// Insert routes below'); + default: {}, - this.config.set('routesBase', '/api/'); - this.config.set('pluralizeRoutes', true); + writing: { - this.config.set('insertSockets', true); - this.config.set('registerSocketsFile', 'server/config/socketio.js'); - this.config.set('socketsNeedle', '// Insert sockets below'); + generateProject: function() { + this.sourceRoot(path.join(__dirname, './templates')); + genUtils.processDirectory(this, '.', '.'); + }, - this.config.set('insertModels', true); - this.config.set('registerModelsFile', 'server/sqldb/index.js'); - this.config.set('modelsNeedle', '// Insert models below'); + generateEndpoint: function() { + var name = this.name = this.cameledName = 'thing'; + this.classedName = name.charAt(0).toUpperCase() + name.slice(1); + this.route = '/api/' + name + 's'; + this.sourceRoot(path.join(__dirname, '..', 'endpoint', 'templates')); + genUtils.processDirectory(this, '.', 'server/api/' + name); + } - this.config.set('filters', this.filters); - this.config.forceSave(); }, - compose: function() { - if(this.skipConfig) return; - var appPath = 'client/app/'; - var extensions = []; - var filters = [ - 'ngroute', - 'uirouter', - 'jasmine', - 'mocha', - 'expect', - 'should' - ].filter(function(v) {return this.filters[v];}, this); - - if(this.filters.ngroute) filters.push('ngroute'); - if(this.filters.uirouter) filters.push('uirouter'); - if(this.filters.babel) extensions.push('babel'); - if(this.filters.coffee) extensions.push('coffee'); - if(this.filters.js) extensions.push('js'); - if(this.filters.html) extensions.push('html'); - if(this.filters.jade) extensions.push('jade'); - if(this.filters.css) extensions.push('css'); - if(this.filters.stylus) extensions.push('styl'); - if(this.filters.sass) extensions.push('scss'); - if(this.filters.less) extensions.push('less'); - - this.composeWith('ng-component', { - options: { - 'routeDirectory': appPath, - 'directiveDirectory': appPath, - 'filterDirectory': appPath, - 'serviceDirectory': appPath, - 'filters': filters, - 'extensions': extensions, - 'basePath': 'client' - } - }, { local: require.resolve('generator-ng-component/app/index.js') }); - }, + install: { - ngModules: function() { - var angModules = [ - "'ngCookies'", - "'ngResource'", - "'ngSanitize'" - ]; - if(this.filters.ngroute) angModules.push("'ngRoute'"); - if(this.filters.socketio) angModules.push("'btford.socket-io'"); - if(this.filters.uirouter) angModules.push("'ui.router'"); - if(this.filters.uibootstrap) angModules.push("'ui.bootstrap'"); - - this.angularModules = '\n ' + angModules.join(',\n ') +'\n'; - }, + installDeps: function() { + this.installDependencies({ + skipInstall: this.options['skip-install'] + }); + } - generate: function() { - this.sourceRoot(path.join(__dirname, './templates')); - genUtils.processDirectory(this, '.', '.'); }, - end: function() { - this.installDependencies({ - skipInstall: this.options['skip-install'] - }); - } + end: {} + }); module.exports = AngularFullstackGenerator; diff --git a/app/templates/server/api/thing/index.js b/app/templates/server/api/thing/index.js deleted file mode 100644 index fde8f3968..000000000 --- a/app/templates/server/api/thing/index.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -var express = require('express'); -var controller = require('./thing.controller'); - -var router = express.Router(); - -router.get('/', controller.index);<% if (filters.models) { %> -router.get('/:id', controller.show); -router.post('/', controller.create); -router.put('/:id', controller.update); -router.patch('/:id', controller.update); -router.delete('/:id', controller.destroy);<% } %> - -module.exports = router; diff --git a/app/templates/server/api/thing/index.spec.js b/app/templates/server/api/thing/index.spec.js deleted file mode 100644 index 91f02f6df..000000000 --- a/app/templates/server/api/thing/index.spec.js +++ /dev/null @@ -1,97 +0,0 @@ -'use strict'; - -var proxyquire = require('proxyquire').noPreserveCache(); - -var thingCtrlStub = { - index: 'thingCtrl.index'<% if (filters.models) { %>, - show: 'thingCtrl.show', - create: 'thingCtrl.create', - update: 'thingCtrl.update', - destroy: 'thingCtrl.destroy'<% } %> -}; - -var routerStub = { - get: sinon.spy()<% if (filters.models) { %>, - put: sinon.spy(), - patch: sinon.spy(), - post: sinon.spy(), - delete: sinon.spy()<% } %> -}; - -// require the index with our stubbed out modules -var thingIndex = proxyquire('./index.js', { - 'express': { - Router: function() { - return routerStub; - } - }, - './thing.controller': thingCtrlStub -}); - -describe('Thing API Router:', function() { - - it('should return an express router instance', function() { - thingIndex.should.equal(routerStub); - }); - - describe('GET /api/things', function() { - - it('should route to thing.controller.index', function() { - routerStub.get - .withArgs('/', 'thingCtrl.index') - .should.have.been.calledOnce; - }); - - });<% if (filters.models) { %> - - describe('GET /api/things/:id', function() { - - it('should route to thing.controller.show', function() { - routerStub.get - .withArgs('/:id', 'thingCtrl.show') - .should.have.been.calledOnce; - }); - - }); - - describe('POST /api/things', function() { - - it('should route to thing.controller.create', function() { - routerStub.post - .withArgs('/', 'thingCtrl.create') - .should.have.been.calledOnce; - }); - - }); - - describe('PUT /api/things/:id', function() { - - it('should route to thing.controller.update', function() { - routerStub.put - .withArgs('/:id', 'thingCtrl.update') - .should.have.been.calledOnce; - }); - - }); - - describe('PATCH /api/things/:id', function() { - - it('should route to thing.controller.update', function() { - routerStub.patch - .withArgs('/:id', 'thingCtrl.update') - .should.have.been.calledOnce; - }); - - }); - - describe('DELETE /api/things/:id', function() { - - it('should route to thing.controller.destroy', function() { - routerStub.delete - .withArgs('/:id', 'thingCtrl.destroy') - .should.have.been.calledOnce; - }); - - });<% } %> - -}); diff --git a/app/templates/server/api/thing/thing.controller(models).js b/app/templates/server/api/thing/thing.controller(models).js deleted file mode 100644 index c7874b515..000000000 --- a/app/templates/server/api/thing/thing.controller(models).js +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Using Rails-like standard naming convention for endpoints. - * GET /things -> index - * POST /things -> create - * GET /things/:id -> show - * PUT /things/:id -> update - * DELETE /things/:id -> destroy - */ - -'use strict'; - -var _ = require('lodash');<% if (filters.mongooseModels) { %> -var Thing = require('./thing.model');<% } %><% if (filters.sequelizeModels) { %> -var sqldb = require('../../sqldb') -var Thing = sqldb.Thing;<% } %> - -function handleError(res, statusCode) { - statusCode = statusCode || 500; - return function(err) { - res.status(statusCode).send(err); - }; -} - -function responseWithResult(res, statusCode) { - statusCode = statusCode || 200; - return function(entity) { - if (entity) { - return res.status(statusCode).json(entity); - } - }; -} - -function handleEntityNotFound(res) { - return function(entity) { - if (!entity) { - res.status(404).end(); - return null; - } - return entity; - }; -} - -function saveUpdates(updates) { - return function(entity) { - <% if (filters.mongooseModels) { %>var updated = _.merge(entity, updates); - return updated.saveAsync() - .spread(function(updated) {<% } - if (filters.sequelizeModels) { %>return entity.updateAttributes(updates) - .then(function(updated) {<% } %> - return updated; - }); - }; -} - -function removeEntity(res) { - return function(entity) { - if (entity) { - <% if (filters.mongooseModels) { %>return entity.removeAsync()<% } - if (filters.sequelizeModels) { %>return entity.destroy()<% } %> - .then(function() { - return res.status(204).end(); - }); - } - }; -} - -// Get list of things -exports.index = function(req, res) { - <% if (filters.mongooseModels) { %>Thing.findAsync()<% } - if (filters.sequelizeModels) { %>Thing.findAll()<% } %> - .then(responseWithResult(res)) - .catch(handleError(res)); -}; - -// Get a single thing -exports.show = function(req, res) { - <% if (filters.mongooseModels) { %>Thing.findByIdAsync(req.params.id)<% } - if (filters.sequelizeModels) { %>Thing.find({ - where: { - _id: req.params.id - } - })<% } %> - .then(handleEntityNotFound(res)) - .then(responseWithResult(res)) - .catch(handleError(res)); -}; - -// Creates a new thing in the DB. -exports.create = function(req, res) { - <% if (filters.mongooseModels) { %>Thing.createAsync(req.body)<% } - if (filters.sequelizeModels) { %>Thing.create(req.body)<% } %> - .then(responseWithResult(res, 201)) - .catch(handleError(res)); -}; - -// Updates an existing thing in the DB. -exports.update = function(req, res) { - if (req.body._id) { - delete req.body._id; - } - <% if (filters.mongooseModels) { %>Thing.findByIdAsync(req.params.id)<% } - if (filters.sequelizeModels) { %>Thing.find({ - where: { - _id: req.params.id - } - })<% } %> - .then(handleEntityNotFound(res)) - .then(saveUpdates(req.body)) - .then(responseWithResult(res)) - .catch(handleError(res)); -}; - -// Deletes a thing from the DB. -exports.destroy = function(req, res) { - <% if (filters.mongooseModels) { %>Thing.findByIdAsync(req.params.id)<% } - if (filters.sequelizeModels) { %>Thing.find({ - where: { - _id: req.params.id - } - })<% } %> - .then(handleEntityNotFound(res)) - .then(removeEntity(res)) - .catch(handleError(res)); -}; diff --git a/app/templates/server/api/thing/thing.controller(noModels).js b/app/templates/server/api/thing/thing.controller(noModels).js deleted file mode 100644 index a39041258..000000000 --- a/app/templates/server/api/thing/thing.controller(noModels).js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Using Rails-like standard naming convention for endpoints. - * GET /things -> index - * POST /things -> create - * GET /things/:id -> show - * PUT /things/:id -> update - * DELETE /things/:id -> destroy - */ - -'use strict'; - -// Get list of things -exports.index = function(req, res) { - res.json([{ - name: 'Development Tools', - info: 'Integration with popular tools such as Bower, Grunt, Karma, Mocha, JSHint, ' + - 'Node Inspector, Livereload, Protractor, Jade, Stylus, Sass, CoffeeScript, and Less.' - }, { - name: 'Server and Client integration', - info: 'Built with a powerful and fun stack: MongoDB, Express, AngularJS, and Node.' - }, { - name: 'Smart Build System', - info: 'Build system ignores `spec` files, allowing you to keep tests alongside code. ' + - 'Automatic injection of scripts and styles into your index.html' - }, { - name: 'Modular Structure', - info: 'Best practice client and server structures allow for more code reusability and ' + - 'maximum scalability' - }, { - name: 'Optimized Build', - info: 'Build process packs up your templates as a single JavaScript payload, minifies ' + - 'your scripts/css/images, and rewrites asset names for caching.' - }, { - name: 'Deployment Ready', - info: 'Easily deploy your app to Heroku or Openshift with the heroku and openshift ' + - 'sub-generators' - }]); -}; diff --git a/app/templates/server/api/thing/thing.integration.js b/app/templates/server/api/thing/thing.integration.js deleted file mode 100644 index 3eb5d05d8..000000000 --- a/app/templates/server/api/thing/thing.integration.js +++ /dev/null @@ -1,147 +0,0 @@ -'use strict'; - -var app = require('../../app'); -var request = require('supertest');<% if (filters.models) { %> - -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.models) { %> - - 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 exist', 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(mongooseModels).js b/app/templates/server/api/thing/thing.model(mongooseModels).js deleted file mode 100644 index d1e6e49ea..000000000 --- a/app/templates/server/api/thing/thing.model(mongooseModels).js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; - -var mongoose = require('mongoose-bird')(); -var Schema = mongoose.Schema; - -var ThingSchema = new Schema({ - name: String, - info: String, - active: Boolean -}); - -module.exports = mongoose.model('Thing', ThingSchema); diff --git a/app/templates/server/api/thing/thing.model(sequelizeModels).js b/app/templates/server/api/thing/thing.model(sequelizeModels).js deleted file mode 100644 index 8e8072da4..000000000 --- a/app/templates/server/api/thing/thing.model(sequelizeModels).js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -module.exports = function(sequelize, DataTypes) { - return sequelize.define('Thing', { - _id: { - type: DataTypes.INTEGER, - allowNull: false, - primaryKey: true, - autoIncrement: true - }, - name: DataTypes.STRING, - info: DataTypes.STRING, - active: DataTypes.BOOLEAN - }); -}; diff --git a/app/templates/server/api/thing/thing.socket(socketio).js b/app/templates/server/api/thing/thing.socket(socketio).js deleted file mode 100644 index d0d98a6ca..000000000 --- a/app/templates/server/api/thing/thing.socket(socketio).js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Broadcast updates to client when the model changes - */ - -'use strict'; -<% if (filters.mongooseModels) { %> -var thing = require('./thing.model');<% } %><% if (filters.sequelizeModels) { %> -var thing = require('../../sqldb').Thing;<% } %> - -exports.register = function(socket) {<% if (filters.sequelizeModels) { %> - thing.hook('afterCreate', function(doc, fields, fn) { - onSave(socket, doc); - fn(null); - });<% } %> - <% if (filters.mongooseModels) { %>thing.schema.post('save', function(doc) {<% } - if (filters.sequelizeModels) { %>thing.hook('afterUpdate', function(doc, fields, fn) {<% } %> - onSave(socket, doc);<% if (filters.sequelizeModels) { %> - fn(null);<% } %> - }); - <% if (filters.mongooseModels) { %>thing.schema.post('remove', function(doc) {<% } - if (filters.sequelizeModels) { %>thing.hook('afterDestroy', function(doc, fields, fn) {<% } %> - onRemove(socket, doc);<% if (filters.sequelizeModels) { %> - fn(null);<% } %> - }); -}; - -function onSave(socket, doc, cb) { - socket.emit('thing:save', doc); -} - -function onRemove(socket, doc, cb) { - socket.emit('thing:remove', doc); -} From 24171aa4962b460770876bf6232f6b82a27e9925 Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 7 Jul 2015 18:30:59 -0400 Subject: [PATCH 0108/1357] feat(app): implement navbar as directive --- .../client/app/account(auth)/login/login(html).html | 2 +- .../client/app/account(auth)/login/login(jade).jade | 2 +- .../app/account(auth)/settings/settings(html).html | 2 +- .../app/account(auth)/settings/settings(jade).jade | 2 +- .../client/app/account(auth)/signup/signup(html).html | 2 +- .../client/app/account(auth)/signup/signup(jade).jade | 2 +- app/templates/client/app/admin(auth)/admin(html).html | 2 +- app/templates/client/app/admin(auth)/admin(jade).jade | 4 ++-- app/templates/client/app/main/main(html).html | 2 +- app/templates/client/app/main/main(jade).jade | 4 ++-- .../components/navbar/navbar.directive(coffee).coffee | 7 +++++++ .../client/components/navbar/navbar.directive(js).js | 10 ++++++++++ test/test-file-creation.js | 1 + 13 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 app/templates/client/components/navbar/navbar.directive(coffee).coffee create mode 100644 app/templates/client/components/navbar/navbar.directive(js).js diff --git a/app/templates/client/app/account(auth)/login/login(html).html b/app/templates/client/app/account(auth)/login/login(html).html index f02de2616..667ecdd0e 100644 --- a/app/templates/client/app/account(auth)/login/login(html).html +++ b/app/templates/client/app/account(auth)/login/login(html).html @@ -1,4 +1,4 @@ -
+
diff --git a/app/templates/client/app/account(auth)/login/login(jade).jade b/app/templates/client/app/account(auth)/login/login(jade).jade index fd95e6ff1..e7ce91916 100644 --- a/app/templates/client/app/account(auth)/login/login(jade).jade +++ b/app/templates/client/app/account(auth)/login/login(jade).jade @@ -1,4 +1,4 @@ -div(ng-include='"components/navbar/navbar.html"') +navbar .container .row .col-sm-12 diff --git a/app/templates/client/app/account(auth)/settings/settings(html).html b/app/templates/client/app/account(auth)/settings/settings(html).html index bb5d8ded0..fe5c7f0f7 100644 --- a/app/templates/client/app/account(auth)/settings/settings(html).html +++ b/app/templates/client/app/account(auth)/settings/settings(html).html @@ -1,4 +1,4 @@ -
+
diff --git a/app/templates/client/app/account(auth)/settings/settings(jade).jade b/app/templates/client/app/account(auth)/settings/settings(jade).jade index 2dc55d402..96340b522 100644 --- a/app/templates/client/app/account(auth)/settings/settings(jade).jade +++ b/app/templates/client/app/account(auth)/settings/settings(jade).jade @@ -1,4 +1,4 @@ -div(ng-include='"components/navbar/navbar.html"') +navbar .container .row .col-sm-12 diff --git a/app/templates/client/app/account(auth)/signup/signup(html).html b/app/templates/client/app/account(auth)/signup/signup(html).html index fc55d3790..5052a02ee 100644 --- a/app/templates/client/app/account(auth)/signup/signup(html).html +++ b/app/templates/client/app/account(auth)/signup/signup(html).html @@ -1,4 +1,4 @@ -
+
diff --git a/app/templates/client/app/account(auth)/signup/signup(jade).jade b/app/templates/client/app/account(auth)/signup/signup(jade).jade index 081657a6d..cca29a28e 100644 --- a/app/templates/client/app/account(auth)/signup/signup(jade).jade +++ b/app/templates/client/app/account(auth)/signup/signup(jade).jade @@ -1,4 +1,4 @@ -div(ng-include='"components/navbar/navbar.html"') +navbar .container .row .col-sm-12 diff --git a/app/templates/client/app/admin(auth)/admin(html).html b/app/templates/client/app/admin(auth)/admin(html).html index 5c27c7af2..e20129214 100644 --- a/app/templates/client/app/admin(auth)/admin(html).html +++ b/app/templates/client/app/admin(auth)/admin(html).html @@ -1,4 +1,4 @@ -
+

The delete user and user index api routes are restricted to users with the 'admin' role.

diff --git a/app/templates/client/app/admin(auth)/admin(jade).jade b/app/templates/client/app/admin(auth)/admin(jade).jade index fd80a0bb6..bcef64773 100644 --- a/app/templates/client/app/admin(auth)/admin(jade).jade +++ b/app/templates/client/app/admin(auth)/admin(jade).jade @@ -1,4 +1,4 @@ -div(ng-include='"components/navbar/navbar.html"') +navbar .container p | The delete user and user index api routes are restricted to users with the 'admin' role. @@ -8,4 +8,4 @@ div(ng-include='"components/navbar/navbar.html"') br span.text-muted {{user.email}} a.trash(ng-click='delete(user)') - span.glyphicon.glyphicon-trash.pull-right \ No newline at end of file + span.glyphicon.glyphicon-trash.pull-right diff --git a/app/templates/client/app/main/main(html).html b/app/templates/client/app/main/main(html).html index 7d0d5c44b..9416ef0db 100644 --- a/app/templates/client/app/main/main(html).html +++ b/app/templates/client/app/main/main(html).html @@ -1,4 +1,4 @@ -
+
-
\ No newline at end of file +
diff --git a/app/templates/client/app/admin(auth)/admin(coffee).coffee b/app/templates/client/app/admin(auth)/admin(coffee).coffee index 18bb9d4ad..99b49177f 100644 --- a/app/templates/client/app/admin(auth)/admin(coffee).coffee +++ b/app/templates/client/app/admin(auth)/admin(coffee).coffee @@ -12,4 +12,4 @@ angular.module '<%= scriptAppName %>' url: '/admin' templateUrl: 'app/admin/admin.html' controller: 'AdminCtrl' -<% } %> \ No newline at end of file +<% } %> diff --git a/app/templates/client/app/admin(auth)/admin(html).html b/app/templates/client/app/admin(auth)/admin(html).html index e20129214..7688c9b47 100644 --- a/app/templates/client/app/admin(auth)/admin(html).html +++ b/app/templates/client/app/admin(auth)/admin(html).html @@ -9,4 +9,4 @@ -
\ No newline at end of file +
diff --git a/app/templates/client/app/admin(auth)/admin(less).less b/app/templates/client/app/admin(auth)/admin(less).less index ad8202750..a6f536dc5 100644 --- a/app/templates/client/app/admin(auth)/admin(less).less +++ b/app/templates/client/app/admin(auth)/admin(less).less @@ -1 +1 @@ -.trash { color:rgb(209, 91, 71); } \ No newline at end of file +.trash { color:rgb(209, 91, 71); } diff --git a/app/templates/client/app/admin(auth)/admin(stylus).styl b/app/templates/client/app/admin(auth)/admin(stylus).styl index d57e50db5..d7d50a172 100644 --- a/app/templates/client/app/admin(auth)/admin(stylus).styl +++ b/app/templates/client/app/admin(auth)/admin(stylus).styl @@ -1,2 +1,2 @@ .trash - color rgb(209, 91, 71) \ No newline at end of file + color rgb(209, 91, 71) diff --git a/app/templates/client/app/main/main(coffee).coffee b/app/templates/client/app/main/main(coffee).coffee index 5d28335d1..04cd367bb 100644 --- a/app/templates/client/app/main/main(coffee).coffee +++ b/app/templates/client/app/main/main(coffee).coffee @@ -12,4 +12,4 @@ angular.module '<%= scriptAppName %>' url: '/' templateUrl: 'app/main/main.html' controller: 'MainCtrl' -<% } %> \ No newline at end of file +<% } %> diff --git a/app/templates/client/components/modal(uibootstrap)/modal(css).css b/app/templates/client/components/modal(uibootstrap)/modal(css).css index f5cc0d9e7..ae0406856 100644 --- a/app/templates/client/components/modal(uibootstrap)/modal(css).css +++ b/app/templates/client/components/modal(uibootstrap)/modal(css).css @@ -20,4 +20,4 @@ } .modal-danger .modal-header { background: #d9534f; -} \ No newline at end of file +} diff --git a/app/templates/client/components/modal(uibootstrap)/modal(html).html b/app/templates/client/components/modal(uibootstrap)/modal(html).html index 4580254ff..f04d0db03 100644 --- a/app/templates/client/components/modal(uibootstrap)/modal(html).html +++ b/app/templates/client/components/modal(uibootstrap)/modal(html).html @@ -8,4 +8,4 @@
\ No newline at end of file + diff --git a/app/templates/client/components/mongoose-error(auth)/mongoose-error.directive(coffee).coffee b/app/templates/client/components/mongoose-error(auth)/mongoose-error.directive(coffee).coffee index d255f614d..cf0e1ccf0 100644 --- a/app/templates/client/components/mongoose-error(auth)/mongoose-error.directive(coffee).coffee +++ b/app/templates/client/components/mongoose-error(auth)/mongoose-error.directive(coffee).coffee @@ -9,4 +9,4 @@ angular.module '<%= scriptAppName %>' require: 'ngModel' link: (scope, element, attrs, ngModel) -> element.on 'keydown', -> - ngModel.$setValidity 'mongoose', true \ No newline at end of file + ngModel.$setValidity 'mongoose', true diff --git a/app/templates/client/components/mongoose-error(auth)/mongoose-error.directive(js).js b/app/templates/client/components/mongoose-error(auth)/mongoose-error.directive(js).js index 8a331009b..a71cb03cf 100644 --- a/app/templates/client/components/mongoose-error(auth)/mongoose-error.directive(js).js +++ b/app/templates/client/components/mongoose-error(auth)/mongoose-error.directive(js).js @@ -14,4 +14,4 @@ angular.module('<%= scriptAppName %>') }); } }; - }); \ No newline at end of file + }); diff --git a/app/templates/client/components/navbar/navbar(jade).jade b/app/templates/client/components/navbar/navbar(jade).jade index 5d7cb2795..e20a8fffa 100644 --- a/app/templates/client/components/navbar/navbar(jade).jade +++ b/app/templates/client/components/navbar/navbar(jade).jade @@ -31,4 +31,4 @@ div.navbar.navbar-default.navbar-static-top(ng-controller='NavbarCtrl') span.glyphicon.glyphicon-cog li(ng-show='isLoggedIn()') - a(<% if (filters.uirouter) { %>ui-sref='logout'<% } else { %>href='http://github.com/logout'<% } %>) Logout<% } %> \ No newline at end of file + a(<% if (filters.uirouter) { %>ui-sref='logout'<% } else { %>href='http://github.com/logout'<% } %>) Logout<% } %> diff --git a/app/templates/client/components/navbar/navbar.controller(coffee).coffee b/app/templates/client/components/navbar/navbar.controller(coffee).coffee index 9dda1ae4b..98eaf2213 100644 --- a/app/templates/client/components/navbar/navbar.controller(coffee).coffee +++ b/app/templates/client/components/navbar/navbar.controller(coffee).coffee @@ -12,4 +12,4 @@ angular.module '<%= scriptAppName %>' $scope.getCurrentUser = Auth.getCurrentUser<% } %><% if(!filters.uirouter) { %> $scope.isActive = (route) -> - route is $location.path()<% } %> \ No newline at end of file + route is $location.path()<% } %> diff --git a/app/templates/client/components/socket(socketio)/socket.mock(js).js b/app/templates/client/components/socket(socketio)/socket.mock(js).js index 84a2e0c36..ba09c1d35 100644 --- a/app/templates/client/components/socket(socketio)/socket.mock(js).js +++ b/app/templates/client/components/socket(socketio)/socket.mock(js).js @@ -13,4 +13,4 @@ angular.module('socketMock', []) syncUpdates: function() {}, unsyncUpdates: function() {} }; - }); \ No newline at end of file + }); diff --git a/controller/index.js b/controller/index.js index 29f65325b..6d8897d61 100644 --- a/controller/index.js +++ b/controller/index.js @@ -7,4 +7,4 @@ var Generator = yeoman.generators.Base.extend({ } }); -module.exports = Generator; \ No newline at end of file +module.exports = Generator; diff --git a/decorator/index.js b/decorator/index.js index b28be5c88..ae8193eb7 100644 --- a/decorator/index.js +++ b/decorator/index.js @@ -7,4 +7,4 @@ var Generator = yeoman.generators.Base.extend({ } }); -module.exports = Generator; \ No newline at end of file +module.exports = Generator; diff --git a/directive/index.js b/directive/index.js index 298f4240e..257a4b19a 100644 --- a/directive/index.js +++ b/directive/index.js @@ -7,4 +7,4 @@ var Generator = yeoman.generators.Base.extend({ } }); -module.exports = Generator; \ No newline at end of file +module.exports = Generator; diff --git a/factory/index.js b/factory/index.js index 584079bad..c303eb9b8 100644 --- a/factory/index.js +++ b/factory/index.js @@ -7,4 +7,4 @@ var Generator = yeoman.generators.Base.extend({ } }); -module.exports = Generator; \ No newline at end of file +module.exports = Generator; diff --git a/filter/index.js b/filter/index.js index 8aafad6f7..d1119b27d 100644 --- a/filter/index.js +++ b/filter/index.js @@ -7,4 +7,4 @@ var Generator = yeoman.generators.Base.extend({ } }); -module.exports = Generator; \ No newline at end of file +module.exports = Generator; diff --git a/generators/constant/index.js b/generators/constant/index.js index fd7b5c574..4524a8eed 100644 --- a/generators/constant/index.js +++ b/generators/constant/index.js @@ -11,4 +11,4 @@ util.inherits(Generator, yeoman.generators.Base); Generator.prototype.deprecated = function deprecated() { this.log(chalk.yellow('This sub-generator is deprecated. \n')); -}; \ No newline at end of file +}; diff --git a/generators/deploy/index.js b/generators/deploy/index.js index 6a3d5ec9c..7fb3452fa 100644 --- a/generators/deploy/index.js +++ b/generators/deploy/index.js @@ -12,4 +12,4 @@ util.inherits(Generator, yeoman.generators.NamedBase); Generator.prototype.deprecated = function deprecated() { this.log(chalk.yellow(chalk.bold('yo angular-fullstack:deploy') + ' is deprecated, instead use: \n') + chalk.green('yo angular-fullstack:heroku') + ' or ' + chalk.green('yo angular-fullstack:openshift')); -}; \ No newline at end of file +}; diff --git a/generators/readme.md b/generators/readme.md index 670a62a57..d56c72138 100644 --- a/generators/readme.md +++ b/generators/readme.md @@ -1 +1 @@ -This folder is for deprecated generators only. \ No newline at end of file +This folder is for deprecated generators only. diff --git a/generators/value/index.js b/generators/value/index.js index fd7b5c574..4524a8eed 100644 --- a/generators/value/index.js +++ b/generators/value/index.js @@ -11,4 +11,4 @@ util.inherits(Generator, yeoman.generators.Base); Generator.prototype.deprecated = function deprecated() { this.log(chalk.yellow('This sub-generator is deprecated. \n')); -}; \ No newline at end of file +}; diff --git a/generators/view/index.js b/generators/view/index.js index fd7b5c574..4524a8eed 100644 --- a/generators/view/index.js +++ b/generators/view/index.js @@ -11,4 +11,4 @@ util.inherits(Generator, yeoman.generators.Base); Generator.prototype.deprecated = function deprecated() { this.log(chalk.yellow('This sub-generator is deprecated. \n')); -}; \ No newline at end of file +}; diff --git a/openshift/USAGE b/openshift/USAGE index b3dd18759..a57763b36 100644 --- a/openshift/USAGE +++ b/openshift/USAGE @@ -5,4 +5,4 @@ Example: yo angular-fullstack:openshift This will create: - a dist folder and initialize an openshift app \ No newline at end of file + a dist folder and initialize an openshift app diff --git a/provider/index.js b/provider/index.js index ed40ef29d..5e3ac882e 100644 --- a/provider/index.js +++ b/provider/index.js @@ -7,4 +7,4 @@ var Generator = yeoman.generators.Base.extend({ } }); -module.exports = Generator; \ No newline at end of file +module.exports = Generator; diff --git a/route/index.js b/route/index.js index 2a69476c5..cc8569854 100644 --- a/route/index.js +++ b/route/index.js @@ -7,4 +7,4 @@ var Generator = yeoman.generators.Base.extend({ } }); -module.exports = Generator; \ No newline at end of file +module.exports = Generator; diff --git a/scripts/sauce_connect_setup.sh b/scripts/sauce_connect_setup.sh index 06b6e2092..4348e3662 100755 --- a/scripts/sauce_connect_setup.sh +++ b/scripts/sauce_connect_setup.sh @@ -57,4 +57,4 @@ done unset SAUCE_CONNECT_PLATFORM SAUCE_TMP_DIR SC_DIR SC_DISTRIBUTION SC_READYFILE SC_LOGFILE SC_TUNNEL_ID -popd \ No newline at end of file +popd diff --git a/service/index.js b/service/index.js index d133abdbc..9aa5f48b0 100644 --- a/service/index.js +++ b/service/index.js @@ -7,4 +7,4 @@ var Generator = yeoman.generators.Base.extend({ } }); -module.exports = Generator; \ No newline at end of file +module.exports = Generator; diff --git a/test/fixtures/.yo-rc.json b/test/fixtures/.yo-rc.json index 9ab655e54..a26821115 100644 --- a/test/fixtures/.yo-rc.json +++ b/test/fixtures/.yo-rc.json @@ -17,4 +17,4 @@ "googleAuth": true } } -} \ No newline at end of file +} diff --git a/util.js b/util.js index 7544f8c8e..4bf2170c4 100644 --- a/util.js +++ b/util.js @@ -137,4 +137,4 @@ function processDirectory (self, source, destination) { } } }); -} \ No newline at end of file +} From 00b26d6e89229197f493796b93dabe1ec802e28d Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 28 Jul 2015 17:22:17 -0400 Subject: [PATCH 0151/1357] rollback #1092 --- .../client/components/auth(auth)/auth.service(js).js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/templates/client/components/auth(auth)/auth.service(js).js b/app/templates/client/components/auth(auth)/auth.service(js).js index eb2cb1c10..9afb12da9 100644 --- a/app/templates/client/components/auth(auth)/auth.service(js).js +++ b/app/templates/client/components/auth(auth)/auth.service(js).js @@ -1,9 +1,9 @@ 'use strict'; angular.module('<%= scriptAppName %>') - .factory('Auth', function Auth($location, $rootScope, $http, User, $cookies, $q) { + .factory('Auth', function Auth($location, $rootScope, $http, User, $cookieStore, $q) { var currentUser = {}; - if($cookies.get('token')) { + if($cookieStore.get('token')) { currentUser = User.get(); } @@ -25,7 +25,7 @@ angular.module('<%= scriptAppName %>') password: user.password }). success(function(data) { - $cookies.put('token', data.token); + $cookieStore.put('token', data.token); currentUser = User.get(); deferred.resolve(data); return cb(); @@ -45,7 +45,7 @@ angular.module('<%= scriptAppName %>') * @param {Function} */ logout: function() { - $cookies.remove('token'); + $cookieStore.remove('token'); currentUser = {}; }, @@ -61,7 +61,7 @@ angular.module('<%= scriptAppName %>') return User.save(user, function(data) { - $cookies.put('token', data.token); + $cookieStore.put('token', data.token); currentUser = User.get(); return cb(user); }, @@ -140,7 +140,7 @@ angular.module('<%= scriptAppName %>') * Get auth token */ getToken: function() { - return $cookies.get('token'); + return $cookieStore.get('token'); } }; }); From e7a1a462cd825d03c3b9564c1114182fef416466 Mon Sep 17 00:00:00 2001 From: Tyson Quek Date: Wed, 22 Jul 2015 10:32:28 +0800 Subject: [PATCH 0152/1357] refactor(client:auth): use $cookies instead $cookieStore is deprecated. See https://docs.angularjs.org/api/ngCookies/service/$cookieStore --- app/templates/client/app/app(coffee).coffee | 6 +++--- app/templates/client/app/app(js).js | 8 ++++---- .../auth(auth)/auth.service(coffee).coffee | 12 ++++++------ .../client/components/auth(auth)/auth.service(js).js | 12 ++++++------ 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/app/templates/client/app/app(coffee).coffee b/app/templates/client/app/app(coffee).coffee index 25b572a75..b070abd8b 100644 --- a/app/templates/client/app/app(coffee).coffee +++ b/app/templates/client/app/app(coffee).coffee @@ -15,12 +15,12 @@ angular.module '<%= scriptAppName %>', [<%= angularModules %>] $locationProvider.html5Mode true<% if (filters.auth) { %> $httpProvider.interceptors.push 'authInterceptor'<% } %> <% } %><% if (filters.auth) { %> -.factory 'authInterceptor', ($rootScope, $q, $cookieStore<% if (filters.ngroute) { %>, $location<% } if (filters.uirouter) { %>, $injector<% } %>) -> +.factory 'authInterceptor', ($rootScope, $q, $cookies<% if (filters.ngroute) { %>, $location<% } if (filters.uirouter) { %>, $injector<% } %>) -> <% if (filters.uirouter) { %>state = null <% } %># Add authorization token to headers request: (config) -> config.headers = config.headers or {} - config.headers.Authorization = 'Bearer ' + $cookieStore.get 'token' if $cookieStore.get 'token' + config.headers.Authorization = 'Bearer ' + $cookies.get 'token' if $cookies.get 'token' config # Intercept 401s and redirect you to login @@ -28,7 +28,7 @@ angular.module '<%= scriptAppName %>', [<%= angularModules %>] if response.status is 401 <% if (filters.ngroute) { %>$location.path '/login'<% } if (filters.uirouter) { %>(state || state = $injector.get '$state').go 'login'<% } %> # remove any stale tokens - $cookieStore.remove 'token' + $cookies.remove 'token' $q.reject response diff --git a/app/templates/client/app/app(js).js b/app/templates/client/app/app(js).js index 2ee87aafe..0b636714d 100644 --- a/app/templates/client/app/app(js).js +++ b/app/templates/client/app/app(js).js @@ -17,14 +17,14 @@ angular.module('<%= scriptAppName %>', [<%= angularModules %>]) $httpProvider.interceptors.push('authInterceptor');<% } %> })<% } if (filters.auth) { %> - .factory('authInterceptor', function($rootScope, $q, $cookieStore<% if (filters.ngroute) { %>, $location<% } if (filters.uirouter) { %>, $injector<% } %>) { + .factory('authInterceptor', function($rootScope, $q, $cookies<% if (filters.ngroute) { %>, $location<% } if (filters.uirouter) { %>, $injector<% } %>) { <% if (filters.uirouter) { %>var state; <% } %>return { // Add authorization token to headers request: function(config) { config.headers = config.headers || {}; - if ($cookieStore.get('token')) { - config.headers.Authorization = 'Bearer ' + $cookieStore.get('token'); + if ($cookies.get('token')) { + config.headers.Authorization = 'Bearer ' + $cookies.get('token'); } return config; }, @@ -34,7 +34,7 @@ angular.module('<%= scriptAppName %>', [<%= angularModules %>]) if (response.status === 401) { <% if (filters.ngroute) { %>$location.path('/login');<% } if (filters.uirouter) { %>(state || (state = $injector.get('$state'))).go('login');<% } %> // remove any stale tokens - $cookieStore.remove('token'); + $cookies.remove('token'); return $q.reject(response); } else { diff --git a/app/templates/client/components/auth(auth)/auth.service(coffee).coffee b/app/templates/client/components/auth(auth)/auth.service(coffee).coffee index 1d4b29544..778c4e547 100644 --- a/app/templates/client/components/auth(auth)/auth.service(coffee).coffee +++ b/app/templates/client/components/auth(auth)/auth.service(coffee).coffee @@ -1,8 +1,8 @@ 'use strict' angular.module '<%= scriptAppName %>' -.factory 'Auth', ($http, User, $cookieStore, $q) -> - currentUser = if $cookieStore.get 'token' then User.get() else {} +.factory 'Auth', ($http, User, $cookies, $q) -> + currentUser = if $cookies.get 'token' then User.get() else {} ### Authenticate user and save token @@ -17,7 +17,7 @@ angular.module '<%= scriptAppName %>' password: user.password .then (res) -> - $cookieStore.put 'token', res.data.token + $cookies.put 'token', res.data.token currentUser = User.get() callback?() res.data @@ -32,7 +32,7 @@ angular.module '<%= scriptAppName %>' Delete access token and user info ### logout: -> - $cookieStore.remove 'token' + $cookies.remove 'token' currentUser = {} return @@ -47,7 +47,7 @@ angular.module '<%= scriptAppName %>' createUser: (user, callback) -> User.save user, (data) -> - $cookieStore.put 'token', data.token + $cookies.put 'token', data.token currentUser = User.get() callback? null, user @@ -144,4 +144,4 @@ angular.module '<%= scriptAppName %>' Get auth token ### getToken: -> - $cookieStore.get 'token' + $cookies.get 'token' diff --git a/app/templates/client/components/auth(auth)/auth.service(js).js b/app/templates/client/components/auth(auth)/auth.service(js).js index 5baf0e0b4..6b0c80e08 100644 --- a/app/templates/client/components/auth(auth)/auth.service(js).js +++ b/app/templates/client/components/auth(auth)/auth.service(js).js @@ -1,7 +1,7 @@ 'use strict'; angular.module('<%= scriptAppName %>') - .factory('Auth', function Auth($http, User, $cookieStore, $q) { + .factory('Auth', function Auth($http, User, $cookies, $q) { /** * Return a callback or noop function * @@ -14,7 +14,7 @@ angular.module('<%= scriptAppName %>') currentUser = {}; - if ($cookieStore.get('token')) { + if ($cookies.get('token')) { currentUser = User.get(); } @@ -33,7 +33,7 @@ angular.module('<%= scriptAppName %>') password: user.password }) .then(function(res) { - $cookieStore.put('token', res.data.token); + $cookies.put('token', res.data.token); currentUser = User.get(); safeCb(callback)(); return res.data; @@ -48,7 +48,7 @@ angular.module('<%= scriptAppName %>') * Delete access token and user info */ logout: function() { - $cookieStore.remove('token'); + $cookies.remove('token'); currentUser = {}; }, @@ -62,7 +62,7 @@ angular.module('<%= scriptAppName %>') createUser: function(user, callback) { return User.save(user, function(data) { - $cookieStore.put('token', data.token); + $cookies.put('token', data.token); currentUser = User.get(); return safeCb(callback)(null, user); }, @@ -160,7 +160,7 @@ angular.module('<%= scriptAppName %>') * @return {String} - a token string used for authenticating */ getToken: function() { - return $cookieStore.get('token'); + return $cookies.get('token'); } }; }); From e9d3a3e34268519f6992f285112f0edc8284dbb1 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 29 Jul 2015 16:41:55 -0400 Subject: [PATCH 0153/1357] 2.1.1 --- CHANGELOG.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ebbf89c3a..ced95fa81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ + +## v2.1.1 (2015-07-29) + + +#### Bug Fixes + +* **app:** use 0.0.0.0 for default IP ([2cd1c24d](http://github.com/DaftMonk/generator-angular-fullstack/commit/2cd1c24d2224e46fa68f8da834e86ac3ed80de8e)) + ## v2.1.0 (2015-07-15) diff --git a/package.json b/package.json index 23d469194..dbf3f3662 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "generator-angular-fullstack", - "version": "2.1.0", + "version": "2.1.1", "description": "Yeoman generator for creating MEAN stack applications, using MongoDB, Express, AngularJS, and Node", "keywords": [ "yeoman-generator", From 90ff36e8d5eebd53b2a615c4803c412812a11673 Mon Sep 17 00:00:00 2001 From: kingcody Date: Fri, 31 Jul 2015 05:10:28 -0400 Subject: [PATCH 0154/1357] fix(gen): default grunt filter This takes care of the README.md template as well as allowing other template updates related to the grunt/gulp implementation --- app/index.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/index.js b/app/index.js index 5c3ef0673..6c0a7fe3f 100644 --- a/app/index.js +++ b/app/index.js @@ -287,6 +287,11 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ return answers.testing === 'mocha'; } }], function (answers) { + /** + * Default to grunt until gulp support is implemented + */ + this.filters.grunt = true; + this.filters[answers.testing] = true; if (answers.testing === 'mocha') { this.filters.jasmine = false; From 1bfcc1fc05202b2abd05915c52ec5010ad960b5e Mon Sep 17 00:00:00 2001 From: Denis Ciccale Date: Sun, 2 Aug 2015 16:28:22 +0200 Subject: [PATCH 0155/1357] fix(app.coffee): missing preventDefault() --- app/templates/client/app/app(coffee).coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/app/templates/client/app/app(coffee).coffee b/app/templates/client/app/app(coffee).coffee index b070abd8b..bf97363b1 100644 --- a/app/templates/client/app/app(coffee).coffee +++ b/app/templates/client/app/app(coffee).coffee @@ -36,5 +36,6 @@ angular.module '<%= scriptAppName %>', [<%= angularModules %>] # Redirect to login if route requires auth and you're not logged in $rootScope.$on <% if (filters.ngroute) { %>'$routeChangeStart'<% } %><% if (filters.uirouter) { %>'$stateChangeStart'<% } %>, (event, next) -> Auth.isLoggedIn (loggedIn) -> + event.preventDefault() <% if (filters.ngroute) { %>$location.path '/login'<% } %><% if (filters.uirouter) { %>$state.go 'login'<% } %> if next.authenticate and not loggedIn <% } %> From 6bfc1da235d96a1d569c9ac7cba6d765a2a51c4b Mon Sep 17 00:00:00 2001 From: Denis Ciccale Date: Sun, 2 Aug 2015 16:29:30 +0200 Subject: [PATCH 0156/1357] chore(auth.service): changePassword does not receive success data --- .../client/components/auth(auth)/auth.service(coffee).coffee | 4 ++-- .../client/components/auth(auth)/auth.service(js).js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/templates/client/components/auth(auth)/auth.service(coffee).coffee b/app/templates/client/components/auth(auth)/auth.service(coffee).coffee index 778c4e547..d59b1040d 100644 --- a/app/templates/client/components/auth(auth)/auth.service(coffee).coffee +++ b/app/templates/client/components/auth(auth)/auth.service(coffee).coffee @@ -73,8 +73,8 @@ angular.module '<%= scriptAppName %>' oldPassword: oldPassword newPassword: newPassword - , (user) -> - callback? null, user + , () -> + callback? null , (err) -> callback? err diff --git a/app/templates/client/components/auth(auth)/auth.service(js).js b/app/templates/client/components/auth(auth)/auth.service(js).js index 6b0c80e08..d7f787a94 100644 --- a/app/templates/client/components/auth(auth)/auth.service(js).js +++ b/app/templates/client/components/auth(auth)/auth.service(js).js @@ -84,8 +84,8 @@ angular.module('<%= scriptAppName %>') return User.changePassword({ id: currentUser._id }, { oldPassword: oldPassword, newPassword: newPassword - }, function(user) { - return safeCb(callback)(null, user); + }, function() { + return safeCb(callback)(null); }, function(err) { return safeCb(callback)(err); }).$promise; From 7ecf75180fc89de2ad441adf651dcfcd95ad85ae Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 4 Aug 2015 00:05:49 -0400 Subject: [PATCH 0157/1357] chore(dependencies): update grunt-wiredep to `^2.0.0` --- app/templates/_package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 194af868e..31b5aa5d5 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -36,7 +36,7 @@ "devDependencies": { "autoprefixer-core": "^5.2.1", "grunt": "~0.4.4", - "grunt-wiredep": "~1.8.0", + "grunt-wiredep": "^2.0.0", "grunt-concurrent": "~0.5.0", "grunt-contrib-clean": "~0.5.0", "grunt-contrib-concat": "~0.4.0", From f31e9968dc1aca0b0254d411b19fdc5bd19a6b7f Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 4 Aug 2015 00:07:14 -0400 Subject: [PATCH 0158/1357] feat(app): use wiredep to inject bower deps into karma.conf.js --- app/templates/Gruntfile.js | 31 +++++++++++++++++++++++-------- app/templates/karma.conf.js | 14 +++----------- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index ce5275629..e635727f9 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -72,7 +72,7 @@ module.exports = function (grunt) { }, jsTest: { files: ['<%%= yeoman.client %>/{app,components}/**/*.{spec,mock}.js'], - tasks: ['newer:jshint:all', 'karma'] + tasks: ['newer:jshint:all', 'wiredep:test', 'karma'] },<% if (filters.stylus) { %> injectStylus: { files: ['<%%= yeoman.client %>/{app,components}/**/*.styl'], @@ -240,12 +240,26 @@ module.exports = function (grunt) { } }, - // Automatically inject Bower components into the app + // Automatically inject Bower components into the app and karma.conf.js wiredep: { - target: { + options: { + exclude: [ + /angular-scenario/, + /bootstrap-sass-official/, + /bootstrap.js/, + '/json3/', + '/es5-shim/'<% if(!filters.css) { %>, + /bootstrap.css/, + /font-awesome.css/<% } %> + ] + }, + client: { src: '<%%= yeoman.client %>/index.html', ignorePath: '<%%= yeoman.client %>/', - exclude: [/bootstrap-sass-official/, /bootstrap.js/, '/json3/', '/es5-shim/'<% if(!filters.css) { %>, /bootstrap.css/, /font-awesome.css/ <% } %>] + }, + test: { + src: './karma.conf.js', + devDependencies: true } }, @@ -773,7 +787,7 @@ module.exports = function (grunt) { 'injector:sass',<% } %> 'concurrent:server', 'injector', - 'wiredep', + 'wiredep:client', 'postcss', 'concurrent:debug' ]); @@ -787,7 +801,7 @@ module.exports = function (grunt) { 'injector:sass',<% } %> 'concurrent:server', 'injector', - 'wiredep', + 'wiredep:client', 'postcss', 'express:dev', 'wait', @@ -821,6 +835,7 @@ module.exports = function (grunt) { 'concurrent:test', 'injector', 'postcss', + 'wiredep:test', 'karma' ]); } @@ -847,7 +862,7 @@ module.exports = function (grunt) { 'injector:sass',<% } %> 'concurrent:test', 'injector', - 'wiredep', + 'wiredep:client', 'postcss', 'express:dev', 'protractor' @@ -903,7 +918,7 @@ module.exports = function (grunt) { 'injector:sass',<% } %> 'concurrent:dist', 'injector', - 'wiredep', + 'wiredep:client', 'useminPrepare', 'postcss', 'ngtemplates', diff --git a/app/templates/karma.conf.js b/app/templates/karma.conf.js index b18bc8da3..5b45e4f86 100644 --- a/app/templates/karma.conf.js +++ b/app/templates/karma.conf.js @@ -12,17 +12,9 @@ module.exports = function(config) { // list of files / patterns to load in the browser files: [ - 'client/bower_components/jquery/dist/jquery.js', - 'client/bower_components/angular/angular.js', - 'client/bower_components/angular-mocks/angular-mocks.js', - 'client/bower_components/angular-resource/angular-resource.js', - 'client/bower_components/angular-cookies/angular-cookies.js', - 'client/bower_components/angular-sanitize/angular-sanitize.js', - 'client/bower_components/angular-route/angular-route.js',<% if (filters.uibootstrap) { %> - 'client/bower_components/angular-bootstrap/ui-bootstrap-tpls.js',<% } %> - 'client/bower_components/lodash/dist/lodash.compat.js',<% if (filters.socketio) { %> - 'client/bower_components/angular-socket-io/socket.js',<% } %><% if (filters.uirouter) { %> - 'client/bower_components/angular-ui-router/release/angular-ui-router.js',<% } %> + // bower:js + // endbower<% if (filters.socketio) { %> + 'node_modules/socket.io-client/socket.io.js',<% } %> 'client/app/app.js', 'client/app/app.coffee', 'client/app/**/*.js', From e04185a7227ad018f620aa1e32d813b555d1dc76 Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 4 Aug 2015 03:45:09 -0400 Subject: [PATCH 0159/1357] fix(app): auth.login waits for user resource to resolve --- .../auth(auth)/auth.service(coffee).coffee | 11 +++++++---- .../client/components/auth(auth)/auth.service(js).js | 12 ++++++++---- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/app/templates/client/components/auth(auth)/auth.service(coffee).coffee b/app/templates/client/components/auth(auth)/auth.service(coffee).coffee index 778c4e547..3b1ab4d0c 100644 --- a/app/templates/client/components/auth(auth)/auth.service(coffee).coffee +++ b/app/templates/client/components/auth(auth)/auth.service(coffee).coffee @@ -8,7 +8,7 @@ angular.module '<%= scriptAppName %>' Authenticate user and save token @param {Object} user - login info - @param {Function} callback - optional, function(error) + @param {Function} callback - optional, function(error, user) @return {Promise} ### login: (user, callback) -> @@ -19,10 +19,13 @@ angular.module '<%= scriptAppName %>' .then (res) -> $cookies.put 'token', res.data.token currentUser = User.get() - callback?() - res.data + currentUser.$promise + + .then (user) -> + callback? null, user + user - , (err) => + .catch (err) => @logout() callback? err.data $q.reject err.data diff --git a/app/templates/client/components/auth(auth)/auth.service(js).js b/app/templates/client/components/auth(auth)/auth.service(js).js index 6b0c80e08..32a4eabf3 100644 --- a/app/templates/client/components/auth(auth)/auth.service(js).js +++ b/app/templates/client/components/auth(auth)/auth.service(js).js @@ -24,7 +24,7 @@ angular.module('<%= scriptAppName %>') * Authenticate user and save token * * @param {Object} user - login info - * @param {Function} callback - optional, function(error) + * @param {Function} callback - optional, function(error, user) * @return {Promise} */ login: function(user, callback) { @@ -35,9 +35,13 @@ angular.module('<%= scriptAppName %>') .then(function(res) { $cookies.put('token', res.data.token); currentUser = User.get(); - safeCb(callback)(); - return res.data; - }, function(err) { + return currentUser.$promise; + }) + .then(function(user) { + safeCb(callback)(null, user); + return user; + }) + .catch(function(err) { this.logout(); safeCb(callback)(err.data); return $q.reject(err.data); From 8247085844f3b73feb7db3cc785a4bc48b3b2e6c Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 5 Aug 2015 00:57:24 -0400 Subject: [PATCH 0160/1357] feat(grunt): add watch to bower.json --- app/templates/Gruntfile.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index e635727f9..361c49f1a 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -133,7 +133,11 @@ module.exports = function (grunt) { livereload: true, nospawn: true //Without this option specified express won't be reloaded } - } + }, + bower: { + files: ['bower.json'], + tasks: ['wiredep'] + }, }, // Make sure code styles are up to par and there are no obvious mistakes From 2526ca5c90edced22eac4980bef5b9b6a5f1b156 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 5 Aug 2015 13:28:26 -0400 Subject: [PATCH 0161/1357] feat(server:auth): add role to signToken add role as second parameter, and attach to jwt closes #382 --- app/templates/server/auth(auth)/auth.service.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/server/auth(auth)/auth.service.js b/app/templates/server/auth(auth)/auth.service.js index 86f781f84..faa2684cf 100644 --- a/app/templates/server/auth(auth)/auth.service.js +++ b/app/templates/server/auth(auth)/auth.service.js @@ -71,8 +71,8 @@ function hasRole(roleRequired) { /** * Returns a jwt token signed by the app secret */ -function signToken(id) { - return jwt.sign({ _id: id }, config.secrets.session, { +function signToken(id, role) { + return jwt.sign({ _id: id, role: role }, config.secrets.session, { expiresInMinutes: 60 * 5 }); } From 76325bdc24b6c0a613981a4f95830341c09bf490 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Fri, 17 Jul 2015 18:51:33 -0400 Subject: [PATCH 0162/1357] fix(gen:css): ensure scss/less/stylus files have proper relative paths --- app/templates/Gruntfile.js | 6 +++--- app/templates/client/app/app(less).less | 8 ++++---- app/templates/client/app/app(sass).scss | 8 ++++---- app/templates/client/app/app(stylus).styl | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 361c49f1a..fde0acb0a 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -689,7 +689,7 @@ module.exports = function (grunt) { options: { transform: function(filePath) { filePath = filePath.replace('/client/app/', ''); - filePath = filePath.replace('/client/components/', ''); + filePath = filePath.replace('/client/components/', '../components/'); return '@import \'' + filePath + '\';'; }, starttag: '// injector', @@ -708,7 +708,7 @@ module.exports = function (grunt) { options: { transform: function(filePath) { filePath = filePath.replace('/client/app/', ''); - filePath = filePath.replace('/client/components/', ''); + filePath = filePath.replace('/client/components/', '../components/'); return '@import \'' + filePath + '\';'; }, starttag: '// injector', @@ -727,7 +727,7 @@ module.exports = function (grunt) { options: { transform: function(filePath) { filePath = filePath.replace('/client/app/', ''); - filePath = filePath.replace('/client/components/', ''); + filePath = filePath.replace('/client/components/', '../components/'); return '@import \'' + filePath + '\';'; }, starttag: '// injector', diff --git a/app/templates/client/app/app(less).less b/app/templates/client/app/app(less).less index 460b56bdb..cbfffbe88 100644 --- a/app/templates/client/app/app(less).less +++ b/app/templates/client/app/app(less).less @@ -1,8 +1,8 @@ -<% if (filters.bootstrap) { %>@import 'http://github.com/bootstrap/less/bootstrap.less';<% } %> -@import 'http://github.com/font-awesome/less/font-awesome.less'; +<% if (filters.bootstrap) { %>@import 'http://github.com/bower_components/bootstrap/less/bootstrap.less';<% } %> +@import 'http://github.com/bower_components/font-awesome/less/font-awesome.less'; -<% if (filters.bootstrap) { %>@icon-font-path: '/bower_components/bootstrap/fonts/';<% } %> -@fa-font-path: '/bower_components/font-awesome/fonts'; +<% if (filters.bootstrap) { %>@icon-font-path: '../bower_components/bootstrap/fonts/';<% } %> +@fa-font-path: '../bower_components/font-awesome/fonts'; /** * App-wide Styles diff --git a/app/templates/client/app/app(sass).scss b/app/templates/client/app/app(sass).scss index 30befa636..889878aee 100644 --- a/app/templates/client/app/app(sass).scss +++ b/app/templates/client/app/app(sass).scss @@ -1,8 +1,8 @@ -<% if (filters.bootstrap) { %>$icon-font-path: "/bower_components/bootstrap-sass-official/vendor/assets/fonts/bootstrap/";<% } %> -$fa-font-path: "/bower_components/font-awesome/fonts"; +<% if (filters.bootstrap) { %>$icon-font-path: "../bower_components/bootstrap-sass-official/vendor/assets/fonts/bootstrap/";<% } %> +$fa-font-path: "../bower_components/font-awesome/fonts"; <% if (filters.bootstrap) { %> -@import 'http://github.com/bootstrap-sass-official/vendor/assets/stylesheets/bootstrap';<% } %> -@import 'http://github.com/font-awesome/scss/font-awesome'; +@import 'http://github.com/bower_components/bootstrap-sass-official/vendor/assets/stylesheets/bootstrap';<% } %> +@import 'http://github.com/bower_components/font-awesome/scss/font-awesome'; /** * App-wide Styles diff --git a/app/templates/client/app/app(stylus).styl b/app/templates/client/app/app(stylus).styl index 9eab53889..d25cdfc59 100644 --- a/app/templates/client/app/app(stylus).styl +++ b/app/templates/client/app/app(stylus).styl @@ -1,5 +1,5 @@ -@import "http://github.com/font-awesome/css/font-awesome.css" -<% if (filters.bootstrap) { %>@import "http://github.com/bootstrap/dist/css/bootstrap.css" +@import "http://github.com/bower_components/font-awesome/css/font-awesome.css" +<% if (filters.bootstrap) { %>@import "http://github.com/bower_components/bootstrap/dist/css/bootstrap.css" // // Bootstrap Fonts From 799e94b9a12e119cc29bc68a864aab833f4e28ba Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 5 Aug 2015 12:59:29 -0400 Subject: [PATCH 0163/1357] refactor(grunt): remove no longer needed paths remove Sass/Stylus/Less include paths --- app/templates/Gruntfile.js | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index fde0acb0a..d562f6b3b 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -612,11 +612,6 @@ module.exports = function (grunt) { stylus: { server: { options: { - paths: [ - '<%%= yeoman.client %>/bower_components', - '<%%= yeoman.client %>/app', - '<%%= yeoman.client %>/components' - ], "include css": true }, files: { @@ -629,11 +624,6 @@ module.exports = function (grunt) { sass: { server: { options: { - loadPath: [ - '<%%= yeoman.client %>/bower_components', - '<%%= yeoman.client %>/app', - '<%%= yeoman.client %>/components' - ], compass: false }, files: { @@ -644,18 +634,11 @@ module.exports = function (grunt) { // Compiles Less to CSS less: { - options: { - paths: [ - '<%%= yeoman.client %>/bower_components', - '<%%= yeoman.client %>/app', - '<%%= yeoman.client %>/components' - ] - }, server: { files: { '.tmp/app/app.css' : '<%%= yeoman.client %>/app/app.less' } - }, + } },<% } %> injector: { From 9c3e7eed5d66d5d3a136d7d72dd7f0f8a32b65d6 Mon Sep 17 00:00:00 2001 From: kingcody Date: Thu, 6 Aug 2015 02:42:18 -0400 Subject: [PATCH 0164/1357] fix(grunt): `watch.jade` only watches jade files --- app/templates/Gruntfile.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 361c49f1a..420f6dd21 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -99,10 +99,7 @@ module.exports = function (grunt) { tasks: ['less', 'postcss'] },<% } if (filters.jade) { %> jade: { - files: [ - '<%%= yeoman.client %>/{app,components}/*', - '<%%= yeoman.client %>/{app,components}/**/*.jade' - ], + files: ['<%%= yeoman.client %>/{app,components}/**/*.jade'], tasks: ['jade'] },<% } if (filters.coffee) { %> coffee: { From 1dfc856d21f94808954c0dd5cae97741a216e62f Mon Sep 17 00:00:00 2001 From: kingcody Date: Fri, 24 Jul 2015 03:17:00 -0400 Subject: [PATCH 0165/1357] chore(dependencies): update yeoman-generator to ~0.8.10 --- app/index.js | 9 +++++---- endpoint/index.js | 16 ++++++++-------- package.json | 4 ++-- test/test-file-creation.js | 30 +++++++++++++++--------------- 4 files changed, 30 insertions(+), 29 deletions(-) diff --git a/app/index.js b/app/index.js index 6c0a7fe3f..4ae1ad871 100644 --- a/app/index.js +++ b/app/index.js @@ -37,7 +37,7 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ }, info: function () { - this.log(this.yeoman); + this.log(this.welcome); this.log('Out of the box I create an AngularJS app with an Express server.\n'); }, @@ -60,14 +60,15 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ }); // NOTE: temp(?) fix for #403 - if(typeof this.filters.oauth==='undefined') { + if(typeof this.filters.oauth === 'undefined') { var strategies = Object.keys(this.filters).filter(function(key) { - return key.match(/Auth$/) && key; - }); + return key.match(/Auth$/) && this.filters[key]; + }.bind(this)); if(strategies.length) this.filters.oauth = true; } + this.config.set('filters', this.filters); this.config.forceSave(); cb(); diff --git a/endpoint/index.js b/endpoint/index.js index 8fa1f498d..22e8e8950 100644 --- a/endpoint/index.js +++ b/endpoint/index.js @@ -11,7 +11,7 @@ var Generator = module.exports = function Generator() { util.inherits(Generator, ScriptBase); -Generator.prototype.askFor = function askFor() { +Generator.prototype.prompting = function askFor() { var done = this.async(); var name = this.name; @@ -66,7 +66,13 @@ Generator.prototype.askFor = function askFor() { }.bind(this)); }; -Generator.prototype.registerEndpoint = function registerEndpoint() { +Generator.prototype.writing = function createFiles() { + var dest = this.config.get('endpointDirectory') || 'server/api/' + this.name; + this.sourceRoot(path.join(__dirname, './templates')); + ngUtil.processDirectory(this, '.', dest); +}; + +Generator.prototype.end = function registerEndpoint() { if(this.config.get('insertRoutes')) { var routeConfig = { file: this.config.get('registerRoutesFile'), @@ -110,9 +116,3 @@ Generator.prototype.registerEndpoint = function registerEndpoint() { } } }; - -Generator.prototype.createFiles = function createFiles() { - var dest = this.config.get('endpointDirectory') || 'server/api/' + this.name; - this.sourceRoot(path.join(__dirname, './templates')); - ngUtil.processDirectory(this, '.', dest); -}; diff --git a/package.json b/package.json index f66b72cb0..c1a50c792 100644 --- a/package.json +++ b/package.json @@ -26,9 +26,9 @@ "test": "grunt test" }, "dependencies": { - "yeoman-generator": "~0.17.0", "chalk": "~0.4.0", - "generator-ng-component": "~0.0.4" + "generator-ng-component": "~0.0.4", + "yeoman-generator": "~0.18.10" }, "devDependencies": { "chai": "^1.9.1", diff --git a/test/test-file-creation.js b/test/test-file-creation.js index bec4ab17d..ce8635c0b 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -26,13 +26,13 @@ describe('angular-fullstack generator', function () { }, dependenciesInstalled = false; function generatorTest(generatorType, name, mockPrompt, callback) { - gen.run({}, function () { + gen.run(function () { var afGenerator; var deps = [path.join('../..', generatorType)]; afGenerator = helpers.createGenerator('angular-fullstack:' + generatorType, deps, [name]); helpers.mockPrompt(afGenerator, mockPrompt); - afGenerator.run([], function () { + afGenerator.run(function () { callback(); }); }); @@ -107,7 +107,7 @@ describe('angular-fullstack generator', function () { if (endpoint) { generatorTest('endpoint', endpoint, {}, execFn); } else { - gen.run({}, execFn); + gen.run(execFn); } } @@ -430,7 +430,7 @@ describe('angular-fullstack generator', function () { helpers.mockPrompt(gen, { skipConfig: true }); - gen.run({}, function () { + gen.run(function () { helpers.assertFile([ 'client/app/main/main.less', 'client/app/main/main.coffee', @@ -454,7 +454,7 @@ describe('angular-fullstack generator', function () { helpers.mockPrompt(gen, { skipConfig: true }); - gen.run({}, function () { + gen.run(function () { var yoConfig = require(__dirname + '/temp/.yo-rc.json'); expect(yoConfig['generator-angular-fullstack'].filters.oauth).to.be.true; done(); @@ -462,14 +462,14 @@ describe('angular-fullstack generator', function () { }); it('should generate expected files', function (done) { - gen.run({}, function () { + gen.run(function () { helpers.assertFile(genFiles(defaultOptions)); done(); }); }); it('should not generate unexpected files', function (done) { - gen.run({}, function () { + gen.run(function () { assertOnlyFiles(genFiles(defaultOptions), done); }); }); @@ -533,14 +533,14 @@ describe('angular-fullstack generator', function () { }); it('should generate expected files', function (done) { - gen.run({}, function () { + gen.run(function () { helpers.assertFile(genFiles(testOptions)); done(); }); }); it('should not generate unexpected files', function (done) { - gen.run({}, function () { + gen.run(function () { assertOnlyFiles(genFiles(testOptions), done); }); }); @@ -605,14 +605,14 @@ describe('angular-fullstack generator', function () { }); it('should generate expected files', function (done) { - gen.run({}, function () { + gen.run(function () { helpers.assertFile(genFiles(testOptions)); done(); }); }); it('should not generate unexpected files', function (done) { - gen.run({}, function () { + gen.run(function () { assertOnlyFiles(genFiles(testOptions), done); }); }); @@ -679,14 +679,14 @@ describe('angular-fullstack generator', function () { }); it('should generate expected files', function (done) { - gen.run({}, function () { + gen.run(function () { helpers.assertFile(genFiles(testOptions)); done(); }); }); it('should not generate unexpected files', function (done) { - gen.run({}, function () { + gen.run(function () { assertOnlyFiles(genFiles(testOptions), done); }); }); @@ -740,14 +740,14 @@ describe('angular-fullstack generator', function () { }); it('should generate expected files', function (done) { - gen.run({}, function () { + gen.run(function () { helpers.assertFile(genFiles(testOptions)); done(); }); }); it('should not generate unexpected files', function (done) { - gen.run({}, function () { + gen.run(function () { assertOnlyFiles(genFiles(testOptions), done); }); }); From 533bbd7991e4066e724f7c4807020eeef2739384 Mon Sep 17 00:00:00 2001 From: kingcody Date: Thu, 6 Aug 2015 02:58:35 -0400 Subject: [PATCH 0166/1357] chore(dependencies): update generator-ng-component to ~0.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c1a50c792..a062a68a9 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ }, "dependencies": { "chalk": "~0.4.0", - "generator-ng-component": "~0.0.4", + "generator-ng-component": "~0.1.0", "yeoman-generator": "~0.18.10" }, "devDependencies": { From d7fc0a80abda86c0cdca0de9e7748bb81e1b92ff Mon Sep 17 00:00:00 2001 From: Denis Ciccale Date: Fri, 7 Aug 2015 10:16:42 +0200 Subject: [PATCH 0167/1357] chore(user): change status code 204 for empty response body --- app/templates/server/api/user(auth)/user.controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/server/api/user(auth)/user.controller.js b/app/templates/server/api/user(auth)/user.controller.js index d074c666b..f1c2498fb 100644 --- a/app/templates/server/api/user(auth)/user.controller.js +++ b/app/templates/server/api/user(auth)/user.controller.js @@ -128,7 +128,7 @@ exports.changePassword = function(req, res, next) { <% if (filters.mongooseModels) { %>return user.saveAsync()<% } if (filters.sequelizeModels) { %>return user.save()<% } %> .then(function() { - res.status(200).end(); + res.status(204).end(); }) .catch(validationError(res)); } else { From 63782b360e3c7f12bce073de0a4bfe8817e03dbb Mon Sep 17 00:00:00 2001 From: Dan Rocha Date: Sat, 8 Aug 2015 00:52:31 -0500 Subject: [PATCH 0168/1357] feat(package): upgrade jshint packages --- app/templates/_package.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 31b5aa5d5..c9b1533be 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -44,7 +44,7 @@ "grunt-contrib-cssmin": "~0.9.0", "grunt-contrib-htmlmin": "~0.2.0", "grunt-contrib-imagemin": "~0.7.1", - "grunt-contrib-jshint": "~0.10.0", + "grunt-contrib-jshint": "~0.11.2", "grunt-contrib-uglify": "~0.4.0", "grunt-contrib-watch": "~0.6.1",<% if (filters.coffee) { %> "grunt-contrib-coffee": "^0.10.1",<% } %><% if (filters.jade) { %> @@ -76,7 +76,7 @@ "grunt-postcss": "^0.5.5", "grunt-open": "~0.2.3", "open": "~0.0.4", - "jshint-stylish": "~0.1.5", + "jshint-stylish": "~2.0.1", "connect-livereload": "^0.5.3", "mocha": "^2.2.5", "grunt-mocha-test": "~0.12.7", diff --git a/package.json b/package.json index f66b72cb0..e576c2ca9 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "grunt": "~0.4.1", "grunt-build-control": "DaftMonk/grunt-build-control", "grunt-contrib-clean": "^0.6.0", - "grunt-contrib-jshint": "^0.10.0", + "grunt-contrib-jshint": "^0.11.2", "grunt-conventional-changelog": "~1.0.0", "grunt-env": "^0.4.1", "grunt-mocha-test": "^0.11.0", From ea2a7331cfdb3fd7d0c0ee0f8f6a7ba021dd7647 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 11 Aug 2015 10:56:00 -0400 Subject: [PATCH 0169/1357] fix(server:errors): fix res.render syntax --- app/templates/server/components/errors/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/server/components/errors/index.js b/app/templates/server/components/errors/index.js index 52dba3749..ba71c73ba 100644 --- a/app/templates/server/components/errors/index.js +++ b/app/templates/server/components/errors/index.js @@ -12,11 +12,11 @@ module.exports[404] = function pageNotFound(req, res) { }; res.status(result.status); - res.render(viewFilePath, function(err) { + res.render(viewFilePath, {}, function(err, html) { if (err) { return res.json(result, result.status); } - res.render(viewFilePath); + res.send(html); }); }; From 2617ab28a772af21cbb21597cb36bb47a7ea6a00 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 11 Aug 2015 11:08:32 -0400 Subject: [PATCH 0170/1357] feat(client:main): use times symbol instead of 'x' in jade template --- app/templates/client/app/main/main(jade).jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/client/app/main/main(jade).jade b/app/templates/client/app/main/main(jade).jade index e791e96ab..3277e7b05 100644 --- a/app/templates/client/app/main/main(jade).jade +++ b/app/templates/client/app/main/main(jade).jade @@ -14,7 +14,7 @@ header#banner.hero-unit li a(href='#', tooltip='{{thing.info}}') | {{thing.name}}<% if (filters.socketio) { %> - button.close(type='button', ng-click='deleteThing(thing)') ×<% } %><% if (filters.socketio) { %> + button.close(type='button', ng-click='deleteThing(thing)') ×<% } %><% if (filters.socketio) { %> form.thing-form label Syncs in realtime across clients From bb394eeff9deb119b40b1c75cabd4c15d8931506 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 11 Aug 2015 16:12:29 -0400 Subject: [PATCH 0171/1357] feat(gen): move babel choice to script list --- app/index.js | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/app/index.js b/app/index.js index 4ae1ad871..e25388d7b 100644 --- a/app/index.js +++ b/app/index.js @@ -92,21 +92,13 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ type: 'list', name: 'script', message: 'What would you like to write scripts with?', - choices: [ 'JavaScript', 'CoffeeScript'], + choices: [ 'JavaScript', 'JavaScript + Babel', 'CoffeeScript'], filter: function( val ) { - var filterMap = { + return { 'JavaScript': 'js', + 'JavaScript + Babel': 'babel', 'CoffeeScript': 'coffee' - }; - - return filterMap[val]; - } - }, { - type: 'confirm', - name: 'babel', - message: 'Would you like to use Javascript ES6 in your client by preprocessing it with Babel?', - when: function (answers) { - return answers.script === 'js'; + }[val]; } }, { type: 'list', @@ -141,8 +133,8 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ } }], function (answers) { - this.filters.babel = !!answers.babel; - if(this.filters.babel){ this.filters.js = true; } + // also set 'js' to true if using babel + if(answers.script === 'babel') { this.filters.js = true; } this.filters[answers.script] = true; this.filters[answers.markup] = true; this.filters[answers.stylesheet] = true; From fb915b29d07044b09f5014b317b2303b94f47252 Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 28 Jul 2015 17:59:38 -0400 Subject: [PATCH 0172/1357] fix(gen): `endpointDirectory` is now a full option/config --- app/index.js | 1 + endpoint/index.js | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/app/index.js b/app/index.js index 4ae1ad871..f31a71fa7 100644 --- a/app/index.js +++ b/app/index.js @@ -316,6 +316,7 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ saveSettings: function() { if(this.skipConfig) return; + this.config.set('endpointDirectory', 'server/api/'); this.config.set('insertRoutes', true); this.config.set('registerRoutesFile', 'server/routes.js'); this.config.set('routesNeedle', '// Insert routes below'); diff --git a/endpoint/index.js b/endpoint/index.js index 22e8e8950..01d4486df 100644 --- a/endpoint/index.js +++ b/endpoint/index.js @@ -7,6 +7,11 @@ var ScriptBase = require('../script-base.js'); var Generator = module.exports = function Generator() { ScriptBase.apply(this, arguments); + + this.option('endpointDirectory', { + desc: 'Parent directory for enpoints', + type: String + }); }; util.inherits(Generator, ScriptBase); @@ -66,10 +71,14 @@ Generator.prototype.prompting = function askFor() { }.bind(this)); }; +Generator.prototype.configuring = function config() { + this.routeDest = path.join(this.options.endpointDirectory || + this.config.get('endpointDirectory') || 'server/api/', this.name); +}; + Generator.prototype.writing = function createFiles() { - var dest = this.config.get('endpointDirectory') || 'server/api/' + this.name; this.sourceRoot(path.join(__dirname, './templates')); - ngUtil.processDirectory(this, '.', dest); + ngUtil.processDirectory(this, '.', this.routeDest); }; Generator.prototype.end = function registerEndpoint() { From 3fcd8e909c29ee4903a083ef6bce83b9fa1b93dc Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 28 Jul 2015 18:03:53 -0400 Subject: [PATCH 0173/1357] feat(gen): add `relativeRequire` and other template helpers --- script-base.js | 15 +++++++++++++-- util.js | 25 ++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/script-base.js b/script-base.js index 5d6c7dd2e..d88cd988c 100644 --- a/script-base.js +++ b/script-base.js @@ -15,8 +15,13 @@ var Generator = module.exports = function Generator() { this.appname = this._.slugify(this._.humanize(this.appname)); this.scriptAppName = this._.camelize(this.appname) + angularUtils.appName(this); - this.cameledName = this._.camelize(this.name); - this.classedName = this._.classify(this.name); + var name = this.name.replace(/\//g, '-'); + + this.cameledName = this._.camelize(name); + this.classedName = this._.classify(name); + + this.basename = path.basename(this.name); + this.dirname = (this.name.indexOf('/') >= 0) ? path.dirname(this.name) : this.name; // dynamic assertion statement this.does = this.is = function(foo) { @@ -27,6 +32,12 @@ var Generator = module.exports = function Generator() { } }.bind(this); + // dynamic relative require path + this.relativeRequire = function(to, fr) { + fr = fr || this.filePath; + return angularUtils.relativeRequire(this, to, fr); + }.bind(this); + this.filters = this.config.get('filters'); this.sourceRoot(path.join(__dirname, '/templates')); }; diff --git a/util.js b/util.js index 4bf2170c4..6657cfc9f 100644 --- a/util.js +++ b/util.js @@ -6,7 +6,8 @@ module.exports = { rewrite: rewrite, rewriteFile: rewriteFile, appName: appName, - processDirectory: processDirectory + processDirectory: processDirectory, + relativeRequire: relativeRequire }; function rewriteFile (args) { @@ -74,6 +75,23 @@ function appName (self) { return suffix ? self._.classify(suffix) : ''; } +function destinationPath (self, filepath) { + filepath = path.normalize(filepath); + if (!path.isAbsolute(filepath)) { + filepath = path.join(self.destinationRoot(), filepath); + } + + return filepath; +} + +function relativeRequire (self, to, fr) { + fr = destinationPath(self, fr); + to = destinationPath(self, to); + return path.relative(path.dirname(fr), to) + .replace(/^(?!\.\.)(.*)/, './$1') + .replace(/[\/\\]index\.js$/, ''); +} + function filterFile (template) { // Find matches for parans var filterMatches = template.match(/\(([^)]+)\)/g); @@ -109,6 +127,9 @@ function processDirectory (self, source, destination) { files.forEach(function(f) { var filteredFile = filterFile(f); + if(self.basename) { + filteredFile.name = filteredFile.name.replace('basename', self.basename); + } if(self.name) { filteredFile.name = filteredFile.name.replace('name', self.name); } @@ -133,7 +154,9 @@ function processDirectory (self, source, destination) { if(copy) { self.copy(src, dest); } else { + self.filePath = dest; self.template(src, dest); + delete self.filePath; } } }); From 5227ef033fa80f51c7a764c99d99780d4bad958a Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 28 Jul 2015 18:16:15 -0400 Subject: [PATCH 0174/1357] fix(gen): endpoint accepts path as name --- app/index.js | 18 ++- endpoint/index.js | 119 +++++++++++------- ...e.controller.js => basename.controller.js} | 14 +-- ...(models).js => basename.events(models).js} | 4 +- ...integration.js => basename.integration.js} | 20 +-- ...).js => basename.model(mongooseModels).js} | 0 ....js => basename.model(sequelizeModels).js} | 0 ...ketio).js => basename.socket(socketio).js} | 4 +- endpoint/templates/index.js | 2 +- endpoint/templates/index.spec.js | 36 +++--- 10 files changed, 124 insertions(+), 93 deletions(-) rename endpoint/templates/{name.controller.js => basename.controller.js} (89%) rename endpoint/templates/{name.events(models).js => basename.events(models).js} (84%) rename endpoint/templates/{name.integration.js => basename.integration.js} (84%) rename endpoint/templates/{name.model(mongooseModels).js => basename.model(mongooseModels).js} (100%) rename endpoint/templates/{name.model(sequelizeModels).js => basename.model(sequelizeModels).js} (100%) rename endpoint/templates/{name.socket(socketio).js => basename.socket(socketio).js} (82%) diff --git a/app/index.js b/app/index.js index f31a71fa7..99f1e3995 100644 --- a/app/index.js +++ b/app/index.js @@ -400,11 +400,19 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ }, generateEndpoint: function() { - var name = this.name = this.cameledName = 'thing'; - this.classedName = name.charAt(0).toUpperCase() + name.slice(1); - this.route = '/api/' + name + 's'; - this.sourceRoot(path.join(__dirname, '..', 'endpoint', 'templates')); - genUtils.processDirectory(this, '.', 'server/api/' + name); + var models; + if (this.filters.mongooseModels) { + models = 'mongoose'; + } else if (this.filters.sequelizeModels) { + models = 'sequelize'; + } + this.composeWith('angular-fullstack:endpoint', { + options: { + route: '/api/things', + models: models + }, + args: ['thing'] + }); } }, diff --git a/endpoint/index.js b/endpoint/index.js index 01d4486df..cbb8d5aeb 100644 --- a/endpoint/index.js +++ b/endpoint/index.js @@ -8,6 +8,16 @@ var ScriptBase = require('../script-base.js'); var Generator = module.exports = function Generator() { ScriptBase.apply(this, arguments); + this.option('route', { + desc: 'URL for the endpoint', + type: String + }); + + this.option('models', { + desc: 'Specify which model(s) to use', + type: String + }); + this.option('endpointDirectory', { desc: 'Parent directory for enpoints', type: String @@ -18,6 +28,38 @@ util.inherits(Generator, ScriptBase); Generator.prototype.prompting = function askFor() { var done = this.async(); + var promptCb = function (props) { + if(props.route.charAt(0) !== '/') { + props.route = '/' + props.route; + } + + this.route = props.route; + + if (props.models) { + delete this.filters.mongoose; + delete this.filters.mongooseModels; + delete this.filters.sequelize; + delete this.filters.sequelizeModels; + + this.filters[props.models] = true; + this.filters[props.models + 'Models'] = true; + } + done(); + }.bind(this); + + if (this.options.route) { + if (this.filters.mongoose && this.filters.sequelize) { + if (this.options.models) { + return promptCb(this.options); + } + } else { + if (this.filters.mongooseModels) { this.options.models = 'mongoose'; } + else if (this.filters.sequelizeModels) { this.options.models = 'sequelize'; } + else { delete this.options.models; } + return promptCb(this.options); + } + } + var name = this.name; var base = this.config.get('routesBase') || '/api/'; @@ -51,24 +93,7 @@ Generator.prototype.prompting = function askFor() { } ]; - this.prompt(prompts, function (props) { - if(props.route.charAt(0) !== '/') { - props.route = '/' + props.route; - } - - this.route = props.route; - - if (props.models) { - delete this.filters.mongoose; - delete this.filters.mongooseModels; - delete this.filters.sequelize; - delete this.filters.sequelizeModels; - - this.filters[props.models] = true; - this.filters[props.models + 'Models'] = true; - } - done(); - }.bind(this)); + this.prompt(prompts, promptCb); }; Generator.prototype.configuring = function config() { @@ -83,45 +108,43 @@ Generator.prototype.writing = function createFiles() { Generator.prototype.end = function registerEndpoint() { if(this.config.get('insertRoutes')) { + var routesFile = this.config.get('registerRoutesFile'); + var reqPath = this.relativeRequire(this.routeDest, routesFile); var routeConfig = { - file: this.config.get('registerRoutesFile'), + file: routesFile, needle: this.config.get('routesNeedle'), splicable: [ - "app.use(\'" + this.route +"\', require(\'./api/" + this.name + "\'));" + "app.use(\'" + this.route +"\', require(\'" + reqPath + "\'));" ] }; ngUtil.rewriteFile(routeConfig); } - if (this.filters.socketio) { - if(this.config.get('insertSockets')) { - var socketConfig = { - file: this.config.get('registerSocketsFile'), - needle: this.config.get('socketsNeedle'), - splicable: [ - "require(\'../api/" + this.name + '/' + this.name + ".socket\').register(socket);" - ] - }; - ngUtil.rewriteFile(socketConfig); - } + if (this.filters.socketio && this.config.get('insertSockets')) { + var socketsFile = this.config.get('registerSocketsFile'); + var reqPath = this.relativeRequire(this.routeDest + '/' + this.basename + + '.socket', socketsFile); + var socketConfig = { + file: socketsFile, + needle: this.config.get('socketsNeedle'), + splicable: [ + "require(\'" + reqPath + "\').register(socket);" + ] + }; + ngUtil.rewriteFile(socketConfig); } - if (this.filters.sequelize) { - if (this.config.get('insertModels')) { - var modelConfig = { - file: this.config.get('registerModelsFile'), - needle: this.config.get('modelsNeedle'), - splicable: [ - "db." + this.classedName + " = db.sequelize.import(path.join(\n" + - " config.root,\n" + - " 'server',\n" + - " 'api',\n" + - " '" + this.name + "',\n" + - " '" + this.name + ".model'\n" + - "));" - ] - }; - ngUtil.rewriteFile(modelConfig); - } + if (this.filters.sequelize && this.config.get('insertModels')) { + var modelsFile = this.config.get('registerModelsFile'); + var reqPath = this.relativeRequire(this.routeDest + '/' + this.basename + + '.model', modelsFile); + var modelConfig = { + file: modelsFile, + needle: this.config.get('modelsNeedle'), + splicable: [ + "db." + this.classedName + " = db.sequelize.import(\'" + reqPath +"\');" + ] + }; + ngUtil.rewriteFile(modelConfig); } }; diff --git a/endpoint/templates/name.controller.js b/endpoint/templates/basename.controller.js similarity index 89% rename from endpoint/templates/name.controller.js rename to endpoint/templates/basename.controller.js index abcc5f34b..cd151b13a 100644 --- a/endpoint/templates/name.controller.js +++ b/endpoint/templates/basename.controller.js @@ -10,8 +10,8 @@ 'use strict';<% if (filters.models) { %> var _ = require('lodash');<% if (filters.mongooseModels) { %> -var <%= classedName %> = require('./<%= name %>.model');<% } if (filters.sequelizeModels) { %> -var sqldb = require('../../sqldb'); +var <%= classedName %> = require('./<%= basename %>.model');<% } if (filters.sequelizeModels) { %> +var sqldb = require('<%= relativeRequire(config.get('registerModelsFile')) %>'); var <%= classedName %> = sqldb.<%= classedName %>;<% } %> function handleError(res, statusCode) { @@ -64,7 +64,7 @@ function removeEntity(res) { }; }<% } %> -// Gets a list of <%= name %>s +// Gets a list of <%= classedName %>s exports.index = function(req, res) {<% if (!filters.models) { %> res.json([]);<% } else { %> <% if (filters.mongooseModels) { %><%= classedName %>.findAsync()<% } @@ -73,7 +73,7 @@ exports.index = function(req, res) {<% if (!filters.models) { %> .catch(handleError(res));<% } %> };<% if (filters.models) { %> -// Gets a single <%= name %> from the DB +// Gets a single <%= classedName %> from the DB exports.show = function(req, res) { <% if (filters.mongooseModels) { %><%= classedName %>.findByIdAsync(req.params.id)<% } if (filters.sequelizeModels) { %><%= classedName %>.find({ @@ -86,7 +86,7 @@ exports.show = function(req, res) { .catch(handleError(res)); }; -// Creates a new <%= name %> in the DB +// Creates a new <%= classedName %> in the DB exports.create = function(req, res) { <% if (filters.mongooseModels) { %><%= classedName %>.createAsync(req.body)<% } if (filters.sequelizeModels) { %><%= classedName %>.create(req.body)<% } %> @@ -94,7 +94,7 @@ exports.create = function(req, res) { .catch(handleError(res)); }; -// Updates an existing <%= name %> in the DB +// Updates an existing <%= classedName %> in the DB exports.update = function(req, res) { if (req.body._id) { delete req.body._id; @@ -111,7 +111,7 @@ exports.update = function(req, res) { .catch(handleError(res)); }; -// Deletes a <%= name %> from the DB +// Deletes a <%= classedName %> from the DB exports.destroy = function(req, res) { <% if (filters.mongooseModels) { %><%= classedName %>.findByIdAsync(req.params.id)<% } if (filters.sequelizeModels) { %><%= classedName %>.find({ diff --git a/endpoint/templates/name.events(models).js b/endpoint/templates/basename.events(models).js similarity index 84% rename from endpoint/templates/name.events(models).js rename to endpoint/templates/basename.events(models).js index 8bda5cf9a..f39b5b0be 100644 --- a/endpoint/templates/name.events(models).js +++ b/endpoint/templates/basename.events(models).js @@ -5,8 +5,8 @@ 'use strict'; var EventEmitter = require('events').EventEmitter;<% if (filters.mongooseModels) { %> -var <%= classedName %> = require('./<%= name %>.model');<% } if (filters.sequelizeModels) { %> -var <%= classedName %> = require('../../sqldb').<%= classedName %>;<% } %> +var <%= classedName %> = require('./<%= basename %>.model');<% } if (filters.sequelizeModels) { %> +var <%= classedName %> = require('<%= relativeRequire(config.get('registerModelsFile')) %>').<%= classedName %>;<% } %> var <%= classedName %>Events = new EventEmitter(); // Set max event listeners (0 == unlimited) diff --git a/endpoint/templates/name.integration.js b/endpoint/templates/basename.integration.js similarity index 84% rename from endpoint/templates/name.integration.js rename to endpoint/templates/basename.integration.js index 160cdedfa..bcd3fd407 100644 --- a/endpoint/templates/name.integration.js +++ b/endpoint/templates/basename.integration.js @@ -1,6 +1,6 @@ 'use strict'; -var app = require('../../app'); +var app = require('<%= relativeRequire('server/app') %>'); var request = require('supertest');<% if(filters.models) { %> var new<%= classedName %>;<% } %> @@ -36,7 +36,7 @@ describe('<%= classedName %> API:', function() { .post('<%= route %>') .send({ name: 'New <%= classedName %>', - info: 'This is the brand new <%= name %>!!!' + info: 'This is the brand new <%= cameledName %>!!!' }) .expect(201) .expect('Content-Type', /json/) @@ -49,9 +49,9 @@ describe('<%= classedName %> API:', function() { }); }); - it('should respond with the newly created <%= name %>', function() { + it('should respond with the newly created <%= cameledName %>', function() { new<%= classedName %>.name.should.equal('New <%= classedName %>'); - new<%= classedName %>.info.should.equal('This is the brand new <%= name %>!!!'); + new<%= classedName %>.info.should.equal('This is the brand new <%= cameledName %>!!!'); }); }); @@ -77,9 +77,9 @@ describe('<%= classedName %> API:', function() { <%= cameledName %> = {}; }); - it('should respond with the requested <%= name %>', function() { + it('should respond with the requested <%= cameledName %>', function() { <%= cameledName %>.name.should.equal('New <%= classedName %>'); - <%= cameledName %>.info.should.equal('This is the brand new <%= name %>!!!'); + <%= cameledName %>.info.should.equal('This is the brand new <%= cameledName %>!!!'); }); }); @@ -92,7 +92,7 @@ describe('<%= classedName %> API:', function() { .put('<%= route %>/' + new<%= classedName %>._id) .send({ name: 'Updated <%= classedName %>', - info: 'This is the updated <%= name %>!!!' + info: 'This is the updated <%= cameledName %>!!!' }) .expect(200) .expect('Content-Type', /json/) @@ -109,9 +109,9 @@ describe('<%= classedName %> API:', function() { updated<%= classedName %> = {}; }); - it('should respond with the updated <%= name %>', function() { + it('should respond with the updated <%= cameledName %>', function() { updated<%= classedName %>.name.should.equal('Updated <%= classedName %>'); - updated<%= classedName %>.info.should.equal('This is the updated <%= name %>!!!'); + updated<%= classedName %>.info.should.equal('This is the updated <%= cameledName %>!!!'); }); }); @@ -130,7 +130,7 @@ describe('<%= classedName %> API:', function() { }); }); - it('should respond with 404 when <%= name %> does not exist', function(done) { + it('should respond with 404 when <%= cameledName %> does not exist', function(done) { request(app) .delete('<%= route %>/' + new<%= classedName %>._id) .expect(404) diff --git a/endpoint/templates/name.model(mongooseModels).js b/endpoint/templates/basename.model(mongooseModels).js similarity index 100% rename from endpoint/templates/name.model(mongooseModels).js rename to endpoint/templates/basename.model(mongooseModels).js diff --git a/endpoint/templates/name.model(sequelizeModels).js b/endpoint/templates/basename.model(sequelizeModels).js similarity index 100% rename from endpoint/templates/name.model(sequelizeModels).js rename to endpoint/templates/basename.model(sequelizeModels).js diff --git a/endpoint/templates/name.socket(socketio).js b/endpoint/templates/basename.socket(socketio).js similarity index 82% rename from endpoint/templates/name.socket(socketio).js rename to endpoint/templates/basename.socket(socketio).js index 24d744d13..037f6113a 100644 --- a/endpoint/templates/name.socket(socketio).js +++ b/endpoint/templates/basename.socket(socketio).js @@ -4,7 +4,7 @@ 'use strict'; -var <%= classedName %>Events = require('./<%= name %>.events'); +var <%= classedName %>Events = require('./<%= basename %>.events'); // Model events to emit var events = ['save', 'remove']; @@ -13,7 +13,7 @@ exports.register = function(socket) { // Bind model events to socket events for (var i = 0, eventsLength = events.length; i < eventsLength; i++) { var event = events[i]; - var listener = createListener('<%= name %>:' + event, socket); + var listener = createListener('<%= cameledName %>:' + event, socket); <%= classedName %>Events.on(event, listener); socket.on('disconnect', removeListener(event, listener)); diff --git a/endpoint/templates/index.js b/endpoint/templates/index.js index 60198d142..26dc430dd 100644 --- a/endpoint/templates/index.js +++ b/endpoint/templates/index.js @@ -1,7 +1,7 @@ 'use strict'; var express = require('express'); -var controller = require('./<%= name %>.controller'); +var controller = require('./<%= basename %>.controller'); var router = express.Router(); diff --git a/endpoint/templates/index.spec.js b/endpoint/templates/index.spec.js index 291a04662..4bd178948 100644 --- a/endpoint/templates/index.spec.js +++ b/endpoint/templates/index.spec.js @@ -3,11 +3,11 @@ var proxyquire = require('proxyquire').noPreserveCache(); var <%= cameledName %>CtrlStub = { - index: '<%= name %>Ctrl.index'<% if(filters.models) { %>, - show: '<%= name %>Ctrl.show', - create: '<%= name %>Ctrl.create', - update: '<%= name %>Ctrl.update', - destroy: '<%= name %>Ctrl.destroy'<% } %> + index: '<%= cameledName %>Ctrl.index'<% if(filters.models) { %>, + show: '<%= cameledName %>Ctrl.show', + create: '<%= cameledName %>Ctrl.create', + update: '<%= cameledName %>Ctrl.update', + destroy: '<%= cameledName %>Ctrl.destroy'<% } %> }; var routerStub = { @@ -25,7 +25,7 @@ var <%= cameledName %>Index = proxyquire('./index.js', { return routerStub; } }, - './<%= name %>.controller': <%= cameledName %>CtrlStub + './<%= basename %>.controller': <%= cameledName %>CtrlStub }); describe('<%= classedName %> API Router:', function() { @@ -36,9 +36,9 @@ describe('<%= classedName %> API Router:', function() { describe('GET <%= route %>', function() { - it('should route to <%= name %>.controller.index', function() { + it('should route to <%= cameledName %>.controller.index', function() { routerStub.get - .withArgs('/', '<%= name %>Ctrl.index') + .withArgs('/', '<%= cameledName %>Ctrl.index') .should.have.been.calledOnce; }); @@ -46,9 +46,9 @@ describe('<%= classedName %> API Router:', function() { describe('GET <%= route %>/:id', function() { - it('should route to <%= name %>.controller.show', function() { + it('should route to <%= cameledName %>.controller.show', function() { routerStub.get - .withArgs('/:id', '<%= name %>Ctrl.show') + .withArgs('/:id', '<%= cameledName %>Ctrl.show') .should.have.been.calledOnce; }); @@ -56,9 +56,9 @@ describe('<%= classedName %> API Router:', function() { describe('POST <%= route %>', function() { - it('should route to <%= name %>.controller.create', function() { + it('should route to <%= cameledName %>.controller.create', function() { routerStub.post - .withArgs('/', '<%= name %>Ctrl.create') + .withArgs('/', '<%= cameledName %>Ctrl.create') .should.have.been.calledOnce; }); @@ -66,9 +66,9 @@ describe('<%= classedName %> API Router:', function() { describe('PUT <%= route %>/:id', function() { - it('should route to <%= name %>.controller.update', function() { + it('should route to <%= cameledName %>.controller.update', function() { routerStub.put - .withArgs('/:id', '<%= name %>Ctrl.update') + .withArgs('/:id', '<%= cameledName %>Ctrl.update') .should.have.been.calledOnce; }); @@ -76,9 +76,9 @@ describe('<%= classedName %> API Router:', function() { describe('PATCH <%= route %>/:id', function() { - it('should route to <%= name %>.controller.update', function() { + it('should route to <%= cameledName %>.controller.update', function() { routerStub.patch - .withArgs('/:id', '<%= name %>Ctrl.update') + .withArgs('/:id', '<%= cameledName %>Ctrl.update') .should.have.been.calledOnce; }); @@ -86,9 +86,9 @@ describe('<%= classedName %> API Router:', function() { describe('DELETE <%= route %>/:id', function() { - it('should route to <%= name %>.controller.destroy', function() { + it('should route to <%= cameledName %>.controller.destroy', function() { routerStub.delete - .withArgs('/:id', '<%= name %>Ctrl.destroy') + .withArgs('/:id', '<%= cameledName %>Ctrl.destroy') .should.have.been.calledOnce; }); From 40277fdb35478df8c4860ed2bed2997bb2b4edb4 Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 29 Jul 2015 07:08:59 -0400 Subject: [PATCH 0175/1357] chore(dependencies): update sequelize --- app/templates/_package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index c9b1533be..f72c18ca5 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -19,7 +19,7 @@ "mongoose": "~4.0.3", "mongoose-bird": "~0.0.1", "connect-mongo": "^0.8.1",<% } %><% if (filters.sequelize) { %> - "sequelize": "^2.0.0-rc2", + "sequelize": "^3.5.1", "sqlite3": "~3.0.2",<% } %><% if (filters.auth) { %> "jsonwebtoken": "^5.0.0", "express-jwt": "^3.0.0", From 63fae5cb2c8e0b21e5140ebd522a8b8d768c075b Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 29 Jul 2015 07:09:40 -0400 Subject: [PATCH 0176/1357] fix(gen): remove thing import from sequelize template --- .../server/sqldb(sequelize)/index.js | 21 +++---------------- 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/app/templates/server/sqldb(sequelize)/index.js b/app/templates/server/sqldb(sequelize)/index.js index 231db9823..2500a2213 100644 --- a/app/templates/server/sqldb(sequelize)/index.js +++ b/app/templates/server/sqldb(sequelize)/index.js @@ -13,23 +13,8 @@ var db = { Sequelize: Sequelize, sequelize: new Sequelize(config.sequelize.uri, config.sequelize.options) }; -<% if (filters.sequelizeModels) { %> -db.Thing = db.sequelize.import(path.join( - config.root, - 'server', - 'api', - 'thing', - 'thing.model' -)); -<% if (filters.auth) { %> -db.User = db.sequelize.import(path.join( - config.root, - 'server', - 'api', - 'user', - 'user.model' -)); -<% } %><% } %> -// Insert models below + +// Insert models below<% if (filters.sequelizeModels && filters.auth) { %> +db.User = db.sequelize.import('../api/user/user.model');<% } %> module.exports = db; From 06eeab4312bde750819366b40ab062fd5c8b7465 Mon Sep 17 00:00:00 2001 From: kingcody Date: Sun, 2 Aug 2015 05:23:26 -0400 Subject: [PATCH 0177/1357] fix(test): add endpoint sub-gen as test dependency --- test/test-file-creation.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/test-file-creation.js b/test/test-file-creation.js index ce8635c0b..21b4c69fa 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -314,6 +314,7 @@ describe('angular-fullstack generator', function () { this.timeout(10000); var deps = [ '../../app', + '../../endpoint', [ helpers.createDummyGenerator(), 'ng-component:app' @@ -421,6 +422,7 @@ describe('angular-fullstack generator', function () { fs.copySync(__dirname + '/fixtures/.yo-rc.json', __dirname + '/temp/.yo-rc.json'); var gen = helpers.createGenerator('angular-fullstack:app', [ '../../app', + '../../endpoint', [ helpers.createDummyGenerator(), 'ng-component:app' @@ -445,6 +447,7 @@ describe('angular-fullstack generator', function () { fs.copySync(__dirname + '/fixtures/.yo-rc.json', __dirname + '/temp/.yo-rc.json'); var gen = helpers.createGenerator('angular-fullstack:app', [ '../../app', + '../../endpoint', [ helpers.createDummyGenerator(), 'ng-component:app' From c18824a8bbdeedf84807fc04d08eaa3ff7246772 Mon Sep 17 00:00:00 2001 From: kingcody Date: Sun, 2 Aug 2015 06:36:29 -0400 Subject: [PATCH 0178/1357] test(endpoint): test against a path name endpoint --- test/test-file-creation.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 21b4c69fa..fb0fb2b91 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -417,6 +417,29 @@ describe('angular-fullstack generator', function () { runTest('grunt test:server', this, done, 'Foo'); }); + it('should pass lint with generated path name endpoint', function(done) { + runTest('grunt jshint', this, done, 'foo/bar'); + }); + + it('should run server tests successfully with generated path name endpoint', function(done) { + runTest('grunt test:server', this, done, 'foo/bar'); + }); + + it('should generate expected files with path name endpoint', function(done) { + runTest('(exit 0)', this, function() { + helpers.assertFile([ + 'server/api/foo/bar/index.js', + 'server/api/foo/bar/index.spec.js', + 'server/api/foo/bar/bar.controller.js', + 'server/api/foo/bar/bar.events.js', + 'server/api/foo/bar/bar.integration.js', + 'server/api/foo/bar/bar.model.js', + 'server/api/foo/bar/bar.socket.js' + ]); + done(); + }, 'foo/bar'); + }); + it('should use existing config if available', function(done) { this.timeout(60000); fs.copySync(__dirname + '/fixtures/.yo-rc.json', __dirname + '/temp/.yo-rc.json'); From 3b6650710ff7b212e4fc9e74b98c7bac719c397f Mon Sep 17 00:00:00 2001 From: kingcody Date: Mon, 10 Aug 2015 00:25:45 -0400 Subject: [PATCH 0179/1357] feat(gen): add david grunt task --- Gruntfile.js | 15 +++++++++++++++ package.json | 1 + 2 files changed, 16 insertions(+) diff --git a/Gruntfile.js b/Gruntfile.js index c81bffa5c..befea75e5 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -87,6 +87,16 @@ module.exports = function (grunt) { ] }] } + }, + david: { + gen: { + options: {} + }, + app: { + options: { + package: 'test/fixtures/package.json' + } + } } }); @@ -271,6 +281,11 @@ module.exports = function (grunt) { ]) }); + grunt.registerTask('deps', function(target) { + if (!target || target === 'app') grunt.task.run(['updateFixtures']); + grunt.task.run(['david:' + (target || '')]); + }); + grunt.registerTask('demo', [ 'clean:demo', 'generateDemo' diff --git a/package.json b/package.json index f20b54725..7dfa26f05 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "grunt-contrib-clean": "^0.6.0", "grunt-contrib-jshint": "^0.11.2", "grunt-conventional-changelog": "~1.0.0", + "grunt-david": "~0.5.0", "grunt-env": "^0.4.1", "grunt-mocha-test": "^0.11.0", "grunt-release": "~0.6.0", From 1d5ab7db3b71110b30aa9fc0a3a3601c47e6e72f Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 12 Aug 2015 06:01:22 -0400 Subject: [PATCH 0180/1357] feat(app): server ships with babel --- app/templates/README.md | 3 +-- app/templates/_package.json | 4 ++-- app/templates/server/index.js | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/templates/README.md b/app/templates/README.md index bb4def0ce..e49273a90 100644 --- a/app/templates/README.md +++ b/app/templates/README.md @@ -11,8 +11,7 @@ This project was generated with the [Angular Full-Stack Generator](https://githu - [Bower](bower.io) (`npm install --global bower`)<% if(filters.sass) { %> - [Ruby](https://www.ruby-lang.org) and then `gem install sass`<% } if(filters.grunt) { %> - [Grunt](http://gruntjs.com/) (`npm install --global grunt-cli`)<% } if(filters.gulp) { %> -- [Gulp](http://gulpjs.com/) (`npm install --global gulp`)<% } if(filters.babel) { %> -- [Babel](https://babeljs.io) (`npm install --global babel`)<% } if(filters.mongoose) { %> +- [Gulp](http://gulpjs.com/) (`npm install --global gulp`)<% } if(filters.mongoose) { %> - [MongoDB](https://www.mongodb.org/) - Keep a running daemon with `mongod`<% } if(filters.sequelize) { %> - [SQLite](https://www.sqlite.org/quickstart.html)<% } %> diff --git a/app/templates/_package.json b/app/templates/_package.json index f72c18ca5..7ea2eda4b 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -12,8 +12,8 @@ "errorhandler": "~1.0.0", "compression": "~1.0.1", "composable-middleware": "^0.3.0", - "lodash": "~2.4.1",<% if(filters.babel) { %> - "babel-core": "^5.6.4",<% } %><% if (filters.jade) { %> + "lodash": "~2.4.1", + "babel-core": "^5.6.4",<% if (filters.jade) { %> "jade": "~1.2.0",<% } %><% if (filters.html) { %> "ejs": "~0.8.4",<% } %><% if (filters.mongoose) { %> "mongoose": "~4.0.3", diff --git a/app/templates/server/index.js b/app/templates/server/index.js index 7722a0e6c..fc65cd5f4 100644 --- a/app/templates/server/index.js +++ b/app/templates/server/index.js @@ -1,7 +1,7 @@ -'use strict';<% if (filters.babel) { %> +'use strict'; // Register the Babel require hook -require('babel-core/register');<% } %> +require('babel-core/register'); // Export the application exports = module.exports = require('./app'); From 733843e68348a96a5444fd37640d1726dc517701 Mon Sep 17 00:00:00 2001 From: Jinyoung Kim Date: Wed, 12 Aug 2015 22:32:37 +0900 Subject: [PATCH 0181/1357] chore(dependencies): remove angular-scenario --- app/templates/Gruntfile.js | 1 - app/templates/_bower.json | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index bd4559db6..8788038b1 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -245,7 +245,6 @@ module.exports = function (grunt) { wiredep: { options: { exclude: [ - /angular-scenario/, /bootstrap-sass-official/, /bootstrap.js/, '/json3/', diff --git a/app/templates/_bower.json b/app/templates/_bower.json index 5798b8a73..1d41b39d1 100644 --- a/app/templates/_bower.json +++ b/app/templates/_bower.json @@ -18,7 +18,6 @@ "angular-ui-router": "~0.2.15"<% } %> }, "devDependencies": { - "angular-mocks": "~1.4.0", - "angular-scenario": "~1.4.0" + "angular-mocks": "~1.4.0" } } From a849395d67290dd68721eb4f9871db2f1d3c6b66 Mon Sep 17 00:00:00 2001 From: Jinyoung Kim Date: Wed, 12 Aug 2015 22:35:49 +0900 Subject: [PATCH 0182/1357] docs(readme): remove angular-senario in bower list --- readme.md | 1 - 1 file changed, 1 deletion(-) diff --git a/readme.md b/readme.md index af727cdb8..f5f37e9e1 100644 --- a/readme.md +++ b/readme.md @@ -302,7 +302,6 @@ The following packages are always installed by the [app](#app) generator: * angular-mocks * angular-resource * angular-sanitize -* angular-scenario * es5-shim * font-awesome * json3 From c8e2f0f36e373bb22596c36fcb74cc3695f02e9a Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 12 Aug 2015 23:05:29 -0400 Subject: [PATCH 0183/1357] feat(gen): test helper `does` accepts escaped template strings --- app/index.js | 2 ++ script-base.js | 2 ++ 2 files changed, 4 insertions(+) diff --git a/app/index.js b/app/index.js index c161fd381..50ec1deed 100644 --- a/app/index.js +++ b/app/index.js @@ -28,6 +28,8 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ // dynamic assertion statement this.does = this.is = function(foo) { + foo = this.engine(foo.replace(/\(;>%%<;\)/g, '<%') + .replace(/\(;>%<;\)/g, '%>'), this); if (this.filters.should) { return foo + '.should'; } else { diff --git a/script-base.js b/script-base.js index d88cd988c..f24b61f85 100644 --- a/script-base.js +++ b/script-base.js @@ -25,6 +25,8 @@ var Generator = module.exports = function Generator() { // dynamic assertion statement this.does = this.is = function(foo) { + foo = this.engine(foo.replace(/\(;>%%<;\)/g, '<%') + .replace(/\(;>%<;\)/g, '%>'), this); if (this.filters.should) { return foo + '.should'; } else { From 6fa4b4e56c6f6e56d103fba8dab7ba75cabbe142 Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 12 Aug 2015 23:28:56 -0400 Subject: [PATCH 0184/1357] fix(app): only generate excludes for included deps --- app/templates/Gruntfile.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 8788038b1..c9d5568aa 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -245,12 +245,12 @@ module.exports = function (grunt) { wiredep: { options: { exclude: [ - /bootstrap-sass-official/, /bootstrap.js/, '/json3/', '/es5-shim/'<% if(!filters.css) { %>, - /bootstrap.css/, - /font-awesome.css/<% } %> + /font-awesome\.css/<% if(filters.bootstrap) { %>, + /bootstrap\.css/<% if(filters.sass) { %>, + /bootstrap-sass-official/<% }}} %> ] }, client: { From 11ce5c10d619d12d95102a962836ea2c84ed3e1f Mon Sep 17 00:00:00 2001 From: kingcody Date: Thu, 13 Aug 2015 06:19:59 -0400 Subject: [PATCH 0185/1357] feat(gen): replace `does` templating syntax Changes: * Use `<%= expect() %>ASSERTION_SUBJECT<%= to() %>` syntax * Implement dynamic assertions for all server tests including endpoints * Default to `should` even when jasmine is chosen since there are no jasmine server tests * Refactor tests to comply with project indentation closes DaftMonk/generator-angular-fullstack#1163 --- app/index.js | 15 +++----- .../main/main.controller.spec(coffee).coffee | 2 +- .../app/main/main.controller.spec(js).js | 2 +- .../components/auth(auth)/user.service(js).js | 2 +- .../account(auth)/login/login.spec(mocha).js | 20 +++++----- .../logout/logout.spec(mocha).js | 8 ++-- .../signup/signup.spec(mocha).js | 26 ++++++------- app/templates/e2e/main/main.spec(mocha).js | 6 +-- .../server/api/user(auth)/index.spec.js | 38 +++++++++---------- .../server/api/user(auth)/user.integration.js | 2 +- .../user.model.spec(mongooseModels).js | 18 ++++----- .../user.model.spec(sequelizeModels).js | 18 ++++----- endpoint/templates/basename.integration.js | 14 +++---- endpoint/templates/index.spec.js | 38 +++++++++---------- script-base.js | 15 +++----- 15 files changed, 109 insertions(+), 115 deletions(-) diff --git a/app/index.js b/app/index.js index 50ec1deed..896418259 100644 --- a/app/index.js +++ b/app/index.js @@ -26,15 +26,12 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ this.filters = {}; - // dynamic assertion statement - this.does = this.is = function(foo) { - foo = this.engine(foo.replace(/\(;>%%<;\)/g, '<%') - .replace(/\(;>%<;\)/g, '%>'), this); - if (this.filters.should) { - return foo + '.should'; - } else { - return 'expect(' + foo + ').to'; - } + // dynamic assertion statements + this.expect = function() { + return this.filters.expect ? 'expect(' : ''; + }.bind(this); + this.to = function() { + return this.filters.expect ? ').to' : '.should'; }.bind(this); }, diff --git a/app/templates/client/app/main/main.controller.spec(coffee).coffee b/app/templates/client/app/main/main.controller.spec(coffee).coffee index a72ae8695..0284253d7 100644 --- a/app/templates/client/app/main/main.controller.spec(coffee).coffee +++ b/app/templates/client/app/main/main.controller.spec(coffee).coffee @@ -29,4 +29,4 @@ describe 'Controller: MainCtrl', -> it 'should attach a list of things to the scope', -> $httpBackend.flush()<% if (filters.jasmine) { %> expect(scope.awesomeThings.length).toBe 4 <% } if (filters.mocha) { %> - <%= does("scope.awesomeThings.length") %>.equal 4<% } %> + <%= expect() %>scope.awesomeThings.length<%= to() %>.equal 4<% } %> diff --git a/app/templates/client/app/main/main.controller.spec(js).js b/app/templates/client/app/main/main.controller.spec(js).js index 71fd2a783..b8a652a79 100644 --- a/app/templates/client/app/main/main.controller.spec(js).js +++ b/app/templates/client/app/main/main.controller.spec(js).js @@ -28,6 +28,6 @@ describe('Controller: MainCtrl', function() { it('should attach a list of things to the scope', function() { $httpBackend.flush();<% if (filters.jasmine) { %> expect(scope.awesomeThings.length).toBe(4);<% } if (filters.mocha) { %> - <%= does("scope.awesomeThings.length") %>.equal(4);<% } %> + <%= expect() %>scope.awesomeThings.length<%= to() %>.equal(4);<% } %> }); }); diff --git a/app/templates/client/components/auth(auth)/user.service(js).js b/app/templates/client/components/auth(auth)/user.service(js).js index c41fe8312..aad887945 100644 --- a/app/templates/client/components/auth(auth)/user.service(js).js +++ b/app/templates/client/components/auth(auth)/user.service(js).js @@ -18,5 +18,5 @@ angular.module('<%= scriptAppName %>') id:'me' } } - }); + }); }); diff --git a/app/templates/e2e/account(auth)/login/login.spec(mocha).js b/app/templates/e2e/account(auth)/login/login.spec(mocha).js index a33970e67..1f7540e94 100644 --- a/app/templates/e2e/account(auth)/login/login.spec(mocha).js +++ b/app/templates/e2e/account(auth)/login/login.spec(mocha).js @@ -35,12 +35,12 @@ describe('Login View', function() { }); it('should include login form with correct inputs and submit button', function() { - <%= does("page.form.email.getAttribute('type')") %>.eventually.equal('email'); - <%= does("page.form.email.getAttribute('name')") %>.eventually.equal('email'); - <%= does("page.form.password.getAttribute('type')") %>.eventually.equal('password'); - <%= does("page.form.password.getAttribute('name')") %>.eventually.equal('password'); - <%= does("page.form.submit.getAttribute('type')") %>.eventually.equal('submit'); - <%= does("page.form.submit.getText()") %>.eventually.equal('Login'); + <%= expect() %>page.form.email.getAttribute('type')<%= to() %>.eventually.equal('email'); + <%= expect() %>page.form.email.getAttribute('name')<%= to() %>.eventually.equal('email'); + <%= expect() %>page.form.password.getAttribute('type')<%= to() %>.eventually.equal('password'); + <%= expect() %>page.form.password.getAttribute('name')<%= to() %>.eventually.equal('password'); + <%= expect() %>page.form.submit.getAttribute('type')<%= to() %>.eventually.equal('submit'); + <%= expect() %>page.form.submit.getText()<%= to() %>.eventually.equal('Login'); }); describe('with local auth', function() { @@ -50,8 +50,8 @@ describe('Login View', function() { var navbar = require('../../components/navbar/navbar.po'); - <%= does("browser.getCurrentUrl()") %>.eventually.equal(config.baseUrl + '/'); - <%= does("navbar.navbarAccountGreeting.getText()") %>.eventually.equal('Hello ' + testUser.name); + <%= expect() %>browser.getCurrentUrl()<%= to() %>.eventually.equal(config.baseUrl + '/'); + <%= expect() %>navbar.navbarAccountGreeting.getText()<%= to() %>.eventually.equal('Hello ' + testUser.name); }); describe('and invalid credentials', function() { @@ -65,10 +65,10 @@ describe('Login View', function() { password: 'badPassword' }); - <%= does("browser.getCurrentUrl()") %>.eventually.equal(config.baseUrl + '/login'); + <%= expect() %>browser.getCurrentUrl()<%= to() %>.eventually.equal(config.baseUrl + '/login'); var helpBlock = page.form.element(by.css('.form-group.has-error .help-block.ng-binding')); - <%= does("helpBlock.getText()") %>.eventually.equal('This password is not correct.'); + <%= expect() %>helpBlock.getText()<%= to() %>.eventually.equal('This password is not correct.'); }); }); diff --git a/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js b/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js index 1e969ccf2..9343c702b 100644 --- a/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js +++ b/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js @@ -39,15 +39,15 @@ describe('Logout View', function() { it('should logout a user and redirecting to "/"', function() { var navbar = require('../../components/navbar/navbar.po'); - <%= does("browser.getCurrentUrl()") %>.eventually.equal(config.baseUrl + '/'); - <%= does("navbar.navbarAccountGreeting.getText()") %>.eventually.equal('Hello ' + testUser.name); + <%= expect() %>browser.getCurrentUrl()<%= to() %>.eventually.equal(config.baseUrl + '/'); + <%= expect() %>navbar.navbarAccountGreeting.getText()<%= to() %>.eventually.equal('Hello ' + testUser.name); browser.get(config.baseUrl + '/logout'); navbar = require('../../components/navbar/navbar.po'); - <%= does("browser.getCurrentUrl()") %>.eventually.equal(config.baseUrl + '/'); - <%= does("navbar.navbarAccountGreeting.isDisplayed()") %>.eventually.equal(false); + <%= expect() %>browser.getCurrentUrl()<%= to() %>.eventually.equal(config.baseUrl + '/'); + <%= expect() %>navbar.navbarAccountGreeting.isDisplayed()<%= to() %>.eventually.equal(false); }); }); diff --git a/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js b/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js index c0bade616..9ac285f13 100644 --- a/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js +++ b/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js @@ -29,14 +29,14 @@ describe('Signup View', function() { }); it('should include signup form with correct inputs and submit button', function() { - <%= does("page.form.name.getAttribute('type')") %>.eventually.equal('text'); - <%= does("page.form.name.getAttribute('name')") %>.eventually.equal('name'); - <%= does("page.form.email.getAttribute('type')") %>.eventually.equal('email'); - <%= does("page.form.email.getAttribute('name')") %>.eventually.equal('email'); - <%= does("page.form.password.getAttribute('type')") %>.eventually.equal('password'); - <%= does("page.form.password.getAttribute('name')") %>.eventually.equal('password'); - <%= does("page.form.submit.getAttribute('type')") %>.eventually.equal('submit'); - <%= does("page.form.submit.getText()") %>.eventually.equal('Sign up'); + <%= expect() %>page.form.name.getAttribute('type')<%= to() %>.eventually.equal('text'); + <%= expect() %>page.form.name.getAttribute('name')<%= to() %>.eventually.equal('name'); + <%= expect() %>page.form.email.getAttribute('type')<%= to() %>.eventually.equal('email'); + <%= expect() %>page.form.email.getAttribute('name')<%= to() %>.eventually.equal('email'); + <%= expect() %>page.form.password.getAttribute('type')<%= to() %>.eventually.equal('password'); + <%= expect() %>page.form.password.getAttribute('name')<%= to() %>.eventually.equal('password'); + <%= expect() %>page.form.submit.getAttribute('type')<%= to() %>.eventually.equal('submit'); + <%= expect() %>page.form.submit.getText()<%= to() %>.eventually.equal('Sign up'); }); describe('with local auth', function() { @@ -51,8 +51,8 @@ describe('Signup View', function() { var navbar = require('../../components/navbar/navbar.po'); - <%= does("browser.getCurrentUrl()") %>.eventually.equal(config.baseUrl + '/'); - <%= does("navbar.navbarAccountGreeting.getText()") %>.eventually.equal('Hello ' + testUser.name); + <%= expect() %>browser.getCurrentUrl()<%= to() %>.eventually.equal(config.baseUrl + '/'); + <%= expect() %>navbar.navbarAccountGreeting.getText()<%= to() %>.eventually.equal('Hello ' + testUser.name); }); describe('and invalid credentials', function() { @@ -63,11 +63,11 @@ describe('Signup View', function() { it('should indicate signup failures', function() { page.signup(testUser); - <%= does("browser.getCurrentUrl()") %>.eventually.equal(config.baseUrl + '/signup'); - <%= does("page.form.email.getAttribute('class')") %>.eventually.contain('ng-invalid-mongoose'); + <%= expect() %>browser.getCurrentUrl()<%= to() %>.eventually.equal(config.baseUrl + '/signup'); + <%= expect() %>page.form.email.getAttribute('class')<%= to() %>.eventually.contain('ng-invalid-mongoose'); var helpBlock = page.form.element(by.css('.form-group.has-error .help-block.ng-binding')); - <%= does("helpBlock.getText()") %>.eventually.equal('The specified email address is already in use.'); + <%= expect() %>helpBlock.getText()<%= to() %>.eventually.equal('The specified email address is already in use.'); }); }); diff --git a/app/templates/e2e/main/main.spec(mocha).js b/app/templates/e2e/main/main.spec(mocha).js index 4ea5c1012..d497443cd 100644 --- a/app/templates/e2e/main/main.spec(mocha).js +++ b/app/templates/e2e/main/main.spec(mocha).js @@ -11,8 +11,8 @@ describe('Main View', function() { }); it('should include jumbotron with correct data', function() { - <%= does("page.h1El.getText()") %>.eventually.equal('\'Allo, \'Allo!'); - <%= does("page.imgEl.getAttribute('src')") %>.eventually.match(/yeoman.png$/); - <%= does("page.imgEl.getAttribute('alt')") %>.eventually.equal('I\'m Yeoman'); + <%= expect() %>page.h1El.getText()<%= to() %>.eventually.equal('\'Allo, \'Allo!'); + <%= expect() %>page.imgEl.getAttribute('src')<%= to() %>.eventually.match(/yeoman.png$/); + <%= expect() %>page.imgEl.getAttribute('alt')<%= to() %>.eventually.equal('I\'m Yeoman'); }); }); diff --git a/app/templates/server/api/user(auth)/index.spec.js b/app/templates/server/api/user(auth)/index.spec.js index d2ee914bd..18d39989d 100644 --- a/app/templates/server/api/user(auth)/index.spec.js +++ b/app/templates/server/api/user(auth)/index.spec.js @@ -41,15 +41,15 @@ var userIndex = proxyquire('./index', { describe('User API Router:', function() { it('should return an express router instance', function() { - userIndex.should.equal(routerStub); + <%= expect() %>userIndex<%= to() %>.equal(routerStub); }); describe('GET /api/users', function() { it('should verify admin role and route to user.controller.index', function() { - routerStub.get - .withArgs('/', 'authService.hasRole.admin', 'userCtrl.index') - .should.have.been.calledOnce; + <%= expect() %>routerStub.get + .withArgs('/', 'authService.hasRole.admin', 'userCtrl.index') + <%= to() %>.have.been.calledOnce; }); }); @@ -57,9 +57,9 @@ describe('User API Router:', function() { describe('DELETE /api/users/:id', function() { it('should verify admin role and route to user.controller.destroy', function() { - routerStub.delete - .withArgs('/:id', 'authService.hasRole.admin', 'userCtrl.destroy') - .should.have.been.calledOnce; + <%= expect() %>routerStub.delete + .withArgs('/:id', 'authService.hasRole.admin', 'userCtrl.destroy') + <%= to() %>.have.been.calledOnce; }); }); @@ -67,9 +67,9 @@ describe('User API Router:', function() { describe('GET /api/users/me', function() { it('should be authenticated and route to user.controller.me', function() { - routerStub.get - .withArgs('/me', 'authService.isAuthenticated', 'userCtrl.me') - .should.have.been.calledOnce; + <%= expect() %>routerStub.get + .withArgs('/me', 'authService.isAuthenticated', 'userCtrl.me') + <%= to() %>.have.been.calledOnce; }); }); @@ -77,9 +77,9 @@ describe('User API Router:', function() { describe('PUT /api/users/:id/password', function() { it('should be authenticated and route to user.controller.changePassword', function() { - routerStub.put - .withArgs('/:id/password', 'authService.isAuthenticated', 'userCtrl.changePassword') - .should.have.been.calledOnce; + <%= expect() %>routerStub.put + .withArgs('/:id/password', 'authService.isAuthenticated', 'userCtrl.changePassword') + <%= to() %>.have.been.calledOnce; }); }); @@ -87,9 +87,9 @@ describe('User API Router:', function() { describe('GET /api/users/:id', function() { it('should be authenticated and route to user.controller.show', function() { - routerStub.get - .withArgs('/:id', 'authService.isAuthenticated', 'userCtrl.show') - .should.have.been.calledOnce; + <%= expect() %>routerStub.get + .withArgs('/:id', 'authService.isAuthenticated', 'userCtrl.show') + <%= to() %>.have.been.calledOnce; }); }); @@ -97,9 +97,9 @@ describe('User API Router:', function() { describe('POST /api/users', function() { it('should route to user.controller.create', function() { - routerStub.post - .withArgs('/', 'userCtrl.create') - .should.have.been.calledOnce; + <%= expect() %>routerStub.post + .withArgs('/', 'userCtrl.create') + <%= to() %>.have.been.calledOnce; }); }); diff --git a/app/templates/server/api/user(auth)/user.integration.js b/app/templates/server/api/user(auth)/user.integration.js index 5273be72a..054619572 100644 --- a/app/templates/server/api/user(auth)/user.integration.js +++ b/app/templates/server/api/user(auth)/user.integration.js @@ -55,7 +55,7 @@ describe('User API:', function() { .expect(200) .expect('Content-Type', /json/) .end(function(err, res) { - res.body._id.toString().should.equal(user._id.toString()); + <%= expect() %>res.body._id.toString()<%= to() %>.equal(user._id.toString()); done(); }); }); diff --git a/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js b/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js index 1aad3b25e..06e76cea8 100644 --- a/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js +++ b/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js @@ -28,22 +28,22 @@ describe('User Model', function() { }); it('should begin with no users', function() { - return User.findAsync({}) - .should.eventually.have.length(0); + return <%= expect() %>User.findAsync({})<%= to() %> + .eventually.have.length(0); }); it('should fail when saving a duplicate user', function() { - return user.saveAsync() + return <%= expect() %>user.saveAsync() .then(function() { var userDup = genUser(); return userDup.saveAsync(); - }).should.be.rejected; + })<%= to() %>.be.rejected; }); describe('#email', function() { it('should fail when saving without an email', function() { user.email = ''; - return user.saveAsync().should.be.rejected; + return <%= expect() %>user.saveAsync()<%= to() %>.be.rejected; }); }); @@ -53,19 +53,19 @@ describe('User Model', function() { }); it('should authenticate user if valid', function() { - user.authenticate('password').should.be.true; + <%= expect() %>user.authenticate('password')<%= to() %>.be.true; }); it('should not authenticate user if invalid', function() { - user.authenticate('blah').should.not.be.true; + <%= expect() %>user.authenticate('blah')<%= to() %>.not.be.true; }); it('should remain the same hash unless the password is updated', function() { user.name = 'Test User'; - return user.saveAsync() + return <%= expect() %>user.saveAsync() .spread(function(u) { return u.authenticate('password'); - }).should.eventually.be.true; + })<%= to() %>.eventually.be.true; }); }); diff --git a/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js b/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js index a7af1bd38..0cbe28f9e 100644 --- a/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js +++ b/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js @@ -30,22 +30,22 @@ describe('User Model', function() { }); it('should begin with no users', function() { - return User.findAll() - .should.eventually.have.length(0); + return <%= expect() %>User.findAll()<%= to() %> + .eventually.have.length(0); }); it('should fail when saving a duplicate user', function() { - return user.save() + return <%= expect() %>user.save() .then(function() { var userDup = genUser(); return userDup.save(); - }).should.be.rejected; + })<%= to() %>.be.rejected; }); describe('#email', function() { it('should fail when saving without an email', function() { user.email = ''; - return user.save().should.be.rejected; + return <%= expect() %>user.save()<%= to() %>.be.rejected; }); }); @@ -55,19 +55,19 @@ describe('User Model', function() { }); it('should authenticate user if valid', function() { - user.authenticate('password').should.be.true; + <%= expect() %>user.authenticate('password')<%= to() %>.be.true; }); it('should not authenticate user if invalid', function() { - user.authenticate('blah').should.not.be.true; + <%= expect() %>user.authenticate('blah')<%= to() %>.not.be.true; }); it('should remain the same hash unless the password is updated', function() { user.name = 'Test User'; - return user.save() + return <%= expect() %>user.save() .then(function(u) { return u.authenticate('password'); - }).should.eventually.be.true; + })<%= to() %>.eventually.be.true; }); }); diff --git a/endpoint/templates/basename.integration.js b/endpoint/templates/basename.integration.js index bcd3fd407..3ea3f36b7 100644 --- a/endpoint/templates/basename.integration.js +++ b/endpoint/templates/basename.integration.js @@ -25,7 +25,7 @@ describe('<%= classedName %> API:', function() { }); it('should respond with JSON array', function() { - <%= cameledName %>s.should.be.instanceOf(Array); + <%= expect() %><%= cameledName %>s<%= to() %>.be.instanceOf(Array); }); });<% if(filters.models) { %> @@ -50,8 +50,8 @@ describe('<%= classedName %> API:', function() { }); it('should respond with the newly created <%= cameledName %>', function() { - new<%= classedName %>.name.should.equal('New <%= classedName %>'); - new<%= classedName %>.info.should.equal('This is the brand new <%= cameledName %>!!!'); + <%= expect() %>new<%= classedName %>.name<%= to() %>.equal('New <%= classedName %>'); + <%= expect() %>new<%= classedName %>.info<%= to() %>.equal('This is the brand new <%= cameledName %>!!!'); }); }); @@ -78,8 +78,8 @@ describe('<%= classedName %> API:', function() { }); it('should respond with the requested <%= cameledName %>', function() { - <%= cameledName %>.name.should.equal('New <%= classedName %>'); - <%= cameledName %>.info.should.equal('This is the brand new <%= cameledName %>!!!'); + <%= expect() %><%= cameledName %>.name<%= to() %>.equal('New <%= classedName %>'); + <%= expect() %><%= cameledName %>.info<%= to() %>.equal('This is the brand new <%= cameledName %>!!!'); }); }); @@ -110,8 +110,8 @@ describe('<%= classedName %> API:', function() { }); it('should respond with the updated <%= cameledName %>', function() { - updated<%= classedName %>.name.should.equal('Updated <%= classedName %>'); - updated<%= classedName %>.info.should.equal('This is the updated <%= cameledName %>!!!'); + <%= expect() %>updated<%= classedName %>.name<%= to() %>.equal('Updated <%= classedName %>'); + <%= expect() %>updated<%= classedName %>.info<%= to() %>.equal('This is the updated <%= cameledName %>!!!'); }); }); diff --git a/endpoint/templates/index.spec.js b/endpoint/templates/index.spec.js index 4bd178948..81b6ec54a 100644 --- a/endpoint/templates/index.spec.js +++ b/endpoint/templates/index.spec.js @@ -31,15 +31,15 @@ var <%= cameledName %>Index = proxyquire('./index.js', { describe('<%= classedName %> API Router:', function() { it('should return an express router instance', function() { - <%= cameledName %>Index.should.equal(routerStub); + <%= expect() %><%= cameledName %>Index<%= to() %>.equal(routerStub); }); describe('GET <%= route %>', function() { it('should route to <%= cameledName %>.controller.index', function() { - routerStub.get - .withArgs('/', '<%= cameledName %>Ctrl.index') - .should.have.been.calledOnce; + <%= expect() %>routerStub.get + .withArgs('/', '<%= cameledName %>Ctrl.index') + <%= to() %>.have.been.calledOnce; }); });<% if(filters.models) { %> @@ -47,9 +47,9 @@ describe('<%= classedName %> API Router:', function() { describe('GET <%= route %>/:id', function() { it('should route to <%= cameledName %>.controller.show', function() { - routerStub.get - .withArgs('/:id', '<%= cameledName %>Ctrl.show') - .should.have.been.calledOnce; + <%= expect() %>routerStub.get + .withArgs('/:id', '<%= cameledName %>Ctrl.show') + <%= to() %>.have.been.calledOnce; }); }); @@ -57,9 +57,9 @@ describe('<%= classedName %> API Router:', function() { describe('POST <%= route %>', function() { it('should route to <%= cameledName %>.controller.create', function() { - routerStub.post - .withArgs('/', '<%= cameledName %>Ctrl.create') - .should.have.been.calledOnce; + <%= expect() %>routerStub.post + .withArgs('/', '<%= cameledName %>Ctrl.create') + <%= to() %>.have.been.calledOnce; }); }); @@ -67,9 +67,9 @@ describe('<%= classedName %> API Router:', function() { describe('PUT <%= route %>/:id', function() { it('should route to <%= cameledName %>.controller.update', function() { - routerStub.put - .withArgs('/:id', '<%= cameledName %>Ctrl.update') - .should.have.been.calledOnce; + <%= expect() %>routerStub.put + .withArgs('/:id', '<%= cameledName %>Ctrl.update') + <%= to() %>.have.been.calledOnce; }); }); @@ -77,9 +77,9 @@ describe('<%= classedName %> API Router:', function() { describe('PATCH <%= route %>/:id', function() { it('should route to <%= cameledName %>.controller.update', function() { - routerStub.patch - .withArgs('/:id', '<%= cameledName %>Ctrl.update') - .should.have.been.calledOnce; + <%= expect() %>routerStub.patch + .withArgs('/:id', '<%= cameledName %>Ctrl.update') + <%= to() %>.have.been.calledOnce; }); }); @@ -87,9 +87,9 @@ describe('<%= classedName %> API Router:', function() { describe('DELETE <%= route %>/:id', function() { it('should route to <%= cameledName %>.controller.destroy', function() { - routerStub.delete - .withArgs('/:id', '<%= cameledName %>Ctrl.destroy') - .should.have.been.calledOnce; + <%= expect() %>routerStub.delete + .withArgs('/:id', '<%= cameledName %>Ctrl.destroy') + <%= to() %>.have.been.calledOnce; }); });<% } %> diff --git a/script-base.js b/script-base.js index f24b61f85..288a4e4f4 100644 --- a/script-base.js +++ b/script-base.js @@ -23,15 +23,12 @@ var Generator = module.exports = function Generator() { this.basename = path.basename(this.name); this.dirname = (this.name.indexOf('/') >= 0) ? path.dirname(this.name) : this.name; - // dynamic assertion statement - this.does = this.is = function(foo) { - foo = this.engine(foo.replace(/\(;>%%<;\)/g, '<%') - .replace(/\(;>%<;\)/g, '%>'), this); - if (this.filters.should) { - return foo + '.should'; - } else { - return 'expect(' + foo + ').to'; - } + // dynamic assertion statements + this.expect = function() { + return this.filters.expect ? 'expect(' : ''; + }.bind(this); + this.to = function() { + return this.filters.expect ? ').to' : '.should'; }.bind(this); // dynamic relative require path From 385ca937ab67478ee83835e4e656ddbbc840d986 Mon Sep 17 00:00:00 2001 From: kingcody Date: Thu, 13 Aug 2015 08:00:51 -0400 Subject: [PATCH 0186/1357] chore(dependencies): update mongoose to `^4.1.2` --- app/templates/_package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 7ea2eda4b..ad59553ed 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -16,7 +16,7 @@ "babel-core": "^5.6.4",<% if (filters.jade) { %> "jade": "~1.2.0",<% } %><% if (filters.html) { %> "ejs": "~0.8.4",<% } %><% if (filters.mongoose) { %> - "mongoose": "~4.0.3", + "mongoose": "^4.1.2", "mongoose-bird": "~0.0.1", "connect-mongo": "^0.8.1",<% } %><% if (filters.sequelize) { %> "sequelize": "^3.5.1", From ee9f4f08a4d6557ff9be446a1622de3e01082b8e Mon Sep 17 00:00:00 2001 From: kingcody Date: Thu, 13 Aug 2015 08:15:20 -0400 Subject: [PATCH 0187/1357] fix(app): karma requires `babel` always --- app/templates/mocha.conf.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/mocha.conf.js b/app/templates/mocha.conf.js index 6b1504e9c..76f56625e 100644 --- a/app/templates/mocha.conf.js +++ b/app/templates/mocha.conf.js @@ -1,7 +1,7 @@ -'use strict';<% if(filters.babel) { %> +'use strict'; // Register the Babel require hook -require('babel-core/register');<% } %> +require('babel-core/register'); var chai = require('chai'); From 4b3b53d48acabb1d71cd677957d4ab9956a375ad Mon Sep 17 00:00:00 2001 From: kingcody Date: Thu, 13 Aug 2015 23:01:55 -0400 Subject: [PATCH 0188/1357] fix(app): increase mocha default timeout to 5000 This matches the default jasmine spec timeout --- app/templates/Gruntfile.js | 3 ++- app/templates/karma.conf.js | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index c9d5568aa..a287531d3 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -484,7 +484,8 @@ module.exports = function (grunt) { mochaTest: { options: { reporter: 'spec', - require: 'mocha.conf.js' + require: 'mocha.conf.js', + timeout: 5000 // set default mocha spec timeout }, unit: { src: ['server/**/*.spec.js'] diff --git a/app/templates/karma.conf.js b/app/templates/karma.conf.js index 5b45e4f86..9b46a3a22 100644 --- a/app/templates/karma.conf.js +++ b/app/templates/karma.conf.js @@ -8,7 +8,13 @@ module.exports = function(config) { // testing framework to use (jasmine/mocha/qunit/...)<% if (filters.jasmine) { %> frameworks: ['jasmine'],<% } if (filters.mocha) { %> - frameworks: ['mocha', 'chai', 'sinon-chai', 'chai-as-promised', 'chai-things'],<% } %> + frameworks: ['mocha', 'chai', 'sinon-chai', 'chai-as-promised', 'chai-things'], + + client: { + mocha: { + timeout: 5000 // set default mocha spec timeout + } + },<% } %> // list of files / patterns to load in the browser files: [ From 6b49ba37bd08ae8774068779e7c96b1f4e5ce5ac Mon Sep 17 00:00:00 2001 From: kingcody Date: Thu, 13 Aug 2015 08:06:58 -0400 Subject: [PATCH 0189/1357] feat(app): directly promisify mongoose Changes: * Remove `mongoose-bird` dependency * Add `bluebird` dependency * Use `bluebird.promisifyAll` when requiring `mongoose` for models see https://github.com/petkaantonov/bluebird/blob/master/API.md#promisification --- app/templates/_package.json | 2 +- app/templates/protractor.conf.js | 2 +- .../server/api/user(auth)/user.model(mongooseModels).js | 2 +- app/templates/server/app.js | 2 +- app/templates/server/auth(auth)/auth.service.js | 3 +-- app/templates/server/config/express.js | 2 +- endpoint/templates/basename.model(mongooseModels).js | 2 +- 7 files changed, 7 insertions(+), 8 deletions(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index ad59553ed..7d061fe3b 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -17,7 +17,7 @@ "jade": "~1.2.0",<% } %><% if (filters.html) { %> "ejs": "~0.8.4",<% } %><% if (filters.mongoose) { %> "mongoose": "^4.1.2", - "mongoose-bird": "~0.0.1", + "bluebird": "^2.9.34", "connect-mongo": "^0.8.1",<% } %><% if (filters.sequelize) { %> "sequelize": "^3.5.1", "sqlite3": "~3.0.2",<% } %><% if (filters.auth) { %> diff --git a/app/templates/protractor.conf.js b/app/templates/protractor.conf.js index 7142f6f54..6178c1a76 100644 --- a/app/templates/protractor.conf.js +++ b/app/templates/protractor.conf.js @@ -82,7 +82,7 @@ var config = { var serverConfig = config.params.serverConfig;<% if (filters.mongoose) { %> // Setup mongo for tests - var mongoose = require('mongoose-bird')(); + var mongoose = require('mongoose'); mongoose.connect(serverConfig.mongo.uri, serverConfig.mongo.options); // Connect to database<% } %> } }; diff --git a/app/templates/server/api/user(auth)/user.model(mongooseModels).js b/app/templates/server/api/user(auth)/user.model(mongooseModels).js index 008412eaf..f8fa923cf 100644 --- a/app/templates/server/api/user(auth)/user.model(mongooseModels).js +++ b/app/templates/server/api/user(auth)/user.model(mongooseModels).js @@ -1,6 +1,6 @@ 'use strict'; -var mongoose = require('mongoose-bird')(); +var mongoose = require('bluebird').promisifyAll(require('mongoose')); var Schema = mongoose.Schema; var crypto = require('crypto');<% if (filters.oauth) { %> var authTypes = ['github', 'twitter', 'facebook', 'google'];<% } %> diff --git a/app/templates/server/app.js b/app/templates/server/app.js index 5c98d1612..ca1e4ca78 100644 --- a/app/templates/server/app.js +++ b/app/templates/server/app.js @@ -8,7 +8,7 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'development'; var express = require('express');<% if (filters.mongoose) { %> -var mongoose = require('mongoose-bird')();<% } %><% if (filters.sequelize) { %> +var mongoose = require('mongoose');<% } %><% if (filters.sequelize) { %> var sqldb = require('./sqldb');<% } %> var config = require('./config/environment'); <% if (filters.mongoose) { %> diff --git a/app/templates/server/auth(auth)/auth.service.js b/app/templates/server/auth(auth)/auth.service.js index faa2684cf..8c100e84b 100644 --- a/app/templates/server/auth(auth)/auth.service.js +++ b/app/templates/server/auth(auth)/auth.service.js @@ -1,6 +1,5 @@ 'use strict'; -<% if (filters.mongooseModels) { %> -var mongoose = require('mongoose-bird')();<% } %> + var passport = require('passport'); var config = require('../config/environment'); var jwt = require('jsonwebtoken'); diff --git a/app/templates/server/config/express.js b/app/templates/server/config/express.js index b29739e01..3cd2f2739 100644 --- a/app/templates/server/config/express.js +++ b/app/templates/server/config/express.js @@ -17,7 +17,7 @@ var config = require('./environment');<% if (filters.auth) { %> var passport = require('passport');<% } %><% if (filters.twitterAuth) { %> var session = require('express-session');<% if (filters.mongoose) { %> var mongoStore = require('connect-mongo')(session); -var mongoose = require('mongoose-bird')();<% } %><% } %> +var mongoose = require('mongoose');<% } %><% } %> module.exports = function(app) { var env = app.get('env'); diff --git a/endpoint/templates/basename.model(mongooseModels).js b/endpoint/templates/basename.model(mongooseModels).js index ac7f7f72a..09787cdf3 100644 --- a/endpoint/templates/basename.model(mongooseModels).js +++ b/endpoint/templates/basename.model(mongooseModels).js @@ -1,6 +1,6 @@ 'use strict'; -var mongoose = require('mongoose-bird')(); +var mongoose = require('bluebird').promisifyAll(require('mongoose')); var Schema = mongoose.Schema; var <%= classedName %>Schema = new Schema({ From 5927906013ae68e74e1579b2f0523ec08defe402 Mon Sep 17 00:00:00 2001 From: kingcody Date: Fri, 14 Aug 2015 03:03:32 -0400 Subject: [PATCH 0190/1357] chore(dependencies): update socket.io related dependencies --- app/templates/_package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 7ea2eda4b..467e2a8ba 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -28,9 +28,9 @@ "passport-facebook": "latest",<% } %><% if (filters.twitterAuth) { %> "passport-twitter": "latest",<% } %><% if (filters.googleAuth) { %> "passport-google-oauth": "latest",<% } %><% if (filters.socketio) { %> - "socket.io": "^1.0.6", - "socket.io-client": "^1.0.6", - "socketio-jwt": "^3.0.0",<% } %> + "socket.io": "^1.3.5", + "socket.io-client": "^1.3.5", + "socketio-jwt": "^4.2.0",<% } %> "serve-favicon": "~2.0.1" }, "devDependencies": { From f4bf6851551742aa525df17d971694aad5549db6 Mon Sep 17 00:00:00 2001 From: kingcody Date: Fri, 14 Aug 2015 03:07:31 -0400 Subject: [PATCH 0191/1357] fix(socket.io): update docs and socket.addres ref --- app/templates/server/config/socketio(socketio).js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/templates/server/config/socketio(socketio).js b/app/templates/server/config/socketio(socketio).js index 446b49dff..92f629729 100644 --- a/app/templates/server/config/socketio(socketio).js +++ b/app/templates/server/config/socketio(socketio).js @@ -27,7 +27,7 @@ module.exports = function(socketio) { // // ex: DEBUG: "http*,socket.io:socket" - // We can authenticate socket.io users and access their token through socket.handshake.decoded_token + // We can authenticate socket.io users and access their token through socket.decoded_token // // 1. You will need to send the token in `client/components/socket/socket.service.js` // @@ -38,10 +38,8 @@ module.exports = function(socketio) { // })); socketio.on('connection', function(socket) { - socket.address = - socket.handshake.address !== null ? - socket.handshake.address.address + ':' + socket.handshake.address.port : - process.env.DOMAIN; + socket.address = socket.request.connection.remoteAddress + + ':' + socket.request.connection.remotePort; socket.connectedAt = new Date(); From 6a07a81443c56995558d95b7e7f10013e9253ab9 Mon Sep 17 00:00:00 2001 From: kingcody Date: Fri, 14 Aug 2015 08:55:30 -0400 Subject: [PATCH 0192/1357] fix(app): only check loggedIn when required --- app/templates/client/app/app(coffee).coffee | 11 ++++++----- app/templates/client/app/app(js).js | 16 +++++++++------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/app/templates/client/app/app(coffee).coffee b/app/templates/client/app/app(coffee).coffee index bf97363b1..f0c1bd129 100644 --- a/app/templates/client/app/app(coffee).coffee +++ b/app/templates/client/app/app(coffee).coffee @@ -33,9 +33,10 @@ angular.module '<%= scriptAppName %>', [<%= angularModules %>] $q.reject response .run ($rootScope<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %>, Auth) -> - # Redirect to login if route requires auth and you're not logged in + # Redirect to login if route requires auth and the user is not logged in $rootScope.$on <% if (filters.ngroute) { %>'$routeChangeStart'<% } %><% if (filters.uirouter) { %>'$stateChangeStart'<% } %>, (event, next) -> - Auth.isLoggedIn (loggedIn) -> - event.preventDefault() - <% if (filters.ngroute) { %>$location.path '/login'<% } %><% if (filters.uirouter) { %>$state.go 'login'<% } %> if next.authenticate and not loggedIn -<% } %> + if next.authenticate + Auth.isLoggedIn (loggedIn) -> + if !loggedIn + event.preventDefault() + <% if (filters.ngroute) { %>$location.path '/login'<% } %><% if (filters.uirouter) { %>$state.go 'login'<% }} %> diff --git a/app/templates/client/app/app(js).js b/app/templates/client/app/app(js).js index 0b636714d..27410af8a 100644 --- a/app/templates/client/app/app(js).js +++ b/app/templates/client/app/app(js).js @@ -45,13 +45,15 @@ angular.module('<%= scriptAppName %>', [<%= angularModules %>]) }) .run(function($rootScope<% if (filters.ngroute) { %>, $location<% } if (filters.uirouter) { %>, $state<% } %>, Auth) { - // Redirect to login if route requires auth and you're not logged in + // Redirect to login if route requires auth and the user is not logged in $rootScope.$on(<% if (filters.ngroute) { %>'$routeChangeStart'<% } %><% if (filters.uirouter) { %>'$stateChangeStart'<% } %>, function(event, next) { - Auth.isLoggedIn(function(loggedIn) { - if (next.authenticate && !loggedIn) { - event.preventDefault(); - <% if (filters.ngroute) { %>$location.path('/login');<% } if (filters.uirouter) { %>$state.go('login');<% } %> - } - }); + if (next.authenticate) { + Auth.isLoggedIn(function(loggedIn) { + if (!loggedIn) { + event.preventDefault(); + <% if (filters.ngroute) { %>$location.path('/login');<% } if (filters.uirouter) { %>$state.go('login');<% } %> + } + }); + } }); })<% } %>; From 49b2535f65080b458cd5d90b57c54114da3bd418 Mon Sep 17 00:00:00 2001 From: kingcody Date: Fri, 14 Aug 2015 09:02:12 -0400 Subject: [PATCH 0193/1357] refactor(gen): switch fs-extra to node fs --- Gruntfile.js | 10 +++------- package.json | 1 - test/test-file-creation.js | 8 +++++--- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index befea75e5..e5c4e1768 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -6,7 +6,7 @@ var shell = require('shelljs'); var child_process = require('child_process'); var Q = require('q'); var helpers = require('yeoman-generator').test; -var fs = require('fs-extra'); +var fs = require('fs'); var path = require('path'); module.exports = function (grunt) { @@ -218,7 +218,6 @@ module.exports = function (grunt) { }); grunt.registerTask('updateFixtures', 'updates package and bower fixtures', function() { - var done = this.async(); var packageJson = fs.readFileSync(path.resolve('app/templates/_package.json'), 'utf8'); var bowerJson = fs.readFileSync(path.resolve('app/templates/_bower.json'), 'utf8'); @@ -231,11 +230,8 @@ module.exports = function (grunt) { bowerJson = bowerJson.replace(/<%(.*)%>/g, ''); // save files - fs.writeFile(path.resolve(__dirname + '/test/fixtures/package.json'), packageJson, function() { - fs.writeFile(path.resolve(__dirname + '/test/fixtures/bower.json'), bowerJson, function() { - done(); - }); - }); + fs.writeFileSync(path.resolve(__dirname + '/test/fixtures/package.json'), packageJson); + fs.writeFileSync(path.resolve(__dirname + '/test/fixtures/bower.json'), bowerJson); }); grunt.registerTask('installFixtures', 'install package and bower fixtures', function() { diff --git a/package.json b/package.json index 7dfa26f05..94377188d 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,6 @@ }, "devDependencies": { "chai": "^1.9.1", - "fs-extra": "^0.9.1", "grunt": "~0.4.1", "grunt-build-control": "DaftMonk/grunt-build-control", "grunt-contrib-clean": "^0.6.0", diff --git a/test/test-file-creation.js b/test/test-file-creation.js index fb0fb2b91..db5750900 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -1,7 +1,7 @@ /*global describe, beforeEach, it */ 'use strict'; var path = require('path'); -var fs = require('fs-extra'); +var fs = require('fs'); var exec = require('child_process').exec; var helpers = require('yeoman-generator').test; var chai = require('chai'); @@ -25,6 +25,8 @@ describe('angular-fullstack generator', function () { socketio: true }, dependenciesInstalled = false; + function copySync(s, d) { fs.writeFileSync(d, fs.readFileSync(s)); } + function generatorTest(generatorType, name, mockPrompt, callback) { gen.run(function () { var afGenerator; @@ -442,7 +444,7 @@ describe('angular-fullstack generator', function () { it('should use existing config if available', function(done) { this.timeout(60000); - fs.copySync(__dirname + '/fixtures/.yo-rc.json', __dirname + '/temp/.yo-rc.json'); + copySync(__dirname + '/fixtures/.yo-rc.json', __dirname + '/temp/.yo-rc.json'); var gen = helpers.createGenerator('angular-fullstack:app', [ '../../app', '../../endpoint', @@ -467,7 +469,7 @@ describe('angular-fullstack generator', function () { it('should add oauth option if existing config had oauth strategy selected', function(done) { this.timeout(60000); - fs.copySync(__dirname + '/fixtures/.yo-rc.json', __dirname + '/temp/.yo-rc.json'); + copySync(__dirname + '/fixtures/.yo-rc.json', __dirname + '/temp/.yo-rc.json'); var gen = helpers.createGenerator('angular-fullstack:app', [ '../../app', '../../endpoint', From 973d38c0947e236fc715a01bef90820aac254a13 Mon Sep 17 00:00:00 2001 From: kingcody Date: Fri, 14 Aug 2015 09:19:48 -0400 Subject: [PATCH 0194/1357] feat(gen): implement jit-grunt --- Gruntfile.js | 6 +++++- package.json | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index e5c4e1768..f67a88c57 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -10,7 +10,11 @@ var fs = require('fs'); var path = require('path'); module.exports = function (grunt) { - require('load-grunt-tasks')(grunt); + // Load grunt tasks automatically, when needed + require('jit-grunt')(grunt, { + buildcontrol: 'grunt-build-control', + changelog: 'grunt-conventional-changelog' + }); grunt.initConfig({ config: { diff --git a/package.json b/package.json index 94377188d..f95dbef65 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "grunt-env": "^0.4.1", "grunt-mocha-test": "^0.11.0", "grunt-release": "~0.6.0", - "load-grunt-tasks": "~0.2.0", + "jit-grunt": "^0.9.1", "marked": "~0.2.8", "mocha": "~1.21.0", "q": "^1.0.1", From 2916a1dfe54d0a44e1d730ca780d6a38c0b12e67 Mon Sep 17 00:00:00 2001 From: kingcody Date: Fri, 14 Aug 2015 10:37:51 -0400 Subject: [PATCH 0195/1357] chore(gen): update generator task dependencies --- Gruntfile.js | 3 +-- package.json | 19 +++++++++---------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index f67a88c57..38fc08efc 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,7 +1,6 @@ 'use strict'; -var markdown = require('marked'); + var semver = require('semver'); -var _s = require('underscore.string'); var shell = require('shelljs'); var child_process = require('child_process'); var Q = require('q'); diff --git a/package.json b/package.json index f95dbef65..219b9349b 100644 --- a/package.json +++ b/package.json @@ -26,29 +26,28 @@ "test": "grunt test" }, "dependencies": { - "chalk": "~0.4.0", + "chalk": "^1.1.0", "generator-ng-component": "~0.1.0", "yeoman-generator": "~0.18.10" }, "devDependencies": { - "chai": "^1.9.1", + "chai": "^3.2.0", "grunt": "~0.4.1", - "grunt-build-control": "DaftMonk/grunt-build-control", + "grunt-build-control": "^0.5.0", "grunt-contrib-clean": "^0.6.0", "grunt-contrib-jshint": "^0.11.2", "grunt-conventional-changelog": "~1.0.0", "grunt-david": "~0.5.0", "grunt-env": "^0.4.1", - "grunt-mocha-test": "^0.11.0", - "grunt-release": "~0.6.0", + "grunt-mocha-test": "^0.12.7", + "grunt-release": "^0.13.0", "jit-grunt": "^0.9.1", - "marked": "~0.2.8", - "mocha": "~1.21.0", + "mocha": "^2.2.5", "q": "^1.0.1", "recursive-readdir": "^1.2.0", - "semver": "~2.2.1", - "shelljs": "^0.3.0", - "underscore.string": "^2.3.3" + "semver": "^5.0.1", + "shelljs": "^0.5.3", + "underscore.string": "^3.1.1" }, "engines": { "node": ">=0.10.0", From c708e0c178dce7c0ca07e43fda825d46d25f8b03 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Fri, 14 Aug 2015 16:53:54 -0400 Subject: [PATCH 0196/1357] 3.0.0-rc1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 219b9349b..ff7c96f5c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "generator-angular-fullstack", - "version": "2.1.1", + "version": "3.0.0-rc1", "description": "Yeoman generator for creating MEAN stack applications, using MongoDB, Express, AngularJS, and Node", "keywords": [ "yeoman-generator", From e1c9ca3e581b8527583e8e9ad255a4c064d3dad9 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Fri, 14 Aug 2015 17:03:49 -0400 Subject: [PATCH 0197/1357] 3.0.0-rc2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ff7c96f5c..63d5b7d85 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "generator-angular-fullstack", - "version": "3.0.0-rc1", + "version": "3.0.0-rc2", "description": "Yeoman generator for creating MEAN stack applications, using MongoDB, Express, AngularJS, and Node", "keywords": [ "yeoman-generator", From aa6047e23f9252d5e69cf69be99aa505dd027ca6 Mon Sep 17 00:00:00 2001 From: kingcody Date: Thu, 13 Aug 2015 08:26:53 -0400 Subject: [PATCH 0198/1357] chore(dependencies): update grunt dependencies Changes: * `grunt-contrib-watch` now uses `spawn: false` instead of `nospawn: true` @see https://github.com/gruntjs/grunt-contrib-watch#optionsspawn * `grunt-contrib-imagemin` now minifies svg files, remove `grunt-svgmin` @see https://github.com/gruntjs/grunt-contrib-imagemin#imagemin-task --- app/templates/Gruntfile.js | 18 +++---------- app/templates/_package.json | 51 ++++++++++++++++++------------------- 2 files changed, 28 insertions(+), 41 deletions(-) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index c9d5568aa..070aff36d 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -128,7 +128,7 @@ module.exports = function (grunt) { tasks: ['express:dev', 'wait'], options: { livereload: true, - nospawn: true //Without this option specified express won't be reloaded + spawn: false //Without this option specified express won't be reloaded } }, bower: { @@ -309,18 +309,7 @@ module.exports = function (grunt) { files: [{ expand: true, cwd: '<%%= yeoman.client %>/assets/images', - src: '{,*/}*.{png,jpg,jpeg,gif}', - dest: '<%%= yeoman.dist %>/client/assets/images' - }] - } - }, - - svgmin: { - dist: { - files: [{ - expand: true, - cwd: '<%%= yeoman.client %>/assets/images', - src: '{,*/}*.svg', + src: '{,*/}*.{png,jpg,jpeg,gif,svg}', dest: '<%%= yeoman.dist %>/client/assets/images' }] } @@ -468,8 +457,7 @@ module.exports = function (grunt) { 'stylus',<% } if(filters.sass) { %> 'sass',<% } if(filters.less) { %> 'less',<% } %> - 'imagemin', - 'svgmin' + 'imagemin' ] }, diff --git a/app/templates/_package.json b/app/templates/_package.json index 7d061fe3b..f37d674b1 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -35,44 +35,42 @@ }, "devDependencies": { "autoprefixer-core": "^5.2.1", - "grunt": "~0.4.4", + "grunt": "~0.4.5", "grunt-wiredep": "^2.0.0", - "grunt-concurrent": "~0.5.0", - "grunt-contrib-clean": "~0.5.0", - "grunt-contrib-concat": "~0.4.0", - "grunt-contrib-copy": "~0.5.0", - "grunt-contrib-cssmin": "~0.9.0", - "grunt-contrib-htmlmin": "~0.2.0", - "grunt-contrib-imagemin": "~0.7.1", + "grunt-concurrent": "^2.0.1", + "grunt-contrib-clean": "^0.6.0", + "grunt-contrib-concat": "^0.5.1", + "grunt-contrib-copy": "^0.8.0", + "grunt-contrib-cssmin": "^0.13.0", + "grunt-contrib-imagemin": "^0.9.4", "grunt-contrib-jshint": "~0.11.2", - "grunt-contrib-uglify": "~0.4.0", + "grunt-contrib-uglify": "^0.9.1", "grunt-contrib-watch": "~0.6.1",<% if (filters.coffee) { %> - "grunt-contrib-coffee": "^0.10.1",<% } %><% if (filters.jade) { %> - "grunt-contrib-jade": "^0.11.0",<% } %><% if (filters.less) { %> - "grunt-contrib-less": "^0.11.4",<% } %><% if(filters.babel) { %> + "grunt-contrib-coffee": "^0.13.0",<% } %><% if (filters.jade) { %> + "grunt-contrib-jade": "^0.15.0",<% } %><% if (filters.less) { %> + "grunt-contrib-less": "^1.0.0",<% } %><% if(filters.babel) { %> "karma-babel-preprocessor": "^5.2.1", "grunt-babel": "~5.0.0",<% } %> "grunt-google-cdn": "~0.4.0", - "grunt-jscs": "~0.7.1", - "grunt-newer": "~0.7.0", - "grunt-ng-annotate": "^0.2.3", + "grunt-jscs": "^2.0.0", + "grunt-newer": "^1.1.1", + "grunt-ng-annotate": "^1.0.1", "grunt-filerev": "^2.3.1", - "grunt-svgmin": "~0.4.0", - "grunt-usemin": "~2.1.1", + "grunt-usemin": "^3.0.0", "grunt-env": "~0.4.1", - "grunt-node-inspector": "~0.1.5", - "grunt-nodemon": "~0.2.0", + "grunt-node-inspector": "^0.2.0", + "grunt-nodemon": "^0.4.0", "grunt-angular-templates": "^0.5.4", "grunt-dom-munger": "^3.4.0", "grunt-protractor-runner": "^2.0.0", - "grunt-injector": "~0.5.4", + "grunt-injector": "^0.6.0", "grunt-karma": "~0.12.0", - "grunt-build-control": "~0.4.0",<% if(filters.sass) { %> - "grunt-contrib-sass": "^0.7.3",<% } %><% if(filters.stylus) { %> + "grunt-build-control": "^0.5.0",<% if(filters.sass) { %> + "grunt-contrib-sass": "^0.9.0",<% } %><% if(filters.stylus) { %> "grunt-contrib-stylus": "latest",<% } %> - "jit-grunt": "^0.5.0", - "time-grunt": "~0.3.1", - "grunt-express-server": "~0.4.17", + "jit-grunt": "^0.9.1", + "time-grunt": "^1.2.1", + "grunt-express-server": "^0.5.1", "grunt-postcss": "^0.5.5", "grunt-open": "~0.2.3", "open": "~0.0.4", @@ -80,7 +78,8 @@ "connect-livereload": "^0.5.3", "mocha": "^2.2.5", "grunt-mocha-test": "~0.12.7", - "grunt-mocha-istanbul": "^2.4.0", + "grunt-mocha-istanbul": "^3.0.1", + "istanbul": "^0.3.17", "chai-as-promised": "^5.1.0", "chai-things": "^0.2.0", "sinon-chai": "^2.8.0",<% if (filters.mocha) { %> From 0017b6fee26d21d29fd5f082bea8418f336a5643 Mon Sep 17 00:00:00 2001 From: kingcody Date: Fri, 14 Aug 2015 21:49:09 -0400 Subject: [PATCH 0199/1357] fix(app): babel watches all client (non-spec) js for changes --- app/templates/Gruntfile.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 070aff36d..b67e1825a 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -54,13 +54,17 @@ module.exports = function (grunt) { url: 'http://localhost:<%%= express.options.port %>' } }, - watch: { + watch: {<% if(filters.babel) { %> + babel: { + files: ['<%%= yeoman.client %>/{app,components}/**/!(*.spec|*.mock).js'], + tasks: ['newer:babel:client'] + },<% } %> injectJS: { files: [ '<%%= yeoman.client %>/{app,components}/**/!(*.spec|*.mock).js', '!<%%= yeoman.client %>/app/app.js' ], - tasks: [<% if(filters.babel) { %>'newer:babel:client', <% } %>'injector:scripts'] + tasks: ['injector:scripts'] }, injectCss: { files: ['<%%= yeoman.client %>/{app,components}/**/*.css'], From a22847de6a48e8c29628cd304726de375dfe1e60 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sat, 15 Aug 2015 15:39:17 -0400 Subject: [PATCH 0200/1357] 3.0.0-rc3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 63d5b7d85..54ae8127f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "generator-angular-fullstack", - "version": "3.0.0-rc2", + "version": "3.0.0-rc3", "description": "Yeoman generator for creating MEAN stack applications, using MongoDB, Express, AngularJS, and Node", "keywords": [ "yeoman-generator", From a7cdf29b4f87b7a009a9bbc5a738ed604ff5c4be Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Fri, 14 Aug 2015 15:57:16 -0400 Subject: [PATCH 0201/1357] feat(express): add express-sequelize-session --- app/templates/_package.json | 3 ++- app/templates/server/config/express.js | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 35c2c6c74..725b466ba 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -20,7 +20,8 @@ "bluebird": "^2.9.34", "connect-mongo": "^0.8.1",<% } %><% if (filters.sequelize) { %> "sequelize": "^3.5.1", - "sqlite3": "~3.0.2",<% } %><% if (filters.auth) { %> + "sqlite3": "~3.0.2", + "express-sequelize-session": "0.4.0",<% } %><% if (filters.auth) { %> "jsonwebtoken": "^5.0.0", "express-jwt": "^3.0.0", "passport": "~0.2.0", diff --git a/app/templates/server/config/express.js b/app/templates/server/config/express.js index 3cd2f2739..39a62312c 100644 --- a/app/templates/server/config/express.js +++ b/app/templates/server/config/express.js @@ -17,7 +17,9 @@ var config = require('./environment');<% if (filters.auth) { %> var passport = require('passport');<% } %><% if (filters.twitterAuth) { %> var session = require('express-session');<% if (filters.mongoose) { %> var mongoStore = require('connect-mongo')(session); -var mongoose = require('mongoose');<% } %><% } %> +var mongoose = require('mongoose');<% } else if(filters.sequelize) { %> +var sqldb = require('../sqldb'); +var Store = require('express-sequelize-session')(session.Store);<% } %><% } %> module.exports = function(app) { var env = app.get('env'); @@ -42,7 +44,8 @@ module.exports = function(app) { store: new mongoStore({ mongooseConnection: mongoose.connection, db: '<%= _.slugify(_.humanize(appname)) %>' - })<% } %> + })<% } else if(filters.sequelize) { %>, + store: new Store(sqldb.sequelize)<% } %> })); <% } %> app.set('appPath', path.join(config.root, 'client')); From 908f869db3c00b93187afcaddbb1174a1fdc0831 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Thu, 13 Aug 2015 15:32:28 -0400 Subject: [PATCH 0202/1357] feat(server): add lusca --- app/templates/_package.json | 1 + app/templates/server/config/express.js | 31 +++++++++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 725b466ba..57c862aaa 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -13,6 +13,7 @@ "compression": "~1.0.1", "composable-middleware": "^0.3.0", "lodash": "~2.4.1", + "lusca": "1.3.0", "babel-core": "^5.6.4",<% if (filters.jade) { %> "jade": "~1.2.0",<% } %><% if (filters.html) { %> "ejs": "~0.8.4",<% } %><% if (filters.mongoose) { %> diff --git a/app/templates/server/config/express.js b/app/templates/server/config/express.js index 39a62312c..b6f37009e 100644 --- a/app/templates/server/config/express.js +++ b/app/templates/server/config/express.js @@ -13,13 +13,14 @@ var methodOverride = require('method-override'); var cookieParser = require('cookie-parser'); var errorHandler = require('errorhandler'); var path = require('path'); +var lusca = require('lusca'); var config = require('./environment');<% if (filters.auth) { %> -var passport = require('passport');<% } %><% if (filters.twitterAuth) { %> +var passport = require('passport');<% } %> var session = require('express-session');<% if (filters.mongoose) { %> var mongoStore = require('connect-mongo')(session); var mongoose = require('mongoose');<% } else if(filters.sequelize) { %> var sqldb = require('../sqldb'); -var Store = require('express-sequelize-session')(session.Store);<% } %><% } %> +var Store = require('express-sequelize-session')(session.Store);<% } %> module.exports = function(app) { var env = app.get('env'); @@ -33,10 +34,11 @@ module.exports = function(app) { app.use(bodyParser.json()); app.use(methodOverride()); app.use(cookieParser());<% if (filters.auth) { %> - app.use(passport.initialize());<% } %><% if (filters.twitterAuth) { %> + app.use(passport.initialize());<% } %> // Persist sessions with mongoStore / sequelizeStore - // We need to enable sessions for passport twitter because its an oauth 1.0 strategy + // We need to enable sessions for passport-twitter because it's an + // oauth 1.0 strategy, and Lusca depends on sessions app.use(session({ secret: config.secrets.session, resave: true, @@ -47,7 +49,26 @@ module.exports = function(app) { })<% } else if(filters.sequelize) { %>, store: new Store(sqldb.sequelize)<% } %> })); -<% } %> + + /** + * Lusca - express server security + * https://github.com/krakenjs/lusca + */ + if ('test' !== env) { + app.use(lusca({ + csrf: { + angular: true + }, + xframe: 'SAMEORIGIN', + hsts: { + maxAge: 31536000, //1 year, in seconds + includeSubDomains: true, + preload: true + }, + xssProtection: true + })); + } + app.set('appPath', path.join(config.root, 'client')); if ('production' === env) { From cc9cbcc4b7df758c9e8e98851a3e7006f3a5faa6 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 16 Aug 2015 02:28:22 -0400 Subject: [PATCH 0203/1357] chore(gen): update generated .travis.yml and package.json node target to 0.12 --- app/templates/.travis.yml | 3 +-- app/templates/_package.json | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/templates/.travis.yml b/app/templates/.travis.yml index 5e8066dc8..c12f57edb 100644 --- a/app/templates/.travis.yml +++ b/app/templates/.travis.yml @@ -1,7 +1,6 @@ language: node_js node_js: - - '0.10' - - '0.11' + - '0.12' before_script: - npm install -g bower grunt-cli<% if (filters.sass) { %> - gem install sass<% } %> diff --git a/app/templates/_package.json b/app/templates/_package.json index 725b466ba..53b4e9824 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -107,7 +107,7 @@ "supertest": "~0.11.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.12.0" }, "scripts": { "start": "node server", From ca7fb10829e2f56ae3d43fb155645f1c33c8a969 Mon Sep 17 00:00:00 2001 From: kingcody Date: Sun, 16 Aug 2015 02:32:21 -0400 Subject: [PATCH 0204/1357] chore(gen): bump node requirements to `>=0.12.0` --- app/templates/README.md | 2 +- app/templates/_package.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/templates/README.md b/app/templates/README.md index e49273a90..958834120 100644 --- a/app/templates/README.md +++ b/app/templates/README.md @@ -7,7 +7,7 @@ This project was generated with the [Angular Full-Stack Generator](https://githu ### Prerequisites - [Git](https://git-scm.com/) -- [Node.js and NPM](nodejs.org) >= v0.10.0 +- [Node.js and NPM](nodejs.org) >= v0.12.0 - [Bower](bower.io) (`npm install --global bower`)<% if(filters.sass) { %> - [Ruby](https://www.ruby-lang.org) and then `gem install sass`<% } if(filters.grunt) { %> - [Grunt](http://gruntjs.com/) (`npm install --global grunt-cli`)<% } if(filters.gulp) { %> diff --git a/app/templates/_package.json b/app/templates/_package.json index 725b466ba..53b4e9824 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -107,7 +107,7 @@ "supertest": "~0.11.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.12.0" }, "scripts": { "start": "node server", diff --git a/package.json b/package.json index 54ae8127f..353fcbfdd 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "underscore.string": "^3.1.1" }, "engines": { - "node": ">=0.10.0", + "node": ">=0.12.0", "npm": ">=1.2.10" }, "license": "BSD-2-Clause" From b7c91acebf48684d33235f5e3f83963b442ed236 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Mon, 17 Aug 2015 10:38:48 -0400 Subject: [PATCH 0205/1357] 3.0.0-rc4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 353fcbfdd..ccfcd3ff6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "generator-angular-fullstack", - "version": "3.0.0-rc3", + "version": "3.0.0-rc4", "description": "Yeoman generator for creating MEAN stack applications, using MongoDB, Express, AngularJS, and Node", "keywords": [ "yeoman-generator", From ad267383cfe3653846bc9fa8dcb5f7fe318c839b Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 19 Aug 2015 08:14:31 -0400 Subject: [PATCH 0206/1357] chore(gen): update fixtures config --- test/fixtures/.yo-rc.json | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/test/fixtures/.yo-rc.json b/test/fixtures/.yo-rc.json index a26821115..01d568984 100644 --- a/test/fixtures/.yo-rc.json +++ b/test/fixtures/.yo-rc.json @@ -1,20 +1,36 @@ { "generator-angular-fullstack": { - "insertRoutes": "true", + "endpointDirectory": "server/api/", + "insertRoutes": true, "registerRoutesFile": "server/routes.js", "routesNeedle": "// Insert routes below", - "insertSockets": "true", + "routesBase": "/api/", + "pluralizeRoutes": true, + "insertSockets": true, "registerSocketsFile": "server/config/socketio.js", "socketsNeedle": "// Insert sockets below", + "insertModels": true, + "registerModelsFile": "server/sqldb/index.js", + "modelsNeedle": "// Insert models below", "filters": { "coffee": true, "html": true, "less": true, "uirouter": true, + "bootstrap": false, + "uibootstrap": false, "socketio": true, - "mongoose": true, "auth": true, - "googleAuth": true + "models": true, + "mongooseModels": true, + "mongoose": true, + "oauth": true, + "googleAuth": true, + "grunt": true, + "mocha": true, + "jasmine": false, + "should": true, + "expect": false } } } From baeff6ca497dbbcaea61ad289fa08e99b3c48900 Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 19 Aug 2015 08:20:52 -0400 Subject: [PATCH 0207/1357] chore(gen): remove migration code and test --- app/index.js | 9 --------- test/test-file-creation.js | 22 ---------------------- 2 files changed, 31 deletions(-) diff --git a/app/index.js b/app/index.js index 50ec1deed..ec954aa46 100644 --- a/app/index.js +++ b/app/index.js @@ -61,15 +61,6 @@ var AngularFullstackGenerator = yeoman.generators.Base.extend({ jasmine: true }); - // NOTE: temp(?) fix for #403 - if(typeof this.filters.oauth === 'undefined') { - var strategies = Object.keys(this.filters).filter(function(key) { - return key.match(/Auth$/) && this.filters[key]; - }.bind(this)); - - if(strategies.length) this.filters.oauth = true; - } - this.config.set('filters', this.filters); this.config.forceSave(); diff --git a/test/test-file-creation.js b/test/test-file-creation.js index db5750900..7850fc9e4 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -467,28 +467,6 @@ describe('angular-fullstack generator', function () { }); }); - it('should add oauth option if existing config had oauth strategy selected', function(done) { - this.timeout(60000); - copySync(__dirname + '/fixtures/.yo-rc.json', __dirname + '/temp/.yo-rc.json'); - var gen = helpers.createGenerator('angular-fullstack:app', [ - '../../app', - '../../endpoint', - [ - helpers.createDummyGenerator(), - 'ng-component:app' - ] - ]); - gen.options['skip-install'] = true; - helpers.mockPrompt(gen, { - skipConfig: true - }); - gen.run(function () { - var yoConfig = require(__dirname + '/temp/.yo-rc.json'); - expect(yoConfig['generator-angular-fullstack'].filters.oauth).to.be.true; - done(); - }); - }); - it('should generate expected files', function (done) { gen.run(function () { helpers.assertFile(genFiles(defaultOptions)); From dbc43e9bf1357650f965c90d181ac8470b90dc2f Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 19 Aug 2015 08:25:54 -0400 Subject: [PATCH 0208/1357] fix(test): require `server` instead of `server/app.js` --- app/templates/server/api/user(auth)/user.integration.js | 2 +- .../server/api/user(auth)/user.model.spec(mongooseModels).js | 2 +- .../server/api/user(auth)/user.model.spec(sequelizeModels).js | 2 +- endpoint/templates/basename.integration.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/templates/server/api/user(auth)/user.integration.js b/app/templates/server/api/user(auth)/user.integration.js index 5273be72a..19978ce48 100644 --- a/app/templates/server/api/user(auth)/user.integration.js +++ b/app/templates/server/api/user(auth)/user.integration.js @@ -1,6 +1,6 @@ 'use strict'; -var app = require('../../app');<% if (filters.mongooseModels) { %> +var app = require('../..');<% if (filters.mongooseModels) { %> var User = require('./user.model');<% } %><% if (filters.sequelizeModels) { %> var User = require('../../sqldb').User;<% } %> var request = require('supertest'); diff --git a/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js b/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js index 1aad3b25e..099e4d5c6 100644 --- a/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js +++ b/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js @@ -1,6 +1,6 @@ 'use strict'; -var app = require('../../app'); +var app = require('../..'); var User = require('./user.model'); var user; var genUser = function() { diff --git a/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js b/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js index a7af1bd38..7e0ca0cc4 100644 --- a/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js +++ b/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js @@ -1,6 +1,6 @@ 'use strict'; -var app = require('../../app'); +var app = require('../..'); var User = require('../../sqldb').User; var user; var genUser = function() { diff --git a/endpoint/templates/basename.integration.js b/endpoint/templates/basename.integration.js index bcd3fd407..067898d72 100644 --- a/endpoint/templates/basename.integration.js +++ b/endpoint/templates/basename.integration.js @@ -1,6 +1,6 @@ 'use strict'; -var app = require('<%= relativeRequire('server/app') %>'); +var app = require('<%= relativeRequire('server') %>'); var request = require('supertest');<% if(filters.models) { %> var new<%= classedName %>;<% } %> From 1855265dc3d5b4956b7069d49b2b5e8c1a61e42f Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 19 Aug 2015 16:48:37 -0400 Subject: [PATCH 0209/1357] fix(tests): only use livereload for development --- app/templates/server/config/express.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/templates/server/config/express.js b/app/templates/server/config/express.js index 39a62312c..aa32be65a 100644 --- a/app/templates/server/config/express.js +++ b/app/templates/server/config/express.js @@ -56,8 +56,11 @@ module.exports = function(app) { app.use(morgan('dev')); } - if ('development' === env || 'test' === env) { + if ('development' === env) { app.use(require('connect-livereload')()); + } + + if ('development' === env || 'test' === env) { app.use(express.static(path.join(config.root, '.tmp'))); app.use(express.static(app.get('appPath'))); app.use(morgan('dev')); From d0d1cf383894a59f304b76cad41281c5ba65666e Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Sun, 2 Nov 2014 17:08:57 +0000 Subject: [PATCH 0210/1357] refactor(data): Change seed user account emails to example.com Privately registered domain names such as admin.com should not be used in seed or test data. Change the email address of the 'test' and 'admin' user accounts to 'test@example.com' and 'admin@example.com' respectively. --- app/templates/client/app/account(auth)/login/login(html).html | 4 ++-- app/templates/client/app/account(auth)/login/login(jade).jade | 4 ++-- app/templates/e2e/account(auth)/login/login.spec(jasmine).js | 2 +- app/templates/e2e/account(auth)/login/login.spec(mocha).js | 2 +- .../e2e/account(auth)/logout/logout.spec(jasmine).js | 2 +- app/templates/e2e/account(auth)/logout/logout.spec(mocha).js | 2 +- .../e2e/account(auth)/signup/signup.spec(jasmine).js | 2 +- app/templates/e2e/account(auth)/signup/signup.spec(mocha).js | 2 +- app/templates/server/api/user(auth)/user.integration.js | 4 ++-- .../server/api/user(auth)/user.model.spec(mongooseModels).js | 2 +- .../server/api/user(auth)/user.model.spec(sequelizeModels).js | 2 +- app/templates/server/config/seed(models).js | 4 ++-- 12 files changed, 16 insertions(+), 16 deletions(-) diff --git a/app/templates/client/app/account(auth)/login/login(html).html b/app/templates/client/app/account(auth)/login/login(html).html index 667ecdd0e..df13e5ef2 100644 --- a/app/templates/client/app/account(auth)/login/login(html).html +++ b/app/templates/client/app/account(auth)/login/login(html).html @@ -4,8 +4,8 @@

Login

-

Accounts are reset on server restart from server/config/seed.js. Default account is test@test.com / test

-

Admin account is admin@admin.com / admin

+

Accounts are reset on server restart from server/config/seed.js. Default account is test@example.com / test

+

Admin account is admin@example.com / admin

diff --git a/app/templates/client/app/account(auth)/login/login(jade).jade b/app/templates/client/app/account(auth)/login/login(jade).jade index e7ce91916..7ef7c0134 100644 --- a/app/templates/client/app/account(auth)/login/login(jade).jade +++ b/app/templates/client/app/account(auth)/login/login(jade).jade @@ -7,12 +7,12 @@ navbar | Accounts are reset on server restart from code server/config/seed.js | . Default account is - code test@test.com + code test@example.com | / code test p | Admin account is - code admin@admin.com + code admin@example.com | / code admin diff --git a/app/templates/e2e/account(auth)/login/login.spec(jasmine).js b/app/templates/e2e/account(auth)/login/login.spec(jasmine).js index 6875376bc..568074ccc 100644 --- a/app/templates/e2e/account(auth)/login/login.spec(jasmine).js +++ b/app/templates/e2e/account(auth)/login/login.spec(jasmine).js @@ -14,7 +14,7 @@ describe('Login View', function() { var testUser = { name: 'Test User', - email: 'test@test.com', + email: 'test@example.com', password: 'test' }; diff --git a/app/templates/e2e/account(auth)/login/login.spec(mocha).js b/app/templates/e2e/account(auth)/login/login.spec(mocha).js index a33970e67..ea511e5fc 100644 --- a/app/templates/e2e/account(auth)/login/login.spec(mocha).js +++ b/app/templates/e2e/account(auth)/login/login.spec(mocha).js @@ -14,7 +14,7 @@ describe('Login View', function() { var testUser = { name: 'Test User', - email: 'test@test.com', + email: 'test@example.com', password: 'test' }; diff --git a/app/templates/e2e/account(auth)/logout/logout.spec(jasmine).js b/app/templates/e2e/account(auth)/logout/logout.spec(jasmine).js index cb727f2c5..37c5e375a 100644 --- a/app/templates/e2e/account(auth)/logout/logout.spec(jasmine).js +++ b/app/templates/e2e/account(auth)/logout/logout.spec(jasmine).js @@ -12,7 +12,7 @@ describe('Logout View', function() { var testUser = { name: 'Test User', - email: 'test@test.com', + email: 'test@example.com', password: 'test' }; diff --git a/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js b/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js index 1e969ccf2..510117fb7 100644 --- a/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js +++ b/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js @@ -12,7 +12,7 @@ describe('Logout View', function() { var testUser = { name: 'Test User', - email: 'test@test.com', + email: 'test@example.com', password: 'test' }; diff --git a/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js b/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js index e0a1230d5..29193d97f 100644 --- a/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js +++ b/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js @@ -15,7 +15,7 @@ describe('Signup View', function() { var testUser = { name: 'Test', - email: 'test@test.com', + email: 'test@example.com', password: 'test' }; diff --git a/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js b/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js index c0bade616..934123881 100644 --- a/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js +++ b/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js @@ -15,7 +15,7 @@ describe('Signup View', function() { var testUser = { name: 'Test', - email: 'test@test.com', + email: 'test@example.com', password: 'test' }; diff --git a/app/templates/server/api/user(auth)/user.integration.js b/app/templates/server/api/user(auth)/user.integration.js index 5273be72a..348931ee7 100644 --- a/app/templates/server/api/user(auth)/user.integration.js +++ b/app/templates/server/api/user(auth)/user.integration.js @@ -15,7 +15,7 @@ describe('User API:', function() { <% if (filters.mongooseModels) { %>user = new User({<% } if (filters.sequelizeModels) { %>user = User.build({<% } %> name: 'Fake User', - email: 'test@test.com', + email: 'test@example.com', password: 'password' }); @@ -37,7 +37,7 @@ describe('User API:', function() { request(app) .post('/auth/local') .send({ - email: 'test@test.com', + email: 'test@example.com', password: 'password' }) .expect(200) diff --git a/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js b/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js index 1aad3b25e..2cc60dff2 100644 --- a/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js +++ b/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js @@ -7,7 +7,7 @@ var genUser = function() { user = new User({ provider: 'local', name: 'Fake User', - email: 'test@test.com', + email: 'test@example.com', password: 'password' }); return user; diff --git a/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js b/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js index a7af1bd38..de7e84035 100644 --- a/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js +++ b/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js @@ -7,7 +7,7 @@ var genUser = function() { user = User.build({ provider: 'local', name: 'Fake User', - email: 'test@test.com', + email: 'test@example.com', password: 'password' }); return user; diff --git a/app/templates/server/config/seed(models).js b/app/templates/server/config/seed(models).js index 20ba6b0f2..374278125 100644 --- a/app/templates/server/config/seed(models).js +++ b/app/templates/server/config/seed(models).js @@ -60,13 +60,13 @@ var Thing = sqldb.Thing; if (filters.sequelizeModels) { %>User.bulkCreate([{<% } %> provider: 'local', name: 'Test User', - email: 'test@test.com', + email: 'test@example.com', password: 'test' }, { provider: 'local', role: 'admin', name: 'Admin', - email: 'admin@admin.com', + email: 'admin@example.com', password: 'admin' <% if (filters.mongooseModels) { %>})<% } if (filters.sequelizeModels) { %>}])<% } %> From 930b108d8e8c803e47fcbfef0dcf09028305e4d0 Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 25 Aug 2015 07:09:01 -0400 Subject: [PATCH 0211/1357] fix(app): remove pre generated thing endpoint require statements --- app/templates/server/config/socketio(socketio).js | 2 +- app/templates/server/routes.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/templates/server/config/socketio(socketio).js b/app/templates/server/config/socketio(socketio).js index 92f629729..dbd117851 100644 --- a/app/templates/server/config/socketio(socketio).js +++ b/app/templates/server/config/socketio(socketio).js @@ -18,7 +18,7 @@ function onConnect(socket) { }); // Insert sockets below - require('../api/thing/thing.socket').register(socket); + } module.exports = function(socketio) { diff --git a/app/templates/server/routes.js b/app/templates/server/routes.js index 8330b35fe..23e902765 100644 --- a/app/templates/server/routes.js +++ b/app/templates/server/routes.js @@ -9,8 +9,7 @@ var path = require('path'); module.exports = function(app) { - // Insert routes below - app.use('/api/things', require('./api/thing'));<% if (filters.auth) { %> + // Insert routes below<% if (filters.auth) { %> app.use('/api/users', require('./api/user')); app.use('/auth', require('./auth')); From 2b28e07e4093edd0e07440f6bc23e3c7e5116a22 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 25 Aug 2015 11:00:33 -0400 Subject: [PATCH 0212/1357] refactor(admin:controller): use User.query keep parity with JS file --- .../client/app/admin(auth)/admin.controller(coffee).coffee | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/templates/client/app/admin(auth)/admin.controller(coffee).coffee b/app/templates/client/app/admin(auth)/admin.controller(coffee).coffee index 5183df059..4bdef336a 100644 --- a/app/templates/client/app/admin(auth)/admin.controller(coffee).coffee +++ b/app/templates/client/app/admin(auth)/admin.controller(coffee).coffee @@ -3,9 +3,7 @@ angular.module '<%= scriptAppName %>' .controller 'AdminCtrl', ($scope, $http, Auth, User) -> - $http.get '/api/users' - .success (users) -> - $scope.users = users + $scope.users = User.query $scope.delete = (user) -> User.remove id: user._id From 353f5e5027244880508634d93c339d8400012d13 Mon Sep 17 00:00:00 2001 From: Jinyoung Kim Date: Tue, 25 Aug 2015 22:50:24 +0900 Subject: [PATCH 0213/1357] refactor($http): change legacy promise to standard `success` and `error` promise have been deprecated. --- app/templates/client/app/main/main.controller(coffee).coffee | 4 ++-- app/templates/client/app/main/main.controller(js).js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/templates/client/app/main/main.controller(coffee).coffee b/app/templates/client/app/main/main.controller(coffee).coffee index 4b04a951b..fdd03c644 100644 --- a/app/templates/client/app/main/main.controller(coffee).coffee +++ b/app/templates/client/app/main/main.controller(coffee).coffee @@ -4,8 +4,8 @@ angular.module '<%= scriptAppName %>' .controller 'MainCtrl', ($scope, $http<% if (filters.socketio) { %>, socket<% } %>) -> $scope.awesomeThings = [] - $http.get('/api/things').success (awesomeThings) -> - $scope.awesomeThings = awesomeThings + $http.get('/api/things').then (response) -> + $scope.awesomeThings = response.data <% if (filters.socketio) { %>socket.syncUpdates 'thing', $scope.awesomeThings<% } %> <% if (filters.models) { %> $scope.addThing = -> diff --git a/app/templates/client/app/main/main.controller(js).js b/app/templates/client/app/main/main.controller(js).js index 345d9909d..91ba5d131 100644 --- a/app/templates/client/app/main/main.controller(js).js +++ b/app/templates/client/app/main/main.controller(js).js @@ -4,8 +4,8 @@ angular.module('<%= scriptAppName %>') .controller('MainCtrl', function($scope, $http<% if (filters.socketio) { %>, socket<% } %>) { $scope.awesomeThings = []; - $http.get('/api/things').success(function(awesomeThings) { - $scope.awesomeThings = awesomeThings;<% if (filters.socketio) { %> + $http.get('/api/things').then(function(response) { + $scope.awesomeThings = response.data;<% if (filters.socketio) { %> socket.syncUpdates('thing', $scope.awesomeThings);<% } %> }); <% if (filters.models) { %> From 6c441e39578c7804baea3f996be11d7f9bf96f9b Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 25 Aug 2015 16:40:02 -0400 Subject: [PATCH 0214/1357] fix(admin:controller): fix coffeescript function execution --- .../client/app/admin(auth)/admin.controller(coffee).coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/client/app/admin(auth)/admin.controller(coffee).coffee b/app/templates/client/app/admin(auth)/admin.controller(coffee).coffee index 4bdef336a..04af43178 100644 --- a/app/templates/client/app/admin(auth)/admin.controller(coffee).coffee +++ b/app/templates/client/app/admin(auth)/admin.controller(coffee).coffee @@ -3,7 +3,7 @@ angular.module '<%= scriptAppName %>' .controller 'AdminCtrl', ($scope, $http, Auth, User) -> - $scope.users = User.query + $scope.users = User.query() $scope.delete = (user) -> User.remove id: user._id From 3f85a4a2f5eff5db239daddb7a00ee4e047df1cd Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 26 Aug 2015 04:47:07 -0400 Subject: [PATCH 0215/1357] fix(gen): relativeRequire always returns posix style paths --- util.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/util.js b/util.js index 6657cfc9f..adf494d96 100644 --- a/util.js +++ b/util.js @@ -88,8 +88,9 @@ function relativeRequire (self, to, fr) { fr = destinationPath(self, fr); to = destinationPath(self, to); return path.relative(path.dirname(fr), to) - .replace(/^(?!\.\.)(.*)/, './$1') - .replace(/[\/\\]index\.js$/, ''); + .replace(/\\/g, '/') // convert win32 separator to posix + .replace(/^(?!\.\.)(.*)/, './$1') // prefix non parent path with ./ + .replace(/[\/\\]index\.js$/, ''); // strip index.js suffix from path } function filterFile (template) { From fd6bfe9d4829f3fe907b28e6a3e4ad2b1e699dd6 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Thu, 27 Aug 2015 00:53:44 -0400 Subject: [PATCH 0216/1357] 3.0.0-rc5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ccfcd3ff6..7c401ec46 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "generator-angular-fullstack", - "version": "3.0.0-rc4", + "version": "3.0.0-rc5", "description": "Yeoman generator for creating MEAN stack applications, using MongoDB, Express, AngularJS, and Node", "keywords": [ "yeoman-generator", From fbdb39473cdab4d88f6faeb7a21392744a36d1f6 Mon Sep 17 00:00:00 2001 From: Rex Schrader Date: Thu, 27 Aug 2015 10:09:55 -0700 Subject: [PATCH 0217/1357] fix(wiredep): only exclude bootstrap.js when ui-bootstrap is chosen Fixes #565 --- app/templates/Gruntfile.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 666681a89..fb5675cfd 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -248,8 +248,8 @@ module.exports = function (grunt) { // Automatically inject Bower components into the app and karma.conf.js wiredep: { options: { - exclude: [ - /bootstrap.js/, + exclude: [ <% if(filters.uibootstrap) { %> + /bootstrap.js/,<% } %> '/json3/', '/es5-shim/'<% if(!filters.css) { %>, /font-awesome\.css/<% if(filters.bootstrap) { %>, From 7b9cf3d81b95c067988515dfaf2232ab5e41c704 Mon Sep 17 00:00:00 2001 From: kingcody Date: Sat, 29 Aug 2015 04:06:42 -0400 Subject: [PATCH 0218/1357] fix(app): include `client/*.html` in usemin html glob --- app/templates/Gruntfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index fb5675cfd..5e56ff203 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -290,7 +290,7 @@ module.exports = function (grunt) { // Performs rewrites based on rev and the useminPrepare configuration usemin: { - html: ['<%%= yeoman.dist %>/client/!(bower_components){,*/}*.html'], + html: ['<%%= yeoman.dist %>/client/{,!(bower_components)/**/}*.html'], css: ['<%%= yeoman.dist %>/client/!(bower_components){,*/}*.css'], js: ['<%%= yeoman.dist %>/client/!(bower_components){,*/}*.js'], options: { From 22bb524789efef1c6569e02d5d58cd767ca743cf Mon Sep 17 00:00:00 2001 From: kingcody Date: Sun, 30 Aug 2015 03:16:27 -0400 Subject: [PATCH 0219/1357] fix(auth): setTokenCookie sets token as string closes #1022 --- app/templates/server/auth(auth)/auth.service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/server/auth(auth)/auth.service.js b/app/templates/server/auth(auth)/auth.service.js index 8c100e84b..6cd885313 100644 --- a/app/templates/server/auth(auth)/auth.service.js +++ b/app/templates/server/auth(auth)/auth.service.js @@ -84,7 +84,7 @@ function setTokenCookie(req, res) { return res.status(404).send('Something went wrong, please try again.'); } var token = signToken(req.user._id, req.user.role); - res.cookie('token', JSON.stringify(token)); + res.cookie('token', token); res.redirect('/'); } From dd7d41fcb8fd4316fe77884152157f4e35e1799d Mon Sep 17 00:00:00 2001 From: kingcody Date: Mon, 31 Aug 2015 04:11:35 -0400 Subject: [PATCH 0220/1357] chore(dependencies): update app dev dependencies --- app/templates/_package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 53b4e9824..4065fcd7d 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -72,7 +72,7 @@ "jit-grunt": "^0.9.1", "time-grunt": "^1.2.1", "grunt-express-server": "^0.5.1", - "grunt-postcss": "^0.5.5", + "grunt-postcss": "^0.6.0", "grunt-open": "~0.2.3", "open": "~0.0.4", "jshint-stylish": "~2.0.1", @@ -104,7 +104,7 @@ "karma-ng-html2js-preprocessor": "~0.1.2", "karma-spec-reporter": "~0.0.20", "proxyquire": "^1.0.1", - "supertest": "~0.11.0" + "supertest": "^1.1.0" }, "engines": { "node": ">=0.12.0" From 348cb6399c208e2d3a33032ee4ac55480fe6a257 Mon Sep 17 00:00:00 2001 From: fcagalj Date: Mon, 31 Aug 2015 22:35:55 +0200 Subject: [PATCH 0221/1357] refactor(heroku): change instructions for creating mongoDB after deploying to heroku Change instructions to use method "heroku addons:create" instead of deprecated "heroku addons:add" for adding MongoDB after deploying to heroku. Suggest useing free mongoLab DB instead of charged mongoHQ (now called Compose MongoDB). BREAKING CHANGE: Change console output after deploying process is finished: Before: 'heroku addons:add mongohq' After: 'heroku addons:create mongolab' Closes #1222 --- heroku/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/heroku/index.js b/heroku/index.js index 3c34f37b0..689833d26 100644 --- a/heroku/index.js +++ b/heroku/index.js @@ -158,7 +158,7 @@ Generator.prototype.gitForcePush = function gitForcePush() { var hasWarning = false; if(this.filters.mongoose) { - this.log(chalk.yellow('\nBecause you\'re using mongoose, you must add mongoDB to your heroku app.\n\t' + 'from `/dist`: ' + chalk.bold('heroku addons:add mongohq') + '\n')); + this.log(chalk.yellow('\nBecause you\'re using mongoose, you must add mongoDB to your heroku app.\n\t' + 'from `/dist`: ' + chalk.bold('heroku addons:create mongolab') + '\n')); hasWarning = true; } From b10ca44c56298cad2d108373f5094898550339ad Mon Sep 17 00:00:00 2001 From: kingcody Date: Sun, 30 Aug 2015 01:37:39 -0400 Subject: [PATCH 0222/1357] chore(dependencies): update app dependencies --- app/templates/_package.json | 30 +++++++++---------- .../server/api/user(auth)/user.controller.js | 1 - app/templates/server/config/express.js | 1 - 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 5345f2d5f..67760246d 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -3,20 +3,20 @@ "version": "0.0.0", "main": "server/app.js", "dependencies": { - "express": "~4.9.0", - "morgan": "~1.0.0", - "body-parser": "~1.5.0", - "method-override": "~1.0.0", - "cookie-parser": "~1.0.1", - "express-session": "~1.0.2", - "errorhandler": "~1.0.0", - "compression": "~1.0.1", + "express": "^4.13.3", + "morgan": "~1.6.1", + "body-parser": "^1.13.3", + "method-override": "^2.3.5", + "cookie-parser": "^1.3.5", + "express-session": "^1.11.3", + "errorhandler": "^1.4.2", + "compression": "^1.5.2", "composable-middleware": "^0.3.0", - "lodash": "~2.4.1", - "lusca": "1.3.0", + "lodash": "^3.10.1", + "lusca": "^1.3.0", "babel-core": "^5.6.4",<% if (filters.jade) { %> - "jade": "~1.2.0",<% } %><% if (filters.html) { %> - "ejs": "~0.8.4",<% } %><% if (filters.mongoose) { %> + "jade": "^1.11.0",<% } %><% if (filters.html) { %> + "ejs": "^2.3.3",<% } %><% if (filters.mongoose) { %> "mongoose": "^4.1.2", "bluebird": "^2.9.34", "connect-mongo": "^0.8.1",<% } %><% if (filters.sequelize) { %> @@ -25,15 +25,15 @@ "express-sequelize-session": "0.4.0",<% } %><% if (filters.auth) { %> "jsonwebtoken": "^5.0.0", "express-jwt": "^3.0.0", - "passport": "~0.2.0", - "passport-local": "~0.1.6",<% } %><% if (filters.facebookAuth) { %> + "passport": "~0.3.0", + "passport-local": "^1.0.0",<% } %><% if (filters.facebookAuth) { %> "passport-facebook": "latest",<% } %><% if (filters.twitterAuth) { %> "passport-twitter": "latest",<% } %><% if (filters.googleAuth) { %> "passport-google-oauth": "latest",<% } %><% if (filters.socketio) { %> "socket.io": "^1.3.5", "socket.io-client": "^1.3.5", "socketio-jwt": "^4.2.0",<% } %> - "serve-favicon": "~2.0.1" + "serve-favicon": "^2.3.0" }, "devDependencies": { "autoprefixer-core": "^5.2.1", diff --git a/app/templates/server/api/user(auth)/user.controller.js b/app/templates/server/api/user(auth)/user.controller.js index f1c2498fb..059216b4c 100644 --- a/app/templates/server/api/user(auth)/user.controller.js +++ b/app/templates/server/api/user(auth)/user.controller.js @@ -1,7 +1,6 @@ 'use strict'; <% if (filters.mongooseModels) { %> var User = require('./user.model');<% } %><% if (filters.sequelizeModels) { %> -var _ = require('lodash'); var sqldb = require('../../sqldb'); var User = sqldb.User;<% } %> var passport = require('passport'); diff --git a/app/templates/server/config/express.js b/app/templates/server/config/express.js index ed88b6474..de7505759 100644 --- a/app/templates/server/config/express.js +++ b/app/templates/server/config/express.js @@ -41,7 +41,6 @@ module.exports = function(app) { // oauth 1.0 strategy, and Lusca depends on sessions app.use(session({ secret: config.secrets.session, - resave: true, saveUninitialized: true<% if (filters.mongoose) { %>, store: new mongoStore({ mongooseConnection: mongoose.connection, From bb713bfb988f092e62808748bc8214b025ef37d6 Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 1 Sep 2015 03:14:38 -0400 Subject: [PATCH 0223/1357] fix(gen): templateIsUsable uses self.filters by default closes #1232 --- util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util.js b/util.js index adf494d96..0490a228a 100644 --- a/util.js +++ b/util.js @@ -108,7 +108,7 @@ function filterFile (template) { } function templateIsUsable (self, filteredFile) { - var filters = self.config.get('filters'); + var filters = self.filters || self.config.get('filters'); var enabledFilters = []; for(var key in filters) { if(filters[key]) enabledFilters.push(key); From 2b80a3b455fa016c7311ecbe6e09b0295977d77a Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 1 Sep 2015 04:01:32 -0400 Subject: [PATCH 0224/1357] feat(gen): endpoint uses model default for prompt --- endpoint/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/endpoint/index.js b/endpoint/index.js index cbb8d5aeb..f92517436 100644 --- a/endpoint/index.js +++ b/endpoint/index.js @@ -84,6 +84,7 @@ Generator.prototype.prompting = function askFor() { name: 'models', message: 'What would you like to use for the endpoint\'s models?', choices: [ 'Mongoose', 'Sequelize' ], + default: self.filters.sequelizeModels ? 1 : 0, filter: function( val ) { return val.toLowerCase(); }, From 9513589c020067481df571322cc1f5303c875f37 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 1 Sep 2015 12:02:15 -0400 Subject: [PATCH 0225/1357] refactor(server:auth): use import syntax --- app/templates/server/auth(auth)/auth.service.js | 14 +++++++------- .../auth(auth)/facebook(facebookAuth)/index.js | 6 +++--- .../auth(auth)/facebook(facebookAuth)/passport.js | 4 ++-- .../server/auth(auth)/google(googleAuth)/index.js | 6 +++--- .../auth(auth)/google(googleAuth)/passport.js | 4 ++-- app/templates/server/auth(auth)/index.js | 10 +++++----- app/templates/server/auth(auth)/local/index.js | 6 +++--- app/templates/server/auth(auth)/local/passport.js | 4 ++-- .../auth(auth)/twitter(twitterAuth)/index.js | 6 +++--- .../auth(auth)/twitter(twitterAuth)/passport.js | 6 +++--- 10 files changed, 33 insertions(+), 33 deletions(-) diff --git a/app/templates/server/auth(auth)/auth.service.js b/app/templates/server/auth(auth)/auth.service.js index 6cd885313..edd16506a 100644 --- a/app/templates/server/auth(auth)/auth.service.js +++ b/app/templates/server/auth(auth)/auth.service.js @@ -1,12 +1,12 @@ 'use strict'; -var passport = require('passport'); -var config = require('../config/environment'); -var jwt = require('jsonwebtoken'); -var expressJwt = require('express-jwt'); -var compose = require('composable-middleware');<% if (filters.mongooseModels) { %> -var User = require('../api/user/user.model');<% } %><% if (filters.sequelizeModels) { %> -var User = require('../sqldb').User;<% } %> +import passport from 'passport'; +import config from '../config/environment'; +import jwt from 'jsonwebtoken'; +import expressJwt from 'express-jwt'; +import compose from 'composable-middleware';<% if (filters.mongooseModels) { %> +import User from '../api/user/user.model';<% } %><% if (filters.sequelizeModels) { %> +import {User} from'../sqldb';<% } %> var validateJwt = expressJwt({ secret: config.secrets.session }); diff --git a/app/templates/server/auth(auth)/facebook(facebookAuth)/index.js b/app/templates/server/auth(auth)/facebook(facebookAuth)/index.js index f13d463e1..3605cba5b 100644 --- a/app/templates/server/auth(auth)/facebook(facebookAuth)/index.js +++ b/app/templates/server/auth(auth)/facebook(facebookAuth)/index.js @@ -1,8 +1,8 @@ 'use strict'; -var express = require('express'); -var passport = require('passport'); -var auth = require('../auth.service'); +import express from 'express'; +import passport from 'passport'; +import auth from '../auth.service'; var router = express.Router(); diff --git a/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js b/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js index 00b87a226..341e46535 100644 --- a/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js +++ b/app/templates/server/auth(auth)/facebook(facebookAuth)/passport.js @@ -1,5 +1,5 @@ -var passport = require('passport'); -var FacebookStrategy = require('passport-facebook').Strategy; +import passport from 'passport'; +import {Strategy as FacebookStrategy} from 'passport-facebook'; exports.setup = function(User, config) { passport.use(new FacebookStrategy({ diff --git a/app/templates/server/auth(auth)/google(googleAuth)/index.js b/app/templates/server/auth(auth)/google(googleAuth)/index.js index 7789def92..906493e7d 100644 --- a/app/templates/server/auth(auth)/google(googleAuth)/index.js +++ b/app/templates/server/auth(auth)/google(googleAuth)/index.js @@ -1,8 +1,8 @@ 'use strict'; -var express = require('express'); -var passport = require('passport'); -var auth = require('../auth.service'); +import express from 'express'; +import passport from 'passport'; +import auth from '../auth.service'; var router = express.Router(); diff --git a/app/templates/server/auth(auth)/google(googleAuth)/passport.js b/app/templates/server/auth(auth)/google(googleAuth)/passport.js index f74594c12..97abc3fdf 100644 --- a/app/templates/server/auth(auth)/google(googleAuth)/passport.js +++ b/app/templates/server/auth(auth)/google(googleAuth)/passport.js @@ -1,5 +1,5 @@ -var passport = require('passport'); -var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy; +import passport from 'passport'; +import {OAuth2Strategy as GoogleStrategy} from 'passport-google-oauth'; exports.setup = function(User, config) { passport.use(new GoogleStrategy({ diff --git a/app/templates/server/auth(auth)/index.js b/app/templates/server/auth(auth)/index.js index 75ddfdcb8..513a403b1 100644 --- a/app/templates/server/auth(auth)/index.js +++ b/app/templates/server/auth(auth)/index.js @@ -1,10 +1,10 @@ 'use strict'; -var express = require('express'); -var passport = require('passport'); -var config = require('../config/environment');<% if (filters.mongooseModels) { %> -var User = require('../api/user/user.model');<% } %><% if (filters.sequelizeModels) { %> -var User = require('../sqldb').User;<% } %> +import express from 'express'; +import passport from 'passport'; +import config from '../config/environment';<% if (filters.mongooseModels) { %> +import User from '../api/user/user.model';<% } %><% if (filters.sequelizeModels) { %> +import {User} from '../sqldb';<% } %> // Passport Configuration require('./local/passport').setup(User, config);<% if (filters.facebookAuth) { %> diff --git a/app/templates/server/auth(auth)/local/index.js b/app/templates/server/auth(auth)/local/index.js index e94d0da1a..62ccc4204 100644 --- a/app/templates/server/auth(auth)/local/index.js +++ b/app/templates/server/auth(auth)/local/index.js @@ -1,8 +1,8 @@ 'use strict'; -var express = require('express'); -var passport = require('passport'); -var auth = require('../auth.service'); +import express from 'express'; +import passport from 'passport'; +import auth from '../auth.service'; var router = express.Router(); diff --git a/app/templates/server/auth(auth)/local/passport.js b/app/templates/server/auth(auth)/local/passport.js index 2bd3366f8..df12bf45a 100644 --- a/app/templates/server/auth(auth)/local/passport.js +++ b/app/templates/server/auth(auth)/local/passport.js @@ -1,5 +1,5 @@ -var passport = require('passport'); -var LocalStrategy = require('passport-local').Strategy; +import passport from 'passport'; +import {Strategy as LocalStrategy} from 'passport-local'; function localAuthenticate(User, email, password, done) { <% if (filters.mongooseModels) { %>User.findOneAsync({ diff --git a/app/templates/server/auth(auth)/twitter(twitterAuth)/index.js b/app/templates/server/auth(auth)/twitter(twitterAuth)/index.js index 8e6f32b5d..1810eadc1 100644 --- a/app/templates/server/auth(auth)/twitter(twitterAuth)/index.js +++ b/app/templates/server/auth(auth)/twitter(twitterAuth)/index.js @@ -1,8 +1,8 @@ 'use strict'; -var express = require('express'); -var passport = require('passport'); -var auth = require('../auth.service'); +import express from 'express'; +import passport from 'passport'; +import auth from '../auth.service'; var router = express.Router(); diff --git a/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js b/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js index bf23bd3ba..8c7f341be 100644 --- a/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js +++ b/app/templates/server/auth(auth)/twitter(twitterAuth)/passport.js @@ -1,7 +1,7 @@ -exports.setup = function(User, config) { - var passport = require('passport'); - var TwitterStrategy = require('passport-twitter').Strategy; +import passport from 'passport'; +import {Strategy as TwitterStrategy} from 'passport-twitter'; +exports.setup = function(User, config) { passport.use(new TwitterStrategy({ consumerKey: config.twitter.clientID, consumerSecret: config.twitter.clientSecret, From c1fd93f95b1d25adff0771dcd136437d540081a2 Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 1 Sep 2015 04:26:56 -0400 Subject: [PATCH 0226/1357] feat(app): improved socket.io logging --- app/templates/server/config/socketio(socketio).js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/templates/server/config/socketio(socketio).js b/app/templates/server/config/socketio(socketio).js index dbd117851..e83d9262c 100644 --- a/app/templates/server/config/socketio(socketio).js +++ b/app/templates/server/config/socketio(socketio).js @@ -14,7 +14,7 @@ function onDisconnect(socket) { function onConnect(socket) { // When the client emits 'info', this listens and executes socket.on('info', function(data) { - console.info('[%s] %s', socket.address, JSON.stringify(data, null, 2)); + socket.log(JSON.stringify(data, null, 2)); }); // Insert sockets below @@ -43,14 +43,18 @@ module.exports = function(socketio) { socket.connectedAt = new Date(); + socket.log = function(...data) { + console.log(`SocketIO ${socket.nsp.name} [${socket.address}]`, ...data); + }; + // Call onDisconnect. socket.on('disconnect', function() { onDisconnect(socket); - console.info('[%s] DISCONNECTED', socket.address); + socket.log('DISCONNECTED'); }); // Call onConnect. onConnect(socket); - console.info('[%s] CONNECTED', socket.address); + socket.log('CONNECTED'); }); }; From 8e0ab2d88aff9c2ccbc8c461db54bb059882d1cd Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 1 Sep 2015 12:13:51 -0400 Subject: [PATCH 0227/1357] refactor(server:config): use import syntax --- app/templates/server/config/express.js | 36 ++++++++++--------- app/templates/server/config/seed(models).js | 16 ++++----- .../server/config/socketio(socketio).js | 2 +- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/app/templates/server/config/express.js b/app/templates/server/config/express.js index de7505759..e8748499b 100644 --- a/app/templates/server/config/express.js +++ b/app/templates/server/config/express.js @@ -4,23 +4,25 @@ 'use strict'; -var express = require('express'); -var favicon = require('serve-favicon'); -var morgan = require('morgan'); -var compression = require('compression'); -var bodyParser = require('body-parser'); -var methodOverride = require('method-override'); -var cookieParser = require('cookie-parser'); -var errorHandler = require('errorhandler'); -var path = require('path'); -var lusca = require('lusca'); -var config = require('./environment');<% if (filters.auth) { %> -var passport = require('passport');<% } %> -var session = require('express-session');<% if (filters.mongoose) { %> -var mongoStore = require('connect-mongo')(session); -var mongoose = require('mongoose');<% } else if(filters.sequelize) { %> -var sqldb = require('../sqldb'); -var Store = require('express-sequelize-session')(session.Store);<% } %> +import express from 'express'; +import favicon from 'serve-favicon'; +import morgan from 'morgan'; +import compression from 'compression'; +import bodyParser from 'body-parser'; +import methodOverride from 'method-override'; +import cookieParser from 'cookie-parser'; +import errorHandler from 'errorhandler'; +import path from 'path'; +import lusca from 'lusca'; +import config from './environment';<% if (filters.auth) { %> +import passport from 'passport';<% } %> +import session from 'express-session';<% if (filters.mongoose) { %> +import connectMongo from 'connect-mongo'; +import mongoose from 'mongoose'; +var mongoStore = connectMongo(session);<% } else if(filters.sequelize) { %> +import sqldb from '../sqldb'; +import expressSequelizeSession from 'express-sequelize-session'; +var Store = expressSequelizeSession(session.Store);<% } %> module.exports = function(app) { var env = app.get('env'); diff --git a/app/templates/server/config/seed(models).js b/app/templates/server/config/seed(models).js index 374278125..a0e5edb76 100644 --- a/app/templates/server/config/seed(models).js +++ b/app/templates/server/config/seed(models).js @@ -3,15 +3,13 @@ * to disable, edit config/environment/index.js, and set `seedDB: false` */ -'use strict'; -<% if (filters.mongooseModels) { %> -var Thing = require('../api/thing/thing.model'); -<% if (filters.auth) { %>var User = require('../api/user/user.model');<% } %> -<% } %><% if (filters.sequelizeModels) { %> -var sqldb = require('../sqldb'); -var Thing = sqldb.Thing; -<% if (filters.auth) { %>var User = sqldb.User;<% } %> -<% } %> +'use strict';<% if (filters.mongooseModels) { %> +import Thing from '../api/thing/thing.model';<% if (filters.auth) { %> +import User from '../api/user/user.model';<% } %><% } %><% if (filters.sequelizeModels) { %> +import sqldb from '../sqldb'; +var Thing = sqldb.Thing;<% if (filters.auth) { %> +var User = sqldb.User;<% } %><% } %> + <% if (filters.mongooseModels) { %>Thing.find({}).removeAsync()<% } if (filters.sequelizeModels) { %>Thing.sync() .then(function() { diff --git a/app/templates/server/config/socketio(socketio).js b/app/templates/server/config/socketio(socketio).js index dbd117851..0035b55fe 100644 --- a/app/templates/server/config/socketio(socketio).js +++ b/app/templates/server/config/socketio(socketio).js @@ -4,7 +4,7 @@ 'use strict'; -var config = require('./environment'); +import config from './environment'; // When the user disconnects.. perform this function onDisconnect(socket) { From 9fd53137d62c956c7626e7f0a2d263beb6af4879 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 1 Sep 2015 12:14:20 -0400 Subject: [PATCH 0228/1357] refactor(server:sqldb): use import syntax --- app/templates/server/sqldb(sequelize)/index.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/templates/server/sqldb(sequelize)/index.js b/app/templates/server/sqldb(sequelize)/index.js index 2500a2213..c79688a0e 100644 --- a/app/templates/server/sqldb(sequelize)/index.js +++ b/app/templates/server/sqldb(sequelize)/index.js @@ -4,10 +4,9 @@ 'use strict'; -var path = require('path'); -var config = require('../config/environment'); - -var Sequelize = require('sequelize'); +import path from 'path'; +import config from '../config/environment'; +import Sequelize from 'sequelize'; var db = { Sequelize: Sequelize, From 06fcc18caea2a3a7cfbe3d65257e7ed682a560a5 Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 1 Sep 2015 23:30:12 -0400 Subject: [PATCH 0229/1357] feat(gen): support ES2015 syntax through `babel-core/register` --- app/generator.js | 434 ++++++++++++++++++++++++++++++++++++++++++ app/index.js | 417 +--------------------------------------- endpoint/generator.js | 151 +++++++++++++++ endpoint/index.js | 152 +-------------- package.json | 1 + 5 files changed, 594 insertions(+), 561 deletions(-) create mode 100644 app/generator.js create mode 100644 endpoint/generator.js diff --git a/app/generator.js b/app/generator.js new file mode 100644 index 000000000..517773bc8 --- /dev/null +++ b/app/generator.js @@ -0,0 +1,434 @@ +'use strict'; + +import fs from 'fs'; +import path from 'path'; +import genUtils from '../util.js'; +import {Base} from 'yeoman-generator'; +import chalk from 'chalk'; + +export default class Generator extends Base { + + constructor(...args) { + super(...args); + + this.argument('name', { type: String, required: false }); + this.option('app-suffix', { + desc: 'Allow a custom suffix to be added to the module name', + type: String, + required: 'false' + }); + } + + get initializing() { + return { + + init: function () { + this.appname = this.name || path.basename(process.cwd()); + this.appname = this._.camelize(this._.slugify(this._.humanize(this.appname))); + + this.scriptAppName = this.appname + genUtils.appName(this); + console.log(this.scriptAppName); + this.appPath = this.env.options.appPath; + this.pkg = require('../package.json'); + + this.filters = {}; + + // dynamic assertion statements + this.expect = function() { + return this.filters.expect ? 'expect(' : ''; + }.bind(this); + this.to = function() { + return this.filters.expect ? ').to' : '.should'; + }.bind(this); + }, + + info: function () { + this.log(this.welcome); + this.log('Out of the box I create an AngularJS app with an Express server.\n'); + }, + + checkForConfig: function() { + var cb = this.async(); + + if(this.config.get('filters')) { + this.prompt([{ + type: 'confirm', + name: 'skipConfig', + message: 'Existing .yo-rc configuration found, would you like to use it?', + default: true, + }], function (answers) { + this.skipConfig = answers.skipConfig; + + this.filters = this._.defaults(this.config.get('filters'), { + bootstrap: true, + uibootstrap: true, + jasmine: true + }); + + this.config.set('filters', this.filters); + this.config.forceSave(); + + cb(); + }.bind(this)); + } else { + cb(); + } + } + + }; + } + + get prompting() { + return { + + clientPrompts: function() { + if(this.skipConfig) return; + var cb = this.async(); + + this.log('# Client\n'); + + this.prompt([{ + type: 'list', + name: 'script', + message: 'What would you like to write scripts with?', + choices: [ 'JavaScript', 'JavaScript + Babel', 'CoffeeScript'], + filter: function( val ) { + return { + 'JavaScript': 'js', + 'JavaScript + Babel': 'babel', + 'CoffeeScript': 'coffee' + }[val]; + } + }, { + type: 'list', + name: 'markup', + message: 'What would you like to write markup with?', + choices: ['HTML', 'Jade'], + filter: function( val ) { return val.toLowerCase(); } + }, { + type: 'list', + name: 'stylesheet', + default: 1, + message: 'What would you like to write stylesheets with?', + choices: [ 'CSS', 'Sass', 'Stylus', 'Less'], + filter: function( val ) { return val.toLowerCase(); } + }, { + type: 'list', + name: 'router', + default: 1, + message: 'What Angular router would you like to use?', + choices: [ 'ngRoute', 'uiRouter'], + filter: function( val ) { return val.toLowerCase(); } + }, { + type: 'confirm', + name: 'bootstrap', + message: 'Would you like to include Bootstrap?' + }, { + type: 'confirm', + name: 'uibootstrap', + message: 'Would you like to include UI Bootstrap?', + when: function (answers) { + return answers.bootstrap; + } + }], function (answers) { + + // also set 'js' to true if using babel + if(answers.script === 'babel') { this.filters.js = true; } + this.filters[answers.script] = true; + this.filters[answers.markup] = true; + this.filters[answers.stylesheet] = true; + this.filters[answers.router] = true; + this.filters.bootstrap = !!answers.bootstrap; + this.filters.uibootstrap = !!answers.uibootstrap; + cb(); + }.bind(this)); + }, + + serverPrompts: function() { + if(this.skipConfig) return; + var cb = this.async(); + var self = this; + + this.log('\n# Server\n'); + + this.prompt([{ + type: 'checkbox', + name: 'odms', + message: 'What would you like to use for data modeling?', + choices: [ + { + value: 'mongoose', + name: 'Mongoose (MongoDB)', + checked: true + }, + { + value: 'sequelize', + name: 'Sequelize (MySQL, SQLite, MariaDB, PostgreSQL)', + checked: false + } + ] + }, { + type: 'list', + name: 'models', + message: 'What would you like to use for the default models?', + choices: [ 'Mongoose', 'Sequelize' ], + filter: function( val ) { + return val.toLowerCase(); + }, + when: function(answers) { + return answers.odms && answers.odms.length > 1; + } + }, { + type: 'confirm', + name: 'auth', + message: 'Would you scaffold out an authentication boilerplate?', + when: function (answers) { + return answers.odms && answers.odms.length !== 0; + } + }, { + type: 'checkbox', + name: 'oauth', + message: 'Would you like to include additional oAuth strategies?', + when: function (answers) { + return answers.auth; + }, + choices: [ + { + value: 'googleAuth', + name: 'Google', + checked: false + }, + { + value: 'facebookAuth', + name: 'Facebook', + checked: false + }, + { + value: 'twitterAuth', + name: 'Twitter', + checked: false + } + ] + }, { + type: 'confirm', + name: 'socketio', + message: 'Would you like to use socket.io?', + // to-do: should not be dependent on ODMs + when: function (answers) { + return answers.odms && answers.odms.length !== 0; + }, + default: true + }], function (answers) { + if(answers.socketio) this.filters.socketio = true; + if(answers.auth) this.filters.auth = true; + if(answers.odms && answers.odms.length > 0) { + var models; + if(!answers.models) { + models = answers.odms[0]; + } else { + models = answers.models; + } + this.filters.models = true; + this.filters[models + 'Models'] = true; + answers.odms.forEach(function(odm) { + this.filters[odm] = true; + }.bind(this)); + } else { + this.filters.noModels = true; + } + if(answers.oauth) { + if(answers.oauth.length) this.filters.oauth = true; + answers.oauth.forEach(function(oauthStrategy) { + this.filters[oauthStrategy] = true; + }.bind(this)); + } + + cb(); + }.bind(this)); + }, + + projectPrompts: function() { + if(this.skipConfig) return; + var cb = this.async(); + var self = this; + + this.log('\n# Project\n'); + + this.prompt([{ + type: 'list', + name: 'testing', + message: 'What would you like to write tests with?', + choices: [ 'Jasmine', 'Mocha + Chai + Sinon'], + filter: function( val ) { + var filterMap = { + 'Jasmine': 'jasmine', + 'Mocha + Chai + Sinon': 'mocha' + }; + + return filterMap[val]; + } + }, { + type: 'list', + name: 'chai', + message: 'What would you like to write Chai assertions with?', + choices: ['Expect', 'Should'], + filter: function( val ) { + return val.toLowerCase(); + }, + when: function( answers ) { + return answers.testing === 'mocha'; + } + }], function (answers) { + /** + * Default to grunt until gulp support is implemented + */ + this.filters.grunt = true; + + this.filters[answers.testing] = true; + if (answers.testing === 'mocha') { + this.filters.jasmine = false; + this.filters.should = false; + this.filters.expect = false; + this.filters[answers.chai] = true; + } + if (answers.testing === 'jasmine') { + this.filters.mocha = false; + this.filters.should = false; + this.filters.expect = false; + } + + cb(); + }.bind(this)); + } + + }; + } + + get configuring() { + return { + + saveSettings: function() { + if(this.skipConfig) return; + this.config.set('endpointDirectory', 'server/api/'); + this.config.set('insertRoutes', true); + this.config.set('registerRoutesFile', 'server/routes.js'); + this.config.set('routesNeedle', '// Insert routes below'); + + this.config.set('routesBase', '/api/'); + this.config.set('pluralizeRoutes', true); + + this.config.set('insertSockets', true); + this.config.set('registerSocketsFile', 'server/config/socketio.js'); + this.config.set('socketsNeedle', '// Insert sockets below'); + + this.config.set('insertModels', true); + this.config.set('registerModelsFile', 'server/sqldb/index.js'); + this.config.set('modelsNeedle', '// Insert models below'); + + this.config.set('filters', this.filters); + this.config.forceSave(); + }, + + ngComponent: function() { + if(this.skipConfig) return; + var appPath = 'client/app/'; + var extensions = []; + var filters = [ + 'ngroute', + 'uirouter', + 'jasmine', + 'mocha', + 'expect', + 'should' + ].filter(function(v) {return this.filters[v];}, this); + + if(this.filters.ngroute) filters.push('ngroute'); + if(this.filters.uirouter) filters.push('uirouter'); + if(this.filters.babel) extensions.push('babel'); + if(this.filters.coffee) extensions.push('coffee'); + if(this.filters.js) extensions.push('js'); + if(this.filters.html) extensions.push('html'); + if(this.filters.jade) extensions.push('jade'); + if(this.filters.css) extensions.push('css'); + if(this.filters.stylus) extensions.push('styl'); + if(this.filters.sass) extensions.push('scss'); + if(this.filters.less) extensions.push('less'); + + this.composeWith('ng-component', { + options: { + 'routeDirectory': appPath, + 'directiveDirectory': appPath, + 'filterDirectory': appPath, + 'serviceDirectory': appPath, + 'filters': filters, + 'extensions': extensions, + 'basePath': 'client' + } + }, { local: require.resolve('generator-ng-component/app/index.js') }); + }, + + ngModules: function() { + var angModules = [ + "'ngCookies'", + "'ngResource'", + "'ngSanitize'" + ]; + if(this.filters.ngroute) angModules.push("'ngRoute'"); + if(this.filters.socketio) angModules.push("'btford.socket-io'"); + if(this.filters.uirouter) angModules.push("'ui.router'"); + if(this.filters.uibootstrap) angModules.push("'ui.bootstrap'"); + + this.angularModules = '\n ' + angModules.join(',\n ') +'\n'; + } + + }; + } + + get default() { + return {}; + } + + get writing() { + return { + + generateProject: function() { + this.sourceRoot(path.join(__dirname, './templates')); + genUtils.processDirectory(this, '.', '.'); + }, + + generateEndpoint: function() { + var models; + if (this.filters.mongooseModels) { + models = 'mongoose'; + } else if (this.filters.sequelizeModels) { + models = 'sequelize'; + } + this.composeWith('angular-fullstack:endpoint', { + options: { + route: '/api/things', + models: models + }, + args: ['thing'] + }); + } + + }; + } + + get install() { + return { + + installDeps: function() { + this.installDependencies({ + skipInstall: this.options['skip-install'] + }); + } + + }; + } + + get end() { + return {}; + } + +} diff --git a/app/index.js b/app/index.js index cd55ab4eb..994cdee97 100644 --- a/app/index.js +++ b/app/index.js @@ -1,416 +1,7 @@ 'use strict'; -var fs = require('fs'); -var path = require('path'); -var util = require('util'); -var genUtils = require('../util.js'); -var yeoman = require('yeoman-generator'); -var chalk = require('chalk'); -var AngularFullstackGenerator = yeoman.generators.Base.extend({ +// Register the Babel require hook +require('babel-core/register'); - initializing: { - - init: function () { - this.argument('name', { type: String, required: false }); - this.appname = this.name || path.basename(process.cwd()); - this.appname = this._.camelize(this._.slugify(this._.humanize(this.appname))); - - this.option('app-suffix', { - desc: 'Allow a custom suffix to be added to the module name', - type: String, - required: 'false' - }); - this.scriptAppName = this.appname + genUtils.appName(this); - this.appPath = this.env.options.appPath; - this.pkg = require('../package.json'); - - this.filters = {}; - - // dynamic assertion statements - this.expect = function() { - return this.filters.expect ? 'expect(' : ''; - }.bind(this); - this.to = function() { - return this.filters.expect ? ').to' : '.should'; - }.bind(this); - }, - - info: function () { - this.log(this.welcome); - this.log('Out of the box I create an AngularJS app with an Express server.\n'); - }, - - checkForConfig: function() { - var cb = this.async(); - - if(this.config.get('filters')) { - this.prompt([{ - type: 'confirm', - name: 'skipConfig', - message: 'Existing .yo-rc configuration found, would you like to use it?', - default: true, - }], function (answers) { - this.skipConfig = answers.skipConfig; - - this.filters = this._.defaults(this.config.get('filters'), { - bootstrap: true, - uibootstrap: true, - jasmine: true - }); - - this.config.set('filters', this.filters); - this.config.forceSave(); - - cb(); - }.bind(this)); - } else { - cb(); - } - } - - }, - - prompting: { - - clientPrompts: function() { - if(this.skipConfig) return; - var cb = this.async(); - - this.log('# Client\n'); - - this.prompt([{ - type: 'list', - name: 'script', - message: 'What would you like to write scripts with?', - choices: [ 'JavaScript', 'JavaScript + Babel', 'CoffeeScript'], - filter: function( val ) { - return { - 'JavaScript': 'js', - 'JavaScript + Babel': 'babel', - 'CoffeeScript': 'coffee' - }[val]; - } - }, { - type: 'list', - name: 'markup', - message: 'What would you like to write markup with?', - choices: ['HTML', 'Jade'], - filter: function( val ) { return val.toLowerCase(); } - }, { - type: 'list', - name: 'stylesheet', - default: 1, - message: 'What would you like to write stylesheets with?', - choices: [ 'CSS', 'Sass', 'Stylus', 'Less'], - filter: function( val ) { return val.toLowerCase(); } - }, { - type: 'list', - name: 'router', - default: 1, - message: 'What Angular router would you like to use?', - choices: [ 'ngRoute', 'uiRouter'], - filter: function( val ) { return val.toLowerCase(); } - }, { - type: 'confirm', - name: 'bootstrap', - message: 'Would you like to include Bootstrap?' - }, { - type: 'confirm', - name: 'uibootstrap', - message: 'Would you like to include UI Bootstrap?', - when: function (answers) { - return answers.bootstrap; - } - }], function (answers) { - - // also set 'js' to true if using babel - if(answers.script === 'babel') { this.filters.js = true; } - this.filters[answers.script] = true; - this.filters[answers.markup] = true; - this.filters[answers.stylesheet] = true; - this.filters[answers.router] = true; - this.filters.bootstrap = !!answers.bootstrap; - this.filters.uibootstrap = !!answers.uibootstrap; - cb(); - }.bind(this)); - }, - - serverPrompts: function() { - if(this.skipConfig) return; - var cb = this.async(); - var self = this; - - this.log('\n# Server\n'); - - this.prompt([{ - type: 'checkbox', - name: 'odms', - message: 'What would you like to use for data modeling?', - choices: [ - { - value: 'mongoose', - name: 'Mongoose (MongoDB)', - checked: true - }, - { - value: 'sequelize', - name: 'Sequelize (MySQL, SQLite, MariaDB, PostgreSQL)', - checked: false - } - ] - }, { - type: 'list', - name: 'models', - message: 'What would you like to use for the default models?', - choices: [ 'Mongoose', 'Sequelize' ], - filter: function( val ) { - return val.toLowerCase(); - }, - when: function(answers) { - return answers.odms && answers.odms.length > 1; - } - }, { - type: 'confirm', - name: 'auth', - message: 'Would you scaffold out an authentication boilerplate?', - when: function (answers) { - return answers.odms && answers.odms.length !== 0; - } - }, { - type: 'checkbox', - name: 'oauth', - message: 'Would you like to include additional oAuth strategies?', - when: function (answers) { - return answers.auth; - }, - choices: [ - { - value: 'googleAuth', - name: 'Google', - checked: false - }, - { - value: 'facebookAuth', - name: 'Facebook', - checked: false - }, - { - value: 'twitterAuth', - name: 'Twitter', - checked: false - } - ] - }, { - type: 'confirm', - name: 'socketio', - message: 'Would you like to use socket.io?', - // to-do: should not be dependent on ODMs - when: function (answers) { - return answers.odms && answers.odms.length !== 0; - }, - default: true - }], function (answers) { - if(answers.socketio) this.filters.socketio = true; - if(answers.auth) this.filters.auth = true; - if(answers.odms && answers.odms.length > 0) { - var models; - if(!answers.models) { - models = answers.odms[0]; - } else { - models = answers.models; - } - this.filters.models = true; - this.filters[models + 'Models'] = true; - answers.odms.forEach(function(odm) { - this.filters[odm] = true; - }.bind(this)); - } else { - this.filters.noModels = true; - } - if(answers.oauth) { - if(answers.oauth.length) this.filters.oauth = true; - answers.oauth.forEach(function(oauthStrategy) { - this.filters[oauthStrategy] = true; - }.bind(this)); - } - - cb(); - }.bind(this)); - }, - - projectPrompts: function() { - if(this.skipConfig) return; - var cb = this.async(); - var self = this; - - this.log('\n# Project\n'); - - this.prompt([{ - type: 'list', - name: 'testing', - message: 'What would you like to write tests with?', - choices: [ 'Jasmine', 'Mocha + Chai + Sinon'], - filter: function( val ) { - var filterMap = { - 'Jasmine': 'jasmine', - 'Mocha + Chai + Sinon': 'mocha' - }; - - return filterMap[val]; - } - }, { - type: 'list', - name: 'chai', - message: 'What would you like to write Chai assertions with?', - choices: ['Expect', 'Should'], - filter: function( val ) { - return val.toLowerCase(); - }, - when: function( answers ) { - return answers.testing === 'mocha'; - } - }], function (answers) { - /** - * Default to grunt until gulp support is implemented - */ - this.filters.grunt = true; - - this.filters[answers.testing] = true; - if (answers.testing === 'mocha') { - this.filters.jasmine = false; - this.filters.should = false; - this.filters.expect = false; - this.filters[answers.chai] = true; - } - if (answers.testing === 'jasmine') { - this.filters.mocha = false; - this.filters.should = false; - this.filters.expect = false; - } - - cb(); - }.bind(this)); - } - - }, - - configuring: { - - saveSettings: function() { - if(this.skipConfig) return; - this.config.set('endpointDirectory', 'server/api/'); - this.config.set('insertRoutes', true); - this.config.set('registerRoutesFile', 'server/routes.js'); - this.config.set('routesNeedle', '// Insert routes below'); - - this.config.set('routesBase', '/api/'); - this.config.set('pluralizeRoutes', true); - - this.config.set('insertSockets', true); - this.config.set('registerSocketsFile', 'server/config/socketio.js'); - this.config.set('socketsNeedle', '// Insert sockets below'); - - this.config.set('insertModels', true); - this.config.set('registerModelsFile', 'server/sqldb/index.js'); - this.config.set('modelsNeedle', '// Insert models below'); - - this.config.set('filters', this.filters); - this.config.forceSave(); - }, - - ngComponent: function() { - if(this.skipConfig) return; - var appPath = 'client/app/'; - var extensions = []; - var filters = [ - 'ngroute', - 'uirouter', - 'jasmine', - 'mocha', - 'expect', - 'should' - ].filter(function(v) {return this.filters[v];}, this); - - if(this.filters.ngroute) filters.push('ngroute'); - if(this.filters.uirouter) filters.push('uirouter'); - if(this.filters.babel) extensions.push('babel'); - if(this.filters.coffee) extensions.push('coffee'); - if(this.filters.js) extensions.push('js'); - if(this.filters.html) extensions.push('html'); - if(this.filters.jade) extensions.push('jade'); - if(this.filters.css) extensions.push('css'); - if(this.filters.stylus) extensions.push('styl'); - if(this.filters.sass) extensions.push('scss'); - if(this.filters.less) extensions.push('less'); - - this.composeWith('ng-component', { - options: { - 'routeDirectory': appPath, - 'directiveDirectory': appPath, - 'filterDirectory': appPath, - 'serviceDirectory': appPath, - 'filters': filters, - 'extensions': extensions, - 'basePath': 'client' - } - }, { local: require.resolve('generator-ng-component/app/index.js') }); - }, - - ngModules: function() { - var angModules = [ - "'ngCookies'", - "'ngResource'", - "'ngSanitize'" - ]; - if(this.filters.ngroute) angModules.push("'ngRoute'"); - if(this.filters.socketio) angModules.push("'btford.socket-io'"); - if(this.filters.uirouter) angModules.push("'ui.router'"); - if(this.filters.uibootstrap) angModules.push("'ui.bootstrap'"); - - this.angularModules = '\n ' + angModules.join(',\n ') +'\n'; - } - - }, - - default: {}, - - writing: { - - generateProject: function() { - this.sourceRoot(path.join(__dirname, './templates')); - genUtils.processDirectory(this, '.', '.'); - }, - - generateEndpoint: function() { - var models; - if (this.filters.mongooseModels) { - models = 'mongoose'; - } else if (this.filters.sequelizeModels) { - models = 'sequelize'; - } - this.composeWith('angular-fullstack:endpoint', { - options: { - route: '/api/things', - models: models - }, - args: ['thing'] - }); - } - - }, - - install: { - - installDeps: function() { - this.installDependencies({ - skipInstall: this.options['skip-install'] - }); - } - - }, - - end: {} - -}); - -module.exports = AngularFullstackGenerator; +// Export the generator +exports = module.exports = require('./generator'); diff --git a/endpoint/generator.js b/endpoint/generator.js new file mode 100644 index 000000000..b4757d743 --- /dev/null +++ b/endpoint/generator.js @@ -0,0 +1,151 @@ +'use strict'; + +import path from 'path'; +import ngUtil from '../util'; +import ScriptBase from '../script-base.js'; + +export default class Generator extends ScriptBase { + + constructor(...args) { + super(...args); + + this.option('route', { + desc: 'URL for the endpoint', + type: String + }); + + this.option('models', { + desc: 'Specify which model(s) to use', + type: String + }); + + this.option('endpointDirectory', { + desc: 'Parent directory for enpoints', + type: String + }); + } + + prompting() { + var done = this.async(); + var promptCb = function (props) { + if(props.route.charAt(0) !== '/') { + props.route = '/' + props.route; + } + + this.route = props.route; + + if (props.models) { + delete this.filters.mongoose; + delete this.filters.mongooseModels; + delete this.filters.sequelize; + delete this.filters.sequelizeModels; + + this.filters[props.models] = true; + this.filters[props.models + 'Models'] = true; + } + done(); + }.bind(this); + + if (this.options.route) { + if (this.filters.mongoose && this.filters.sequelize) { + if (this.options.models) { + return promptCb(this.options); + } + } else { + if (this.filters.mongooseModels) { this.options.models = 'mongoose'; } + else if (this.filters.sequelizeModels) { this.options.models = 'sequelize'; } + else { delete this.options.models; } + return promptCb(this.options); + } + } + + var name = this.name; + + var base = this.config.get('routesBase') || '/api/'; + if(base.charAt(base.length-1) !== '/') { + base = base + '/'; + } + + // pluralization defaults to true for backwards compat + if (this.config.get('pluralizeRoutes') !== false) { + name = name + 's'; + } + + var self = this; + var prompts = [ + { + name: 'route', + message: 'What will the url of your endpoint be?', + default: base + name + }, + { + type: 'list', + name: 'models', + message: 'What would you like to use for the endpoint\'s models?', + choices: [ 'Mongoose', 'Sequelize' ], + default: self.filters.sequelizeModels ? 1 : 0, + filter: function( val ) { + return val.toLowerCase(); + }, + when: function() { + return self.filters.mongoose && self.filters.sequelize; + } + } + ]; + + this.prompt(prompts, promptCb); + } + + configuring() { + this.routeDest = path.join(this.options.endpointDirectory || + this.config.get('endpointDirectory') || 'server/api/', this.name); + } + + writing() { + this.sourceRoot(path.join(__dirname, './templates')); + ngUtil.processDirectory(this, '.', this.routeDest); + } + + end() { + if(this.config.get('insertRoutes')) { + var routesFile = this.config.get('registerRoutesFile'); + var reqPath = this.relativeRequire(this.routeDest, routesFile); + var routeConfig = { + file: routesFile, + needle: this.config.get('routesNeedle'), + splicable: [ + "app.use(\'" + this.route +"\', require(\'" + reqPath + "\'));" + ] + }; + ngUtil.rewriteFile(routeConfig); + } + + if (this.filters.socketio && this.config.get('insertSockets')) { + var socketsFile = this.config.get('registerSocketsFile'); + var reqPath = this.relativeRequire(this.routeDest + '/' + this.basename + + '.socket', socketsFile); + var socketConfig = { + file: socketsFile, + needle: this.config.get('socketsNeedle'), + splicable: [ + "require(\'" + reqPath + "\').register(socket);" + ] + }; + ngUtil.rewriteFile(socketConfig); + } + + if (this.filters.sequelize && this.config.get('insertModels')) { + var modelsFile = this.config.get('registerModelsFile'); + var reqPath = this.relativeRequire(this.routeDest + '/' + this.basename + + '.model', modelsFile); + var modelConfig = { + file: modelsFile, + needle: this.config.get('modelsNeedle'), + splicable: [ + "db." + this.classedName + " = db.sequelize.import(\'" + reqPath +"\');" + ] + }; + ngUtil.rewriteFile(modelConfig); + } + } +} diff --git a/endpoint/index.js b/endpoint/index.js index f92517436..994cdee97 100644 --- a/endpoint/index.js +++ b/endpoint/index.js @@ -1,151 +1,7 @@ 'use strict'; -var path = require('path'); -var yeoman = require('yeoman-generator'); -var util = require('util'); -var ngUtil = require('../util'); -var ScriptBase = require('../script-base.js'); -var Generator = module.exports = function Generator() { - ScriptBase.apply(this, arguments); +// Register the Babel require hook +require('babel-core/register'); - this.option('route', { - desc: 'URL for the endpoint', - type: String - }); - - this.option('models', { - desc: 'Specify which model(s) to use', - type: String - }); - - this.option('endpointDirectory', { - desc: 'Parent directory for enpoints', - type: String - }); -}; - -util.inherits(Generator, ScriptBase); - -Generator.prototype.prompting = function askFor() { - var done = this.async(); - var promptCb = function (props) { - if(props.route.charAt(0) !== '/') { - props.route = '/' + props.route; - } - - this.route = props.route; - - if (props.models) { - delete this.filters.mongoose; - delete this.filters.mongooseModels; - delete this.filters.sequelize; - delete this.filters.sequelizeModels; - - this.filters[props.models] = true; - this.filters[props.models + 'Models'] = true; - } - done(); - }.bind(this); - - if (this.options.route) { - if (this.filters.mongoose && this.filters.sequelize) { - if (this.options.models) { - return promptCb(this.options); - } - } else { - if (this.filters.mongooseModels) { this.options.models = 'mongoose'; } - else if (this.filters.sequelizeModels) { this.options.models = 'sequelize'; } - else { delete this.options.models; } - return promptCb(this.options); - } - } - - var name = this.name; - - var base = this.config.get('routesBase') || '/api/'; - if(base.charAt(base.length-1) !== '/') { - base = base + '/'; - } - - // pluralization defaults to true for backwards compat - if (this.config.get('pluralizeRoutes') !== false) { - name = name + 's'; - } - - var self = this; - var prompts = [ - { - name: 'route', - message: 'What will the url of your endpoint be?', - default: base + name - }, - { - type: 'list', - name: 'models', - message: 'What would you like to use for the endpoint\'s models?', - choices: [ 'Mongoose', 'Sequelize' ], - default: self.filters.sequelizeModels ? 1 : 0, - filter: function( val ) { - return val.toLowerCase(); - }, - when: function() { - return self.filters.mongoose && self.filters.sequelize; - } - } - ]; - - this.prompt(prompts, promptCb); -}; - -Generator.prototype.configuring = function config() { - this.routeDest = path.join(this.options.endpointDirectory || - this.config.get('endpointDirectory') || 'server/api/', this.name); -}; - -Generator.prototype.writing = function createFiles() { - this.sourceRoot(path.join(__dirname, './templates')); - ngUtil.processDirectory(this, '.', this.routeDest); -}; - -Generator.prototype.end = function registerEndpoint() { - if(this.config.get('insertRoutes')) { - var routesFile = this.config.get('registerRoutesFile'); - var reqPath = this.relativeRequire(this.routeDest, routesFile); - var routeConfig = { - file: routesFile, - needle: this.config.get('routesNeedle'), - splicable: [ - "app.use(\'" + this.route +"\', require(\'" + reqPath + "\'));" - ] - }; - ngUtil.rewriteFile(routeConfig); - } - - if (this.filters.socketio && this.config.get('insertSockets')) { - var socketsFile = this.config.get('registerSocketsFile'); - var reqPath = this.relativeRequire(this.routeDest + '/' + this.basename + - '.socket', socketsFile); - var socketConfig = { - file: socketsFile, - needle: this.config.get('socketsNeedle'), - splicable: [ - "require(\'" + reqPath + "\').register(socket);" - ] - }; - ngUtil.rewriteFile(socketConfig); - } - - if (this.filters.sequelize && this.config.get('insertModels')) { - var modelsFile = this.config.get('registerModelsFile'); - var reqPath = this.relativeRequire(this.routeDest + '/' + this.basename + - '.model', modelsFile); - var modelConfig = { - file: modelsFile, - needle: this.config.get('modelsNeedle'), - splicable: [ - "db." + this.classedName + " = db.sequelize.import(\'" + reqPath +"\');" - ] - }; - ngUtil.rewriteFile(modelConfig); - } -}; +// Export the generator +exports = module.exports = require('./generator'); diff --git a/package.json b/package.json index 7c401ec46..27dd3aed3 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "test": "grunt test" }, "dependencies": { + "babel-core": "^5.8.23", "chalk": "^1.1.0", "generator-ng-component": "~0.1.0", "yeoman-generator": "~0.18.10" From d15314028f28d786069d92a0e4f065a3f989b8c4 Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 2 Sep 2015 04:03:17 -0400 Subject: [PATCH 0230/1357] refactor(gen): remove legacy argument fix, and ES2015ify more --- app/generator.js | 11 +++--- endpoint/generator.js | 12 +++--- script-base.js | 85 ++++++++++++++++++++++--------------------- util.js | 50 +++++++++---------------- 4 files changed, 72 insertions(+), 86 deletions(-) diff --git a/app/generator.js b/app/generator.js index 517773bc8..7751af8fe 100644 --- a/app/generator.js +++ b/app/generator.js @@ -2,9 +2,9 @@ import fs from 'fs'; import path from 'path'; -import genUtils from '../util.js'; -import {Base} from 'yeoman-generator'; import chalk from 'chalk'; +import {Base} from 'yeoman-generator'; +import * as genUtils from '../util'; export default class Generator extends Base { @@ -12,10 +12,12 @@ export default class Generator extends Base { super(...args); this.argument('name', { type: String, required: false }); + this.option('app-suffix', { desc: 'Allow a custom suffix to be added to the module name', type: String, - required: 'false' + required: 'false', + defaults: 'App' }); } @@ -26,8 +28,7 @@ export default class Generator extends Base { this.appname = this.name || path.basename(process.cwd()); this.appname = this._.camelize(this._.slugify(this._.humanize(this.appname))); - this.scriptAppName = this.appname + genUtils.appName(this); - console.log(this.scriptAppName); + this.scriptAppName = this.appname + genUtils.appSuffix(this); this.appPath = this.env.options.appPath; this.pkg = require('../package.json'); diff --git a/endpoint/generator.js b/endpoint/generator.js index b4757d743..0d6d3217d 100644 --- a/endpoint/generator.js +++ b/endpoint/generator.js @@ -1,8 +1,8 @@ 'use strict'; import path from 'path'; -import ngUtil from '../util'; -import ScriptBase from '../script-base.js'; +import ScriptBase from '../script-base'; +import * as genUtils from '../util'; export default class Generator extends ScriptBase { @@ -103,7 +103,7 @@ export default class Generator extends ScriptBase { writing() { this.sourceRoot(path.join(__dirname, './templates')); - ngUtil.processDirectory(this, '.', this.routeDest); + genUtils.processDirectory(this, '.', this.routeDest); } end() { @@ -117,7 +117,7 @@ export default class Generator extends ScriptBase { "app.use(\'" + this.route +"\', require(\'" + reqPath + "\'));" ] }; - ngUtil.rewriteFile(routeConfig); + genUtils.rewriteFile(routeConfig); } if (this.filters.socketio && this.config.get('insertSockets')) { @@ -131,7 +131,7 @@ export default class Generator extends ScriptBase { "require(\'" + reqPath + "\').register(socket);" ] }; - ngUtil.rewriteFile(socketConfig); + genUtils.rewriteFile(socketConfig); } if (this.filters.sequelize && this.config.get('insertModels')) { @@ -145,7 +145,7 @@ export default class Generator extends ScriptBase { "db." + this.classedName + " = db.sequelize.import(\'" + reqPath +"\');" ] }; - ngUtil.rewriteFile(modelConfig); + genUtils.rewriteFile(modelConfig); } } } diff --git a/script-base.js b/script-base.js index 288a4e4f4..0c9fc299e 100644 --- a/script-base.js +++ b/script-base.js @@ -1,44 +1,45 @@ 'use strict'; -var util = require('util'); -var path = require('path'); -var yeoman = require('yeoman-generator'); -var angularUtils = require('./util.js'); - -var Generator = module.exports = function Generator() { - yeoman.generators.NamedBase.apply(this, arguments); - - try { - this.appname = require(path.join(process.cwd(), 'bower.json')).name; - } catch (e) { - this.appname = path.basename(process.cwd()); - } - this.appname = this._.slugify(this._.humanize(this.appname)); - this.scriptAppName = this._.camelize(this.appname) + angularUtils.appName(this); - - var name = this.name.replace(/\//g, '-'); - - this.cameledName = this._.camelize(name); - this.classedName = this._.classify(name); - - this.basename = path.basename(this.name); - this.dirname = (this.name.indexOf('/') >= 0) ? path.dirname(this.name) : this.name; - // dynamic assertion statements - this.expect = function() { - return this.filters.expect ? 'expect(' : ''; - }.bind(this); - this.to = function() { - return this.filters.expect ? ').to' : '.should'; - }.bind(this); - - // dynamic relative require path - this.relativeRequire = function(to, fr) { - fr = fr || this.filePath; - return angularUtils.relativeRequire(this, to, fr); - }.bind(this); - - this.filters = this.config.get('filters'); - this.sourceRoot(path.join(__dirname, '/templates')); -}; - -util.inherits(Generator, yeoman.generators.NamedBase); +import util from 'util'; +import path from 'path'; +import {NamedBase} from 'yeoman-generator'; +import * as genUtils from './util'; + +export default class ScriptBase extends NamedBase { + constructor(...args) { + super(...args); + + try { + this.appname = require(path.join(process.cwd(), 'bower.json')).name; + } catch (e) { + this.appname = path.basename(process.cwd()); + } + this.appname = this._.slugify(this._.humanize(this.appname)); + this.scriptAppName = this._.camelize(this.appname) + genUtils.appSuffix(this); + + var name = this.name.replace(/\//g, '-'); + + this.cameledName = this._.camelize(name); + this.classedName = this._.classify(name); + + this.basename = path.basename(this.name); + this.dirname = (this.name.indexOf('/') >= 0) ? path.dirname(this.name) : this.name; + + // dynamic assertion statements + this.expect = function() { + return this.filters.expect ? 'expect(' : ''; + }.bind(this); + this.to = function() { + return this.filters.expect ? ').to' : '.should'; + }.bind(this); + + // dynamic relative require path + this.relativeRequire = function(to, fr) { + fr = fr || this.filePath; + return genUtils.relativeRequire(this, to, fr); + }.bind(this); + + this.filters = this.config.get('filters'); + this.sourceRoot(path.join(__dirname, '/templates')); + } +} diff --git a/util.js b/util.js index 0490a228a..64cf5c647 100644 --- a/util.js +++ b/util.js @@ -1,16 +1,9 @@ 'use strict'; -var path = require('path'); -var fs = require('fs'); - -module.exports = { - rewrite: rewrite, - rewriteFile: rewriteFile, - appName: appName, - processDirectory: processDirectory, - relativeRequire: relativeRequire -}; - -function rewriteFile (args) { + +import path from 'path'; +import fs from 'fs'; + +export function rewriteFile(args) { args.path = args.path || process.cwd(); var fullPath = path.join(args.path, args.file); @@ -20,13 +13,13 @@ function rewriteFile (args) { fs.writeFileSync(fullPath, body); } -function escapeRegExp (str) { +function escapeRegExp(str) { return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&'); } -function rewrite (args) { +export function rewrite(args) { // check if splicable is already in the body text - var re = new RegExp(args.splicable.map(function (line) { + var re = new RegExp(args.splicable.map(function(line) { return '\s*' + escapeRegExp(line); }).join('\n')); @@ -54,28 +47,19 @@ function rewrite (args) { spaceStr += ' '; } - lines.splice(otherwiseLineIndex + 1, 0, args.splicable.map(function (line) { + lines.splice(otherwiseLineIndex + 1, 0, args.splicable.map(function(line) { return spaceStr + line; }).join('\n')); return lines.join('\n'); } -function appName (self) { - var counter = 0, suffix = self.options['app-suffix']; - // Have to check this because of generator bug #386 - process.argv.forEach(function(val) { - if (val.indexOf('--app-suffix') > -1) { - counter++; - } - }); - if (counter === 0 || (typeof suffix === 'boolean' && suffix)) { - suffix = 'App'; - } - return suffix ? self._.classify(suffix) : ''; +export function appSuffix(self) { + var suffix = self.options['app-suffix']; + return (typeof suffix === 'string') ? self._.classify(suffix) : ''; } -function destinationPath (self, filepath) { +function destinationPath(self, filepath) { filepath = path.normalize(filepath); if (!path.isAbsolute(filepath)) { filepath = path.join(self.destinationRoot(), filepath); @@ -84,7 +68,7 @@ function destinationPath (self, filepath) { return filepath; } -function relativeRequire (self, to, fr) { +export function relativeRequire(self, to, fr) { fr = destinationPath(self, fr); to = destinationPath(self, to); return path.relative(path.dirname(fr), to) @@ -93,7 +77,7 @@ function relativeRequire (self, to, fr) { .replace(/[\/\\]index\.js$/, ''); // strip index.js suffix from path } -function filterFile (template) { +function filterFile(template) { // Find matches for parans var filterMatches = template.match(/\(([^)]+)\)/g); var filters = []; @@ -107,7 +91,7 @@ function filterFile (template) { return { name: template, filters: filters }; } -function templateIsUsable (self, filteredFile) { +function templateIsUsable(self, filteredFile) { var filters = self.filters || self.config.get('filters'); var enabledFilters = []; for(var key in filters) { @@ -121,7 +105,7 @@ function templateIsUsable (self, filteredFile) { return true; } -function processDirectory (self, source, destination) { +export function processDirectory(self, source, destination) { var root = self.isPathAbsolute(source) ? source : path.join(self.sourceRoot(), source); var files = self.expandFiles('**', { dot: true, cwd: root }); var dest, src; From b81292f0e9c4a9fcd96eaef5fc55283a6ccaa180 Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 2 Sep 2015 06:10:08 -0400 Subject: [PATCH 0231/1357] refactor(gen): improve `generator-base` and `util` wiring --- app/generator.js | 19 ++++------------- endpoint/generator.js | 19 ++++++++++------- generator-base.js | 49 +++++++++++++++++++++++++++++++++++++++++++ script-base.js | 45 --------------------------------------- util.js | 8 ++++--- 5 files changed, 70 insertions(+), 70 deletions(-) create mode 100644 generator-base.js delete mode 100644 script-base.js diff --git a/app/generator.js b/app/generator.js index 7751af8fe..591984d98 100644 --- a/app/generator.js +++ b/app/generator.js @@ -4,7 +4,7 @@ import fs from 'fs'; import path from 'path'; import chalk from 'chalk'; import {Base} from 'yeoman-generator'; -import * as genUtils from '../util'; +import {genBase} from '../generator-base'; export default class Generator extends Base { @@ -25,22 +25,11 @@ export default class Generator extends Base { return { init: function () { - this.appname = this.name || path.basename(process.cwd()); - this.appname = this._.camelize(this._.slugify(this._.humanize(this.appname))); - - this.scriptAppName = this.appname + genUtils.appSuffix(this); - this.appPath = this.env.options.appPath; this.pkg = require('../package.json'); - this.filters = {}; - // dynamic assertion statements - this.expect = function() { - return this.filters.expect ? 'expect(' : ''; - }.bind(this); - this.to = function() { - return this.filters.expect ? ').to' : '.should'; - }.bind(this); + // init shared generator properies and methods + genBase(this); }, info: function () { @@ -394,7 +383,7 @@ export default class Generator extends Base { generateProject: function() { this.sourceRoot(path.join(__dirname, './templates')); - genUtils.processDirectory(this, '.', '.'); + this.processDirectory('.', '.'); }, generateEndpoint: function() { diff --git a/endpoint/generator.js b/endpoint/generator.js index 0d6d3217d..169dec3d8 100644 --- a/endpoint/generator.js +++ b/endpoint/generator.js @@ -1,10 +1,10 @@ 'use strict'; import path from 'path'; -import ScriptBase from '../script-base'; -import * as genUtils from '../util'; +import {NamedBase} from 'yeoman-generator'; +import {genNamedBase} from '../generator-base'; -export default class Generator extends ScriptBase { +export default class Generator extends NamedBase { constructor(...args) { super(...args); @@ -25,6 +25,11 @@ export default class Generator extends ScriptBase { }); } + initializing() { + // init shared generator properies and methods + genNamedBase(this); + } + prompting() { var done = this.async(); var promptCb = function (props) { @@ -103,7 +108,7 @@ export default class Generator extends ScriptBase { writing() { this.sourceRoot(path.join(__dirname, './templates')); - genUtils.processDirectory(this, '.', this.routeDest); + this.processDirectory('.', this.routeDest); } end() { @@ -117,7 +122,7 @@ export default class Generator extends ScriptBase { "app.use(\'" + this.route +"\', require(\'" + reqPath + "\'));" ] }; - genUtils.rewriteFile(routeConfig); + this.rewriteFile(routeConfig); } if (this.filters.socketio && this.config.get('insertSockets')) { @@ -131,7 +136,7 @@ export default class Generator extends ScriptBase { "require(\'" + reqPath + "\').register(socket);" ] }; - genUtils.rewriteFile(socketConfig); + this.rewriteFile(socketConfig); } if (this.filters.sequelize && this.config.get('insertModels')) { @@ -145,7 +150,7 @@ export default class Generator extends ScriptBase { "db." + this.classedName + " = db.sequelize.import(\'" + reqPath +"\');" ] }; - genUtils.rewriteFile(modelConfig); + this.rewriteFile(modelConfig); } } } diff --git a/generator-base.js b/generator-base.js new file mode 100644 index 000000000..fbe4be437 --- /dev/null +++ b/generator-base.js @@ -0,0 +1,49 @@ +'use strict'; + +import util from 'util'; +import path from 'path'; +import * as genUtils from './util'; + +export function genBase(self) { + self = self || this; + + try { + self.appname = require(path.join(process.cwd(), 'bower.json')).name; + } catch (e) { + self.appname = self.name || path.basename(process.cwd()); + } + self.appname = self._.camelize(self._.slugify(self._.humanize(self.appname))); + self.scriptAppName = self.appname + genUtils.appSuffix(self); + + self.filters = self.filters || self.config.get('filters'); + + // dynamic assertion statements + self.expect = function() { + return self.filters.expect ? 'expect(' : ''; + }; + self.to = function() { + return self.filters.expect ? ').to' : '.should'; + }; + + // dynamic relative require path + self.relativeRequire = genUtils.relativeRequire.bind(self); + // process template directory + self.processDirectory = genUtils.processDirectory.bind(self); + // rewrite a file in place + self.rewriteFile = genUtils.rewriteFile; +} + +export function genNamedBase(self) { + self = self || this; + + // extend genBase + genBase(self); + + var name = self.name.replace(/\//g, '-'); + + self.cameledName = self._.camelize(name); + self.classedName = self._.classify(name); + + self.basename = path.basename(self.name); + self.dirname = (self.name.indexOf('/') >= 0) ? path.dirname(self.name) : self.name; +} diff --git a/script-base.js b/script-base.js deleted file mode 100644 index 0c9fc299e..000000000 --- a/script-base.js +++ /dev/null @@ -1,45 +0,0 @@ -'use strict'; - -import util from 'util'; -import path from 'path'; -import {NamedBase} from 'yeoman-generator'; -import * as genUtils from './util'; - -export default class ScriptBase extends NamedBase { - constructor(...args) { - super(...args); - - try { - this.appname = require(path.join(process.cwd(), 'bower.json')).name; - } catch (e) { - this.appname = path.basename(process.cwd()); - } - this.appname = this._.slugify(this._.humanize(this.appname)); - this.scriptAppName = this._.camelize(this.appname) + genUtils.appSuffix(this); - - var name = this.name.replace(/\//g, '-'); - - this.cameledName = this._.camelize(name); - this.classedName = this._.classify(name); - - this.basename = path.basename(this.name); - this.dirname = (this.name.indexOf('/') >= 0) ? path.dirname(this.name) : this.name; - - // dynamic assertion statements - this.expect = function() { - return this.filters.expect ? 'expect(' : ''; - }.bind(this); - this.to = function() { - return this.filters.expect ? ').to' : '.should'; - }.bind(this); - - // dynamic relative require path - this.relativeRequire = function(to, fr) { - fr = fr || this.filePath; - return genUtils.relativeRequire(this, to, fr); - }.bind(this); - - this.filters = this.config.get('filters'); - this.sourceRoot(path.join(__dirname, '/templates')); - } -} diff --git a/util.js b/util.js index 64cf5c647..d23e7f693 100644 --- a/util.js +++ b/util.js @@ -68,8 +68,9 @@ function destinationPath(self, filepath) { return filepath; } -export function relativeRequire(self, to, fr) { - fr = destinationPath(self, fr); +export function relativeRequire(to, fr) { + var self = this; + fr = destinationPath(self, fr || self.filePath); to = destinationPath(self, to); return path.relative(path.dirname(fr), to) .replace(/\\/g, '/') // convert win32 separator to posix @@ -105,7 +106,8 @@ function templateIsUsable(self, filteredFile) { return true; } -export function processDirectory(self, source, destination) { +export function processDirectory(source, destination) { + var self = this; var root = self.isPathAbsolute(source) ? source : path.join(self.sourceRoot(), source); var files = self.expandFiles('**', { dot: true, cwd: root }); var dest, src; From 8d504e87b749b88551ad34f23abdba96c77ffd94 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 1 Sep 2015 12:43:02 -0400 Subject: [PATCH 0232/1357] refactor(api:users): use import syntax --- app/templates/server/api/user(auth)/index.js | 6 +++--- .../server/api/user(auth)/user.controller.js | 11 +++++------ app/templates/server/api/user(auth)/user.events.js | 6 +++--- .../server/api/user(auth)/user.integration.js | 8 ++++---- .../api/user(auth)/user.model(mongooseModels).js | 4 ++-- .../api/user(auth)/user.model(sequelizeModels).js | 2 +- .../api/user(auth)/user.model.spec(mongooseModels).js | 4 ++-- .../user(auth)/user.model.spec(sequelizeModels).js | 4 ++-- 8 files changed, 22 insertions(+), 23 deletions(-) diff --git a/app/templates/server/api/user(auth)/index.js b/app/templates/server/api/user(auth)/index.js index be6fd3af3..f887500de 100644 --- a/app/templates/server/api/user(auth)/index.js +++ b/app/templates/server/api/user(auth)/index.js @@ -1,8 +1,8 @@ 'use strict'; -var express = require('express'); -var controller = require('./user.controller'); -var auth = require('../../auth/auth.service'); +import express from 'express'; +import controller from './user.controller'; +import auth from '../../auth/auth.service'; var router = express.Router(); diff --git a/app/templates/server/api/user(auth)/user.controller.js b/app/templates/server/api/user(auth)/user.controller.js index 059216b4c..ad30b5b3b 100644 --- a/app/templates/server/api/user(auth)/user.controller.js +++ b/app/templates/server/api/user(auth)/user.controller.js @@ -1,11 +1,10 @@ 'use strict'; <% if (filters.mongooseModels) { %> -var User = require('./user.model');<% } %><% if (filters.sequelizeModels) { %> -var sqldb = require('../../sqldb'); -var User = sqldb.User;<% } %> -var passport = require('passport'); -var config = require('../../config/environment'); -var jwt = require('jsonwebtoken'); +import User from './user.model';<% } %><% if (filters.sequelizeModels) { %> +import {User} from '../../sqldb';<% } %> +import passport from 'passport'; +import config from '../../config/environment'; +import jwt from 'jsonwebtoken'; function validationError(res, statusCode) { statusCode = statusCode || 422; diff --git a/app/templates/server/api/user(auth)/user.events.js b/app/templates/server/api/user(auth)/user.events.js index 102fd5d55..42137933d 100644 --- a/app/templates/server/api/user(auth)/user.events.js +++ b/app/templates/server/api/user(auth)/user.events.js @@ -4,9 +4,9 @@ 'use strict'; -var EventEmitter = require('events').EventEmitter;<% if (filters.mongooseModels) { %> -var User = require('./user.model');<% } if (filters.sequelizeModels) { %> -var User = require('../../sqldb').User;<% } %> +import {EventEmitter} from 'events';<% if (filters.mongooseModels) { %> +import User from './user.model';<% } if (filters.sequelizeModels) { %> +import {User} from '../../sqldb';<% } %> var UserEvents = new EventEmitter(); // Set max event listeners (0 == unlimited) diff --git a/app/templates/server/api/user(auth)/user.integration.js b/app/templates/server/api/user(auth)/user.integration.js index 0abae3b89..5c7c652b3 100644 --- a/app/templates/server/api/user(auth)/user.integration.js +++ b/app/templates/server/api/user(auth)/user.integration.js @@ -1,9 +1,9 @@ 'use strict'; -var app = require('../..');<% if (filters.mongooseModels) { %> -var User = require('./user.model');<% } %><% if (filters.sequelizeModels) { %> -var User = require('../../sqldb').User;<% } %> -var request = require('supertest'); +import app from '../..';<% if (filters.mongooseModels) { %> +import User from './user.model';<% } %><% if (filters.sequelizeModels) { %> +import {User} from '../../sqldb';<% } %> +import request from 'supertest'; describe('User API:', function() { var user; diff --git a/app/templates/server/api/user(auth)/user.model(mongooseModels).js b/app/templates/server/api/user(auth)/user.model(mongooseModels).js index f8fa923cf..e97da090f 100644 --- a/app/templates/server/api/user(auth)/user.model(mongooseModels).js +++ b/app/templates/server/api/user(auth)/user.model(mongooseModels).js @@ -1,8 +1,8 @@ 'use strict'; +import crypto from 'crypto'; var mongoose = require('bluebird').promisifyAll(require('mongoose')); -var Schema = mongoose.Schema; -var crypto = require('crypto');<% if (filters.oauth) { %> +var Schema = mongoose.Schema;<% if (filters.oauth) { %> var authTypes = ['github', 'twitter', 'facebook', 'google'];<% } %> var UserSchema = new Schema({ diff --git a/app/templates/server/api/user(auth)/user.model(sequelizeModels).js b/app/templates/server/api/user(auth)/user.model(sequelizeModels).js index 776eafc3e..500f6b81f 100644 --- a/app/templates/server/api/user(auth)/user.model(sequelizeModels).js +++ b/app/templates/server/api/user(auth)/user.model(sequelizeModels).js @@ -1,6 +1,6 @@ 'use strict'; -var crypto = require('crypto');<% if (filters.oauth) { %> +import crypto from 'crypto';<% if (filters.oauth) { %> var authTypes = ['github', 'twitter', 'facebook', 'google'];<% } %> var validatePresenceOf = function(value) { diff --git a/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js b/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js index 478fd74d8..4cff951fd 100644 --- a/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js +++ b/app/templates/server/api/user(auth)/user.model.spec(mongooseModels).js @@ -1,7 +1,7 @@ 'use strict'; -var app = require('../..'); -var User = require('./user.model'); +import app from '../..'; +import User from './user.model'; var user; var genUser = function() { user = new User({ diff --git a/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js b/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js index d231514be..ec4196a03 100644 --- a/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js +++ b/app/templates/server/api/user(auth)/user.model.spec(sequelizeModels).js @@ -1,7 +1,7 @@ 'use strict'; -var app = require('../..'); -var User = require('../../sqldb').User; +import app from '../..'; +import {User} from '../../sqldb'; var user; var genUser = function() { user = User.build({ From ab20456e899454e1d8b4d60fe058ca5a20765c1f Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 1 Sep 2015 12:43:26 -0400 Subject: [PATCH 0233/1357] refactor(server): use import syntax on app.js and routes.js --- app/templates/server/app.js | 11 ++++++----- app/templates/server/routes.js | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/templates/server/app.js b/app/templates/server/app.js index ca1e4ca78..1b28cdb11 100644 --- a/app/templates/server/app.js +++ b/app/templates/server/app.js @@ -7,10 +7,11 @@ // Set default node environment to development process.env.NODE_ENV = process.env.NODE_ENV || 'development'; -var express = require('express');<% if (filters.mongoose) { %> -var mongoose = require('mongoose');<% } %><% if (filters.sequelize) { %> -var sqldb = require('./sqldb');<% } %> -var config = require('./config/environment'); +import express from 'express';<% if (filters.mongoose) { %> +import mongoose from 'mongoose';<% } %><% if (filters.sequelize) { %> +import sqldb from './sqldb';<% } %> +import config from './config/environment'; +import http from 'http'; <% if (filters.mongoose) { %> // Connect to MongoDB mongoose.connect(config.mongo.uri, config.mongo.options); @@ -24,7 +25,7 @@ if (config.seedDB) { require('./config/seed'); } <% } %> // Setup server var app = express(); -var server = require('http').createServer(app);<% if (filters.socketio) { %> +var server = http.createServer(app);<% if (filters.socketio) { %> var socketio = require('socket.io')(server, { serveClient: config.env !== 'production', path: '/socket.io-client' diff --git a/app/templates/server/routes.js b/app/templates/server/routes.js index 23e902765..977829165 100644 --- a/app/templates/server/routes.js +++ b/app/templates/server/routes.js @@ -4,8 +4,8 @@ 'use strict'; -var errors = require('./components/errors'); -var path = require('path'); +import errors from './components/errors'; +import path from 'path'; module.exports = function(app) { From 486440a17911c26bdb4187fa1a426f9166a3b532 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 2 Sep 2015 13:24:51 -0400 Subject: [PATCH 0234/1357] 3.0.0-rc6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 27dd3aed3..e88584a8b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "generator-angular-fullstack", - "version": "3.0.0-rc5", + "version": "3.0.0-rc6", "description": "Yeoman generator for creating MEAN stack applications, using MongoDB, Express, AngularJS, and Node", "keywords": [ "yeoman-generator", From c39078bdcd89f6b1938cb16aa200c9485a02979c Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 2 Sep 2015 13:39:55 -0400 Subject: [PATCH 0235/1357] chore(npm): update author and add contributors --- package.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index e88584a8b..f8b1ff312 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,15 @@ ], "homepage": "https://github.com/DaftMonk/generator-angular-fullstack", "bugs": "https://github.com/DaftMonk/generator-angular-fullstack/issues", - "author": "Tyler Henkel", + "author": "Tyler Henkel (http://tylerhenkel.com/)", + "contributors": [ + "Andrew Koroluk (http://andrewk.me/)", + "Cody Mize (http://codymize.com/)", + "Brian Ford (http://briantford.com/)", + "Pascal Hartig (http://passy.me/)", + "Eddie Monge (http://eddiemonge.com)", + "Sindre Sorhus (https://twitter.com/sindresorhus)" + ], "repository": { "type": "git", "url": "git://github.com/DaftMonk/generator-angular-fullstack.git" From b9de25d75f547d60545a94c16bf838ce54d58d18 Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 2 Sep 2015 15:39:15 -0400 Subject: [PATCH 0236/1357] chore(gen): remove deprecated generators --- generators/constant/index.js | 14 -------------- generators/deploy/index.js | 15 --------------- generators/readme.md | 1 - generators/value/index.js | 14 -------------- generators/view/index.js | 14 -------------- 5 files changed, 58 deletions(-) delete mode 100644 generators/constant/index.js delete mode 100644 generators/deploy/index.js delete mode 100644 generators/readme.md delete mode 100644 generators/value/index.js delete mode 100644 generators/view/index.js diff --git a/generators/constant/index.js b/generators/constant/index.js deleted file mode 100644 index 4524a8eed..000000000 --- a/generators/constant/index.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; -var chalk = require('chalk'); -var yeoman = require('yeoman-generator'); -var util = require('util'); - -var Generator = module.exports = function Generator() { - yeoman.generators.Base.apply(this, arguments); -}; - -util.inherits(Generator, yeoman.generators.Base); - -Generator.prototype.deprecated = function deprecated() { - this.log(chalk.yellow('This sub-generator is deprecated. \n')); -}; diff --git a/generators/deploy/index.js b/generators/deploy/index.js deleted file mode 100644 index 7fb3452fa..000000000 --- a/generators/deploy/index.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; -var chalk = require('chalk'); -var yeoman = require('yeoman-generator'); -var util = require('util'); - -var Generator = module.exports = function Generator() { - yeoman.generators.Base.apply(this, arguments); -}; - -util.inherits(Generator, yeoman.generators.NamedBase); - -Generator.prototype.deprecated = function deprecated() { - this.log(chalk.yellow(chalk.bold('yo angular-fullstack:deploy') + ' is deprecated, instead use: \n') + - chalk.green('yo angular-fullstack:heroku') + ' or ' + chalk.green('yo angular-fullstack:openshift')); -}; diff --git a/generators/readme.md b/generators/readme.md deleted file mode 100644 index d56c72138..000000000 --- a/generators/readme.md +++ /dev/null @@ -1 +0,0 @@ -This folder is for deprecated generators only. diff --git a/generators/value/index.js b/generators/value/index.js deleted file mode 100644 index 4524a8eed..000000000 --- a/generators/value/index.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; -var chalk = require('chalk'); -var yeoman = require('yeoman-generator'); -var util = require('util'); - -var Generator = module.exports = function Generator() { - yeoman.generators.Base.apply(this, arguments); -}; - -util.inherits(Generator, yeoman.generators.Base); - -Generator.prototype.deprecated = function deprecated() { - this.log(chalk.yellow('This sub-generator is deprecated. \n')); -}; diff --git a/generators/view/index.js b/generators/view/index.js deleted file mode 100644 index 4524a8eed..000000000 --- a/generators/view/index.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; -var chalk = require('chalk'); -var yeoman = require('yeoman-generator'); -var util = require('util'); - -var Generator = module.exports = function Generator() { - yeoman.generators.Base.apply(this, arguments); -}; - -util.inherits(Generator, yeoman.generators.Base); - -Generator.prototype.deprecated = function deprecated() { - this.log(chalk.yellow('This sub-generator is deprecated. \n')); -}; From acf61395b36411c2070b9884689f3d1f0ab350ea Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 2 Sep 2015 16:26:03 -0400 Subject: [PATCH 0237/1357] fix(tests): run babel register hook in protractor `onPrepare` --- app/templates/protractor.conf.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/templates/protractor.conf.js b/app/templates/protractor.conf.js index 6178c1a76..ceebb85b2 100644 --- a/app/templates/protractor.conf.js +++ b/app/templates/protractor.conf.js @@ -64,7 +64,8 @@ var config = { serverConfig: require('./server/config/environment') }, - onPrepare: function() {<% if (filters.mocha) { %> + onPrepare: function() { + require('babel-core/register');<% if (filters.mocha) { %> // Load Mocha and Chai + plugins require('./mocha.conf'); From a4ba9647452bfbee2a38b905d7bebfa515826055 Mon Sep 17 00:00:00 2001 From: kingcody Date: Fri, 4 Sep 2015 13:10:10 -0400 Subject: [PATCH 0238/1357] fix(gen): allow generator to be transpiled as a node_module closes #1244 --- app/index.js | 4 +++- endpoint/index.js | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/index.js b/app/index.js index 994cdee97..11dde883e 100644 --- a/app/index.js +++ b/app/index.js @@ -1,7 +1,9 @@ 'use strict'; // Register the Babel require hook -require('babel-core/register'); +require('babel-core/register')({ + only: /generator-angular-fullstack\/(?!node_modules)/ +}); // Export the generator exports = module.exports = require('./generator'); diff --git a/endpoint/index.js b/endpoint/index.js index 994cdee97..11dde883e 100644 --- a/endpoint/index.js +++ b/endpoint/index.js @@ -1,7 +1,9 @@ 'use strict'; // Register the Babel require hook -require('babel-core/register'); +require('babel-core/register')({ + only: /generator-angular-fullstack\/(?!node_modules)/ +}); // Export the generator exports = module.exports = require('./generator'); From b7647165a38492f1eb269d7c43bc5467554d1b3e Mon Sep 17 00:00:00 2001 From: kingcody Date: Thu, 3 Sep 2015 18:44:20 -0400 Subject: [PATCH 0239/1357] feat(gen): add angular-fullstack-deps submodule --- .gitmodules | 3 +++ .travis.yml | 2 ++ angular-fullstack-deps | 1 + 3 files changed, 6 insertions(+) create mode 100644 .gitmodules create mode 160000 angular-fullstack-deps diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..ff287e31c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "angular-fullstack-deps"] + path = angular-fullstack-deps + url = git@github.com:angular-fullstack/angular-fullstack-deps.git diff --git a/.travis.yml b/.travis.yml index 814f378a3..82f95fde5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,3 +24,5 @@ notifications: on_success: change # options: [always|never|change] default: always on_failure: always # options: [always|never|change] default: always on_start: false # default: false +git: + submodules: false diff --git a/angular-fullstack-deps b/angular-fullstack-deps new file mode 160000 index 000000000..45f8b0937 --- /dev/null +++ b/angular-fullstack-deps @@ -0,0 +1 @@ +Subproject commit 45f8b093793dfb562db32777f897d538a403bfc4 From 4f8f8b6d3d91f44a1b01ef222bdf1470ed6db88d Mon Sep 17 00:00:00 2001 From: kingcody Date: Thu, 3 Sep 2015 18:50:47 -0400 Subject: [PATCH 0240/1357] feat(gen): extend `updateFixtures` task to populate `angular-fullstack-deps` Usage: ```bash $ grunt updateFixtures:deps` ``` --- Gruntfile.js | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 38fc08efc..4c4bbb7e3 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -220,21 +220,23 @@ module.exports = function (grunt) { } }); - grunt.registerTask('updateFixtures', 'updates package and bower fixtures', function() { - var packageJson = fs.readFileSync(path.resolve('app/templates/_package.json'), 'utf8'); - var bowerJson = fs.readFileSync(path.resolve('app/templates/_bower.json'), 'utf8'); - - // replace package name - packageJson = packageJson.replace(/"name": "<%(.*)%>"/g, '"name": "tempApp"'); - packageJson = packageJson.replace(/<%(.*)%>/g, ''); - - // remove all ejs conditionals - bowerJson = bowerJson.replace(/"name": "<%(.*)%>"/g, '"name": "tempApp"'); - bowerJson = bowerJson.replace(/<%(.*)%>/g, ''); - - // save files - fs.writeFileSync(path.resolve(__dirname + '/test/fixtures/package.json'), packageJson); - fs.writeFileSync(path.resolve(__dirname + '/test/fixtures/bower.json'), bowerJson); + grunt.registerTask('updateFixtures', 'updates package and bower fixtures', function(target) { + var genVer = require('./package.json').version; + var dest = __dirname + ((target === 'deps') ? '/angular-fullstack-deps/' : '/test/fixtures/'); + var appName = (target === 'deps') ? 'angular-fullstack-deps' : 'tempApp'; + + var processJson = function(s, d) { + // read file, strip all ejs conditionals, and parse as json + var json = JSON.parse(fs.readFileSync(path.resolve(s), 'utf8').replace(/<%(.*)%>/g, '')); + // set properties + json.name = appName, json.version = genVer; + if (target === 'deps') { json.private = false; } + // stringify json and write it to the destination + fs.writeFileSync(path.resolve(d), JSON.stringify(json, null, 2)); + }; + + processJson('app/templates/_package.json', dest + 'package.json'); + processJson('app/templates/_bower.json', dest + 'bower.json'); }); grunt.registerTask('installFixtures', 'install package and bower fixtures', function() { From 940a7c670c2c387bcd9e276541422b65fa384a79 Mon Sep 17 00:00:00 2001 From: kingcody Date: Thu, 3 Sep 2015 19:31:32 -0400 Subject: [PATCH 0241/1357] feat(docs): add `angular-fullstack-deps` dependency badges [ci skip] --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index f5f37e9e1..618dea68c 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,6 @@ # AngularJS Full-Stack generator [![Build Status](https://travis-ci.org/DaftMonk/generator-angular-fullstack.svg?branch=master)](http://travis-ci.org/DaftMonk/generator-angular-fullstack) [![npm version](https://badge.fury.io/js/generator-angular-fullstack.svg)](http://badge.fury.io/js/generator-angular-fullstack) [![Dependency Status](https://david-dm.org/daftmonk/generator-angular-fullstack.png)](https://david-dm.org/daftmonk/generator-angular-fullstack) [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/DaftMonk/generator-angular-fullstack) - +#### Generated project: [![Dependency Status](https://david-dm.org/angular-fullstack/angular-fullstack-deps.svg)](https://david-dm.org/angular-fullstack/angular-fullstack-deps) [![Dev-Dependency Status](https://david-dm.org/angular-fullstack/angular-fullstack-deps/dev-status.svg)](https://david-dm.org/angular-fullstack/angular-fullstack-deps#info=devDependencies) > Yeoman generator for creating MEAN stack applications, using MongoDB, Express, AngularJS, and Node - lets you quickly set up a project following best practices. ## Example project From 87b31362f99d73c26487d731207a2fe59729c357 Mon Sep 17 00:00:00 2001 From: kingcody Date: Fri, 4 Sep 2015 11:43:18 -0400 Subject: [PATCH 0242/1357] feat(gen): update release task for current workflow --- Gruntfile.js | 66 +++++++++++++++++++++++++++++++--------------------- package.json | 1 - 2 files changed, 39 insertions(+), 28 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 4c4bbb7e3..64198cda7 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,6 +1,5 @@ 'use strict'; -var semver = require('semver'); var shell = require('shelljs'); var child_process = require('child_process'); var Q = require('q'); @@ -28,15 +27,26 @@ module.exports = function (grunt) { }, release: { options: { + bump: false, // remove after 3.0.0 release commitMessage: '<%= version %>', - tagName: 'v<%= version %>', - bump: false, // we have our own bump - file: 'package.json' + tagName: '<%= version %>', + file: 'package.json', + afterBump: ['updateFixtures:deps', 'commitNgFullstackDeps'], + beforeRelease: ['stage'], + push: false, + pushTags: false, + npm: false + } + }, + commitNgFullstackDeps: { + options: { + cwd: 'angular-fullstack-deps', + files: ['package.json', 'bower.json'] } }, stage: { options: { - files: ['CHANGELOG.md'] + files: ['CHANGELOG.md', 'angular-fullstack-deps'] } }, buildcontrol: { @@ -103,32 +113,34 @@ module.exports = function (grunt) { } }); - grunt.registerTask('bump', 'bump manifest version', function (type) { - var options = this.options({ - file: grunt.config('pkgFile') || 'package.json' - }); - - function setup(file, type) { - var pkg = grunt.file.readJSON(file); - var newVersion = pkg.version = semver.inc(pkg.version, type || 'patch'); - return { - file: file, - pkg: pkg, - newVersion: newVersion - }; - } - - var config = setup(options.file, type); - grunt.file.write(config.file, JSON.stringify(config.pkg, null, ' ') + '\n'); - grunt.log.ok('Version bumped to ' + config.newVersion); - }); - grunt.registerTask('stage', 'git add files before running the release task', function () { - var files = this.options().files; + var files = grunt.config('stage.options').files, done = this.async(); grunt.util.spawn({ cmd: process.platform === 'win32' ? 'git.cmd' : 'git', args: ['add'].concat(files) - }, grunt.task.current.async()); + }, done); + }); + + grunt.registerTask('commitNgFullstackDeps', function() { + grunt.config.requires( + 'commitNgFullstackDeps.options.files', + 'commitNgFullstackDeps.options.cwd' + ); + var ops = grunt.config.get('commitNgFullstackDeps').options; + var version = require('./package.json').version || 'NO VERSION SET'; + if (Array.isArray(ops.files) && ops.files.length > 0) { + var done = this.async(); + var cwd = path.resolve(__dirname, ops.cwd); + grunt.util.spawn({ + cmd: process.platform === 'win32' ? 'git.cmd' : 'git', + args: ['commit', '-m', version].concat(ops.files), + opts: { + cwd: cwd + } + }, done); + } else { + grunt.log.writeln('No files were commited'); + } }); grunt.registerTask('generateDemo', 'generate demo', function () { diff --git a/package.json b/package.json index f8b1ff312..c36bf2d50 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,6 @@ "mocha": "^2.2.5", "q": "^1.0.1", "recursive-readdir": "^1.2.0", - "semver": "^5.0.1", "shelljs": "^0.5.3", "underscore.string": "^3.1.1" }, From bfd9fce85a39d202321547bbd8cb98429425d8f4 Mon Sep 17 00:00:00 2001 From: kingcody Date: Sat, 5 Sep 2015 04:17:00 -0400 Subject: [PATCH 0243/1357] feat(app): use grunt config for `server` location --- app/templates/Gruntfile.js | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 5e56ff203..94e2aabbf 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -31,6 +31,7 @@ module.exports = function (grunt) { yeoman: { // configurable paths client: require('./bower.json').appPath || 'client', + server: 'server', dist: 'dist' }, express: { @@ -39,13 +40,13 @@ module.exports = function (grunt) { }, dev: { options: { - script: 'server', + script: '<%%= yeoman.server %>', debug: true } }, prod: { options: { - script: 'dist/server' + script: '<%%= yeoman.dist %>/<%%= yeoman.server %>' } } }, @@ -71,7 +72,7 @@ module.exports = function (grunt) { tasks: ['injector:css'] }, mochaTest: { - files: ['server/**/*.{spec,integration}.js'], + files: ['<%%= yeoman.server %>/**/*.{spec,integration}.js'], tasks: ['env:test', 'mochaTest'] }, jsTest: { @@ -128,7 +129,7 @@ module.exports = function (grunt) { } }, express: { - files: ['server/**/*.{js,json}'], + files: ['<%%= yeoman.server %>/**/*.{js,json}'], tasks: ['express:dev', 'wait'], options: { livereload: true, @@ -149,15 +150,15 @@ module.exports = function (grunt) { }, server: { options: { - jshintrc: 'server/.jshintrc' + jshintrc: '<%%= yeoman.server %>/.jshintrc' }, - src: ['server/**/!(*.spec|*.integration).js'] + src: ['<%%= yeoman.server %>/**/!(*.spec|*.integration).js'] }, serverTest: { options: { - jshintrc: 'server/.jshintrc-spec' + jshintrc: '<%%= yeoman.server %>/.jshintrc-spec' }, - src: ['server/**/*.{spec,integration}.js'] + src: ['<%%= yeoman.server %>/**/*.{spec,integration}.js'] }, all: ['<%%= yeoman.client %>/{app,components}/**/!(*.spec|*.mock).js'], test: { @@ -173,7 +174,7 @@ module.exports = function (grunt) { files: { src: [ '<%%= yeoman.client %>/app/**/*.js', - 'server/**/*.js' + '<%%= yeoman.server %>/**/*.js' ] } } @@ -223,7 +224,7 @@ module.exports = function (grunt) { // Use nodemon to run server in debug mode with an initial breakpoint nodemon: { debug: { - script: 'server', + script: '<%%= yeoman.server %>', options: { nodeArgs: ['--debug-brk'], env: { @@ -393,7 +394,7 @@ module.exports = function (grunt) { dest: '<%%= yeoman.dist %>', src: [ 'package.json', - 'server/**/*' + '<%%= yeoman.server %>/**/*' ] }] }, @@ -407,7 +408,7 @@ module.exports = function (grunt) { buildcontrol: { options: { - dir: 'dist', + dir: '<%%= yeoman.dist %>', commit: true, push: true, connectCommits: false, @@ -480,10 +481,10 @@ module.exports = function (grunt) { timeout: 5000 // set default mocha spec timeout }, unit: { - src: ['server/**/*.spec.js'] + src: ['<%%= yeoman.server %>/**/*.spec.js'] }, integration: { - src: ['server/**/*.integration.js'] + src: ['<%%= yeoman.server %>/**/*.integration.js'] } }, @@ -496,7 +497,7 @@ module.exports = function (grunt) { mask: '**/*.spec.js', coverageFolder: 'coverage/server/unit' }, - src: 'server' + src: '<%%= yeoman.server %>' }, integration: { options: { @@ -506,7 +507,7 @@ module.exports = function (grunt) { mask: '**/*.integration.js', coverageFolder: 'coverage/server/integration' }, - src: 'server' + src: '<%%= yeoman.server %>' } }, From b855c248dcbfa62f6e07363affeb3e3b0217feba Mon Sep 17 00:00:00 2001 From: kingcody Date: Sat, 5 Sep 2015 18:48:03 -0400 Subject: [PATCH 0244/1357] feat(gen): ignore angular-fullstack-deps and test for npm publish This will reduce the published size quite a bit since `test/fixtures` was previously being published [ci skip] --- .npmignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .npmignore diff --git a/.npmignore b/.npmignore new file mode 100644 index 000000000..ec6ff802d --- /dev/null +++ b/.npmignore @@ -0,0 +1,2 @@ +angular-fullstack-deps +test From 15fdd0f821ba9ca7f741f128b414b89ebd93b1c3 Mon Sep 17 00:00:00 2001 From: kingcody Date: Thu, 3 Sep 2015 03:17:06 -0400 Subject: [PATCH 0245/1357] chore(gen): update yeoman-generator to `~0.19.2` --- app/generator.js | 4 +- app/templates/README.md | 2 +- app/templates/_bower.json | 2 +- app/templates/_package.json | 2 +- .../components/navbar/navbar(html).html | 2 +- .../components/navbar/navbar(jade).jade | 2 +- app/templates/server/config/_local.env.js | 2 +- .../server/config/_local.env.sample.js | 2 +- .../server/config/environment/development.js | 2 +- .../server/config/environment/index.js | 2 +- .../server/config/environment/production.js | 2 +- .../server/config/environment/test.js | 2 +- app/templates/server/config/express.js | 2 +- generator-base.js | 15 ++++++-- heroku/index.js | 5 ++- openshift/index.js | 5 ++- package.json | 8 +++- test/test-file-creation.js | 37 +++++++++++-------- util.js | 17 +++++++-- 19 files changed, 72 insertions(+), 43 deletions(-) diff --git a/app/generator.js b/app/generator.js index 591984d98..22b46dfe8 100644 --- a/app/generator.js +++ b/app/generator.js @@ -33,7 +33,7 @@ export default class Generator extends Base { }, info: function () { - this.log(this.welcome); + this.log(this.yoWelcome); this.log('Out of the box I create an AngularJS app with an Express server.\n'); }, @@ -49,7 +49,7 @@ export default class Generator extends Base { }], function (answers) { this.skipConfig = answers.skipConfig; - this.filters = this._.defaults(this.config.get('filters'), { + this.filters = this.lodash.defaults(this.config.get('filters'), { bootstrap: true, uibootstrap: true, jasmine: true diff --git a/app/templates/README.md b/app/templates/README.md index 958834120..e5ec70428 100644 --- a/app/templates/README.md +++ b/app/templates/README.md @@ -1,4 +1,4 @@ -# <%= _.slugify(_.humanize(appname)) %> +# <%= lodash.slugify(lodash.humanize(appname)) %> This project was generated with the [Angular Full-Stack Generator](https://github.com/DaftMonk/generator-angular-fullstack) version <%= pkg.version %>. diff --git a/app/templates/_bower.json b/app/templates/_bower.json index 1d41b39d1..85e8835ed 100644 --- a/app/templates/_bower.json +++ b/app/templates/_bower.json @@ -1,5 +1,5 @@ { - "name": "<%= _.slugify(_.humanize(appname)) %>", + "name": "<%= lodash.slugify(lodash.humanize(appname)) %>", "version": "0.0.0", "dependencies": { "angular": "~1.4.0", diff --git a/app/templates/_package.json b/app/templates/_package.json index 67760246d..3187a8ae1 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -1,5 +1,5 @@ { - "name": "<%= _.slugify(_.humanize(appname)) %>", + "name": "<%= lodash.slugify(lodash.humanize(appname)) %>", "version": "0.0.0", "main": "server/app.js", "dependencies": { diff --git a/app/templates/client/components/navbar/navbar(html).html b/app/templates/client/components/navbar/navbar(html).html index ec9e4682d..eda46b07a 100644 --- a/app/templates/client/components/navbar/navbar(html).html +++ b/app/templates/client/components/navbar/navbar(html).html @@ -7,7 +7,7 @@ - <%= _.slugify(_.humanize(appname)) %> + <%= lodash.slugify(lodash.humanize(appname)) %>
+
+ + + +

+ Passwords must match. +

+ +
+

{{ message }}

diff --git a/app/templates/client/app/account(auth)/settings/settings(jade).jade b/app/templates/client/app/account(auth)/settings/settings(jade).jade index 96340b522..701215380 100644 --- a/app/templates/client/app/account(auth)/settings/settings(jade).jade +++ b/app/templates/client/app/account(auth)/settings/settings(jade).jade @@ -7,14 +7,29 @@ navbar form.form(name='form', ng-submit='changePassword(form)', novalidate='') .form-group label Current Password - input.form-control(type='password', name='password', ng-model='user.oldPassword', mongoose-error='') + input.form-control(type='password' + name='password' + ng-model='user.oldPassword' + mongoose-error='') p.help-block(ng-show='form.password.$error.mongoose') | {{ errors.other }} .form-group label New Password - input.form-control(type='password', name='newPassword', ng-model='user.newPassword', ng-minlength='3', required='') + input.form-control(type='password' + name='newPassword' + ng-model='user.newPassword' + ng-minlength='3', required='') p.help-block(ng-show='(form.newPassword.$error.minlength || form.newPassword.$error.required) && (form.newPassword.$dirty || submitted)') | Password must be at least 3 characters. + .form-group + label Confirm New Password + input.form-control(type='password' + name='confirmPassword' + ng-model='user.confirmPassword' + match="user.newPassword" + ng-minlength='3', required='') + p.help-block(ng-show='form.confirmPassword.$error.match && submitted') + | Passwords must match. p.help-block {{ message }} diff --git a/app/templates/client/app/account(auth)/signup/signup(html).html b/app/templates/client/app/account(auth)/signup/signup(html).html index 5052a02ee..0a95a7546 100644 --- a/app/templates/client/app/account(auth)/signup/signup(html).html +++ b/app/templates/client/app/account(auth)/signup/signup(html).html @@ -54,6 +54,18 @@

Sign up

+
+ + +

+ Passwords must match. +

+
+
-<% if (filters.oauth) {%> -
-
<% if (filters.facebookAuth) {%> - - Connect with Facebook - <% } %><% if (filters.googleAuth) {%> - - Connect with Google+ - <% } %><% if (filters.twitterAuth) {%> - - Connect with Twitter - <% } %> +<% if (filters.oauth) { %> +
+
+
+ +
<% } %>
diff --git a/app/templates/client/app/account(auth)/login/login(jade).jade b/app/templates/client/app/account(auth)/login/login(jade).jade index 7ef7c0134..2352e8fad 100644 --- a/app/templates/client/app/account(auth)/login/login(jade).jade +++ b/app/templates/client/app/account(auth)/login/login(jade).jade @@ -39,16 +39,8 @@ navbar <% if (filters.oauth) {%> hr - div<% if (filters.facebookAuth) {%> - a.btn.btn-facebook(href='', ng-click='loginOauth("facebook")') - i.fa.fa-facebook - | Connect with Facebook - = ' '<% } %><% if (filters.googleAuth) {%> - a.btn.btn-google-plus(href='', ng-click='loginOauth("google")') - i.fa.fa-google-plus - | Connect with Google+ - = ' '<% } %><% if (filters.twitterAuth) {%> - a.btn.btn-twitter(href='', ng-click='loginOauth("twitter")') - i.fa.fa-twitter - | Connect with Twitter<% } %><% } %> + .row + .col-sm-4.col-md-3 + oauth-buttons(classes='btn-block') +<% } %> hr diff --git a/app/templates/client/app/account(auth)/login/login(less).less b/app/templates/client/app/account(auth)/login/login(less).less deleted file mode 100644 index 6eaecd90c..000000000 --- a/app/templates/client/app/account(auth)/login/login(less).less +++ /dev/null @@ -1,30 +0,0 @@ -<% if (filters.bootstrap) { %>// Colors -// -------------------------------------------------- - -@btnText: #fff; -@btnTextAlt: #000;<% if (filters.oauth) { %> -<% if (filters.facebookAuth) { %> -@btnFacebookBackground: #3B5998; -@btnFacebookBackgroundHighlight: #133783;<% } if (filters.twitterAuth) { %> -@btnTwitterBackground: #2daddc; -@btnTwitterBackgroundHighlight: #0271bf;<% } if (filters.googleAuth) { %> -@btnGooglePlusBackground: #dd4b39; -@btnGooglePlusBackgroundHighlight: #c53727;<% } %> -@btnGithubBackground: #fafafa; -@btnGithubBackgroundHighlight: #ccc; - -// Social buttons -// -------------------------------------------------- -<% if (filters.facebookAuth) { %> -.btn-facebook { - .button-variant(@btnText; @btnFacebookBackgroundHighlight; @btnFacebookBackgroundHighlight); -}<% } if (filters.twitterAuth) { %> -.btn-twitter { - .button-variant(@btnText; @btnTwitterBackground; @btnTwitterBackgroundHighlight); -}<% } if (filters.googleAuth) { %> -.btn-google-plus { - .button-variant(@btnText; @btnGooglePlusBackground; @btnGooglePlusBackgroundHighlight); -}<% } %> -.btn-github { - .button-variant(@btnTextAlt; @btnGithubBackground; @btnGithubBackgroundHighlight); -}<% } %><% } %> diff --git a/app/templates/client/app/account(auth)/login/login(sass).scss b/app/templates/client/app/account(auth)/login/login(sass).scss deleted file mode 100644 index 5b6956124..000000000 --- a/app/templates/client/app/account(auth)/login/login(sass).scss +++ /dev/null @@ -1,30 +0,0 @@ -<% if (filters.bootstrap) { %>// Colors -// -------------------------------------------------- - -$btnText: #fff; -$btnTextAlt: #000;<% if (filters.oauth) { %> -<% if (filters.facebookAuth) { %> -$btnFacebookBackground: #3B5998; -$btnFacebookBackgroundHighlight: #133783;<% } if (filters.twitterAuth) { %> -$btnTwitterBackground: #2daddc; -$btnTwitterBackgroundHighlight: #0271bf;<% } if (filters.googleAuth) { %> -$btnGooglePlusBackground: #dd4b39; -$btnGooglePlusBackgroundHighlight: #c53727;<% } %> -$btnGithubBackground: #fafafa; -$btnGithubBackgroundHighlight: #ccc; - -// Social buttons -// -------------------------------------------------- -<% if (filters.facebookAuth) { %> -.btn-facebook { - @include button-variant($btnText, $btnFacebookBackgroundHighlight, $btnFacebookBackgroundHighlight); -}<% } if (filters.twitterAuth) { %> -.btn-twitter { - @include button-variant($btnText, $btnTwitterBackground, $btnTwitterBackgroundHighlight); -}<% } if (filters.googleAuth) { %> -.btn-google-plus { - @include button-variant($btnText, $btnGooglePlusBackground, $btnGooglePlusBackgroundHighlight); -}<% } %> -.btn-github { - @include button-variant($btnTextAlt, $btnGithubBackground, $btnGithubBackgroundHighlight); -}<% } %><% } %> diff --git a/app/templates/client/app/account(auth)/login/login(stylus).styl b/app/templates/client/app/account(auth)/login/login(stylus).styl deleted file mode 100644 index 3dc78ee9d..000000000 --- a/app/templates/client/app/account(auth)/login/login(stylus).styl +++ /dev/null @@ -1,22 +0,0 @@ -<% if (filters.oauth) { %>// Social buttons -// -------------------------------------------------- -<% if (filters.facebookAuth) { %> -.btn-facebook - color: #fff; - background-color: #3B5998; - border-color: #133783; -<% } if (filters.twitterAuth) { %> -.btn-twitter - color: #fff; - background-color: #2daddc; - border-color: #0271bf; -<% } if (filters.googleAuth) { %> -.btn-google-plus - color: #fff; - background-color: #dd4b39; - border-color: #c53727; -<% } %> -.btn-github - color: #fff; - background-color: #fafafa; - border-color: #ccc;<% } %> diff --git a/app/templates/client/app/account(auth)/login/login.controller(coffee).coffee b/app/templates/client/app/account(auth)/login/login.controller(coffee).coffee index 7bcb69969..2ba501a42 100644 --- a/app/templates/client/app/account(auth)/login/login.controller(coffee).coffee +++ b/app/templates/client/app/account(auth)/login/login.controller(coffee).coffee @@ -1,7 +1,7 @@ 'use strict' angular.module '<%= scriptAppName %>' -.controller 'LoginCtrl', ($scope, Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %><% if (filters.oauth) {%>, $window<% } %>) -> +.controller 'LoginCtrl', ($scope, Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %>) -> $scope.user = {} $scope.errors = {} $scope.login = (form) -> @@ -18,6 +18,3 @@ angular.module '<%= scriptAppName %>' .catch (err) -> $scope.errors.other = err.message -<% if (filters.oauth) {%> - $scope.loginOauth = (provider) -> - $window.location.href = '/auth/' + provider<% } %> diff --git a/app/templates/client/app/account(auth)/login/login.controller(js).js b/app/templates/client/app/account(auth)/login/login.controller(js).js index 2417e62f4..6e9d5fd7b 100644 --- a/app/templates/client/app/account(auth)/login/login.controller(js).js +++ b/app/templates/client/app/account(auth)/login/login.controller(js).js @@ -1,7 +1,7 @@ 'use strict'; angular.module('<%= scriptAppName %>') - .controller('LoginCtrl', function($scope, Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %><% if (filters.oauth) { %>, $window<% } %>) { + .controller('LoginCtrl', function($scope, Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %>) { $scope.user = {}; $scope.errors = {}; @@ -22,8 +22,5 @@ angular.module('<%= scriptAppName %>') }); } }; -<% if (filters.oauth) {%> - $scope.loginOauth = function(provider) { - $window.location.href = '/auth/' + provider; - };<% } %> + }); diff --git a/app/templates/client/app/account(auth)/signup/signup(html).html b/app/templates/client/app/account(auth)/signup/signup(html).html index 0a95a7546..84f4451e0 100644 --- a/app/templates/client/app/account(auth)/signup/signup(html).html +++ b/app/templates/client/app/account(auth)/signup/signup(html).html @@ -74,18 +74,12 @@

Sign up

Login -<% if (filters.oauth) {%> -
-
<% if (filters.facebookAuth) {%> - - Connect with Facebook - <% } %><% if (filters.googleAuth) {%> - - Connect with Google+ - <% } %><% if (filters.twitterAuth) {%> - - Connect with Twitter - <% } %> +<% if (filters.oauth) { %> +
+
+
+ +
<% } %>
diff --git a/app/templates/client/app/account(auth)/signup/signup(jade).jade b/app/templates/client/app/account(auth)/signup/signup(jade).jade index 2b9fda0c5..139dd2941 100644 --- a/app/templates/client/app/account(auth)/signup/signup(jade).jade +++ b/app/templates/client/app/account(auth)/signup/signup(jade).jade @@ -53,20 +53,11 @@ navbar = ' ' a.btn.btn-default.btn-lg.btn-login(<% if (filters.uirouter) { %>ui-sref='login'<% } else { %>href='http://github.com/login'<% } %>) | Login - <% if (filters.oauth) {%> hr - div<% if (filters.facebookAuth) {%> - a.btn.btn-facebook(href='', ng-click='loginOauth("facebook")') - i.fa.fa-facebook - | Connect with Facebook - = ' '<% } %><% if (filters.googleAuth) {%> - a.btn.btn-google-plus(href='', ng-click='loginOauth("google")') - i.fa.fa-google-plus - | Connect with Google+ - = ' '<% } %><% if (filters.twitterAuth) {%> - a.btn.btn-twitter(href='', ng-click='loginOauth("twitter")') - i.fa.fa-twitter - | Connect with Twitter<% } %><% } %> + .row + .col-sm-4.col-md-3 + oauth-buttons(classes='btn-block') +<% } %> hr diff --git a/app/templates/client/app/account(auth)/signup/signup.controller(coffee).coffee b/app/templates/client/app/account(auth)/signup/signup.controller(coffee).coffee index d167b7e30..68952a74d 100644 --- a/app/templates/client/app/account(auth)/signup/signup.controller(coffee).coffee +++ b/app/templates/client/app/account(auth)/signup/signup.controller(coffee).coffee @@ -1,7 +1,7 @@ 'use strict' angular.module '<%= scriptAppName %>' -.controller 'SignupCtrl', ($scope, Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %><% if (filters.oauth) {%>, $window<% } %>) -> +.controller 'SignupCtrl', ($scope, Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %>) -> $scope.user = {} $scope.errors = {} $scope.register = (form) -> @@ -31,6 +31,3 @@ angular.module '<%= scriptAppName %>' angular.forEach err.fields, (field) -> form[field].$setValidity 'mongoose', false $scope.errors[field] = err.message<% } %> -<% if (filters.oauth) {%> - $scope.loginOauth = (provider) -> - $window.location.href = '/auth/' + provider<% } %> diff --git a/app/templates/client/app/account(auth)/signup/signup.controller(js).js b/app/templates/client/app/account(auth)/signup/signup.controller(js).js index 346eb7ea7..405461a1f 100644 --- a/app/templates/client/app/account(auth)/signup/signup.controller(js).js +++ b/app/templates/client/app/account(auth)/signup/signup.controller(js).js @@ -1,7 +1,7 @@ 'use strict'; angular.module('<%= scriptAppName %>') - .controller('SignupCtrl', function($scope, Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %><% if (filters.oauth) { %>, $window<% } %>) { + .controller('SignupCtrl', function($scope, Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %>) { $scope.user = {}; $scope.errors = {}; @@ -38,8 +38,5 @@ angular.module('<%= scriptAppName %>') }); } }; -<% if (filters.oauth) {%> - $scope.loginOauth = function(provider) { - $window.location.href = '/auth/' + provider; - };<% } %> + }); diff --git a/app/templates/client/app/app(less).less b/app/templates/client/app/app(less).less index cbfffbe88..9cfcfdb16 100644 --- a/app/templates/client/app/app(less).less +++ b/app/templates/client/app/app(less).less @@ -1,5 +1,6 @@ -<% if (filters.bootstrap) { %>@import 'http://github.com/bower_components/bootstrap/less/bootstrap.less';<% } %> -@import 'http://github.com/bower_components/font-awesome/less/font-awesome.less'; +<% if (filters.bootstrap) { %>@import 'http://github.com/bower_components/bootstrap/less/bootstrap.less'; +<% if(filters.oauth) { %>@import 'http://github.com/bower_components/bootstrap-social/bootstrap-social.less'; +<% }} %>@import 'http://github.com/bower_components/font-awesome/less/font-awesome.less'; <% if (filters.bootstrap) { %>@icon-font-path: '../bower_components/bootstrap/fonts/';<% } %> @fa-font-path: '../bower_components/font-awesome/fonts'; diff --git a/app/templates/client/app/app(sass).scss b/app/templates/client/app/app(sass).scss index 889878aee..e20f3f0ad 100644 --- a/app/templates/client/app/app(sass).scss +++ b/app/templates/client/app/app(sass).scss @@ -1,7 +1,7 @@ -<% if (filters.bootstrap) { %>$icon-font-path: "../bower_components/bootstrap-sass-official/vendor/assets/fonts/bootstrap/";<% } %> -$fa-font-path: "../bower_components/font-awesome/fonts"; -<% if (filters.bootstrap) { %> -@import 'http://github.com/bower_components/bootstrap-sass-official/vendor/assets/stylesheets/bootstrap';<% } %> +<% if (filters.bootstrap) { %>$icon-font-path: "../bower_components/bootstrap-sass-official/vendor/assets/fonts/bootstrap/"; +@import 'http://github.com/bower_components/bootstrap-sass-official/vendor/assets/stylesheets/bootstrap'; +<% if(filters.oauth) { %>@import 'http://github.com/bower_components/bootstrap-social/bootstrap-social.scss'; +<% }} %>$fa-font-path: "../bower_components/font-awesome/fonts"; @import 'http://github.com/bower_components/font-awesome/scss/font-awesome'; /** diff --git a/app/templates/client/app/app(stylus).styl b/app/templates/client/app/app(stylus).styl index d25cdfc59..de156ca97 100644 --- a/app/templates/client/app/app(stylus).styl +++ b/app/templates/client/app/app(stylus).styl @@ -1,6 +1,7 @@ @import "http://github.com/bower_components/font-awesome/css/font-awesome.css" <% if (filters.bootstrap) { %>@import "http://github.com/bower_components/bootstrap/dist/css/bootstrap.css" - +<% if (filters.oauth) { %>@import "http://github.com/bower_components/bootstrap-social/bootstrap-social.css" +<% } %> // // Bootstrap Fonts // diff --git a/app/templates/client/components/oauth-buttons(oauth)/oath-buttons(html).html b/app/templates/client/components/oauth-buttons(oauth)/oath-buttons(html).html new file mode 100644 index 000000000..5ea19425f --- /dev/null +++ b/app/templates/client/components/oauth-buttons(oauth)/oath-buttons(html).html @@ -0,0 +1,12 @@ +<% if(filters.facebookAuth) { %> + + Connect with Facebook + +<% } if (filters.googleAuth) { %> + + Connect with Google+ + +<% } if (filters.twitterAuth) { %> + + Connect with Twitter +<% } %> diff --git a/app/templates/client/app/account(auth)/login/login(css).css b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons(css).css similarity index 61% rename from app/templates/client/app/account(auth)/login/login(css).css rename to app/templates/client/components/oauth-buttons(oauth)/oauth-buttons(css).css index 7c865ffc6..be33316e0 100644 --- a/app/templates/client/app/account(auth)/login/login(css).css +++ b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons(css).css @@ -1,22 +1,19 @@ -<% if (filters.oauth) { %><% if (filters.facebookAuth) { %>.btn-facebook { +<% if (!filters.bootstrap) { if (filters.facebookAuth) { %>.btn-facebook { color: #fff; background-color: #3B5998; border-color: #133783; } -<% } if (filters.twitterAuth) { %> -.btn-twitter { - color: #fff; - background-color: #2daddc; - border-color: #0271bf; -} -<% } if (filters.googleAuth) { %> -.btn-google-plus { +<% } if (filters.googleAuth) { %>.btn-google { color: #fff; background-color: #dd4b39; border-color: #c53727; } -<% } %> -.btn-github { +<% } if (filters.twitterAuth) { %>.btn-twitter { + color: #fff; + background-color: #2daddc; + border-color: #0271bf; +} +<% } %>.btn-github { color: #fff; background-color: #fafafa; border-color: #ccc; diff --git a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons(jade).jade b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons(jade).jade new file mode 100644 index 000000000..fd5030bd7 --- /dev/null +++ b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons(jade).jade @@ -0,0 +1,14 @@ +<% if(filters.facebookAuth) { %>a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.btn-facebook(ng-class='classes' + ng-click='OauthButtons.loginOauth("facebook")') + i.fa.fa-facebook + | Connect with Facebook + +<% } if(filters.googleAuth) { %>a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.btn-google(ng-class='classes' + ng-click='OauthButtons.loginOauth("google")') + i.fa.fa-google-plus + | Connect with Google+ + +<% } if(filters.twitterAuth) { %>a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.btn-twitter(ng-class='classes' + ng-click='OauthButtons.loginOauth("twitter")') + i.fa.fa-twitter + | Connect with Twitter<% } %> diff --git a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons(less).less b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons(less).less new file mode 100644 index 000000000..be33316e0 --- /dev/null +++ b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons(less).less @@ -0,0 +1,20 @@ +<% if (!filters.bootstrap) { if (filters.facebookAuth) { %>.btn-facebook { + color: #fff; + background-color: #3B5998; + border-color: #133783; +} +<% } if (filters.googleAuth) { %>.btn-google { + color: #fff; + background-color: #dd4b39; + border-color: #c53727; +} +<% } if (filters.twitterAuth) { %>.btn-twitter { + color: #fff; + background-color: #2daddc; + border-color: #0271bf; +} +<% } %>.btn-github { + color: #fff; + background-color: #fafafa; + border-color: #ccc; +}<% } %> diff --git a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons(sass).scss b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons(sass).scss new file mode 100644 index 000000000..be33316e0 --- /dev/null +++ b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons(sass).scss @@ -0,0 +1,20 @@ +<% if (!filters.bootstrap) { if (filters.facebookAuth) { %>.btn-facebook { + color: #fff; + background-color: #3B5998; + border-color: #133783; +} +<% } if (filters.googleAuth) { %>.btn-google { + color: #fff; + background-color: #dd4b39; + border-color: #c53727; +} +<% } if (filters.twitterAuth) { %>.btn-twitter { + color: #fff; + background-color: #2daddc; + border-color: #0271bf; +} +<% } %>.btn-github { + color: #fff; + background-color: #fafafa; + border-color: #ccc; +}<% } %> diff --git a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons(stylus).styl b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons(stylus).styl new file mode 100644 index 000000000..995d4c766 --- /dev/null +++ b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons(stylus).styl @@ -0,0 +1,16 @@ +<% if (!filters.bootstrap) { if (filters.facebookAuth) { %>.btn-facebook + color #fff + background-color #3B5998 + border-color #133783 +<% } if (filters.googleAuth) { %>.btn-google + color #fff + background-color #dd4b39 + border-color #c53727 +<% } if (filters.twitterAuth) { %>.btn-twitter + color #fff + background-color #2daddc + border-color #0271bf +<% } %>.btn-github + color #fff + background-color #fafafa + border-color #ccc<% } %> diff --git a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller(coffee).coffee b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller(coffee).coffee new file mode 100644 index 000000000..4dca2832f --- /dev/null +++ b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller(coffee).coffee @@ -0,0 +1,7 @@ +'use strict' + +angular.module('<%= scriptAppName %>') +.controller 'OauthButtonsCtrl', ($window) -> + @loginOauth = (provider) -> + $window.location.href = '/auth/' + provider + return; diff --git a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller(js).js b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller(js).js new file mode 100644 index 000000000..36d5d6467 --- /dev/null +++ b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller(js).js @@ -0,0 +1,8 @@ +'use strict'; + +angular.module('<%= scriptAppName %>') + .controller('OauthButtonsCtrl', function($window) { + this.loginOauth = function(provider) { + $window.location.href = '/auth/' + provider; + }; + }); diff --git a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller.spec(coffee).coffee b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller.spec(coffee).coffee new file mode 100644 index 000000000..59b4dd9e4 --- /dev/null +++ b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller.spec(coffee).coffee @@ -0,0 +1,20 @@ +'use strict' + +describe 'Controller: OauthButtonsCtrl', -> + # load the controller's module + beforeEach module('<%= scriptAppName %>') + + OauthButtonsCtrl = null + $window = null + + # Initialize the controller and a mock $window + beforeEach inject ($controller) -> + $window = location: {} + OauthButtonsCtrl = $controller 'OauthButtonsCtrl', $window: $window + return + + it 'should attach loginOauth', -><% if (filters.jasmine) { %> + expect(OauthButtonsCtrl.loginOauth).toEqual jasmine.any Function<% } if (filters.mocha) { %> + <%= expect() %>OauthButtonsCtrl.loginOauth<%= to() %>.be.a 'function' <% } %> + return + return diff --git a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller.spec(js).js b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller.spec(js).js new file mode 100644 index 000000000..144745e5e --- /dev/null +++ b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller.spec(js).js @@ -0,0 +1,25 @@ +'use strict'; + +describe('Controller: OauthButtonsCtrl', function() { + + // load the controller's module + beforeEach(module('<%= scriptAppName %>')); + + var OauthButtonsCtrl, $window; + + // Initialize the controller and a mock $window + beforeEach(inject(function($controller) { + $window = { + location: {} + }; + + OauthButtonsCtrl = $controller('OauthButtonsCtrl', { + $window: $window + }); + })); + + it('should attach loginOauth', function() {<% if (filters.jasmine) { %> + expect(OauthButtonsCtrl.loginOauth).toEqual(jasmine.any(Function));<% } if (filters.mocha) { %> + <%= expect() %>OauthButtonsCtrl.loginOauth<%= to() %>.be.a('function');<% } %> + }); +}); diff --git a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive(coffee).coffee b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive(coffee).coffee new file mode 100644 index 000000000..f009e5b1d --- /dev/null +++ b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive(coffee).coffee @@ -0,0 +1,9 @@ +'use strict' + +angular.module('<%= scriptAppName %>') +.directive 'oauthButtons', -> + templateUrl: 'components/oauth-buttons/oauth-buttons.html' + restrict: 'EA' + controller: 'OauthButtonsCtrl' + controllerAs: 'OauthButtons' + scope: classes: '@' diff --git a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive(js).js b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive(js).js new file mode 100644 index 000000000..401f669e3 --- /dev/null +++ b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive(js).js @@ -0,0 +1,14 @@ +'use strict'; + +angular.module('<%= scriptAppName %>') + .directive('oauthButtons', function() { + return { + templateUrl: 'components/oauth-buttons/oauth-buttons.html', + restrict: 'EA', + controller: 'OauthButtonsCtrl', + controllerAs: 'OauthButtons', + scope: { + classes: '@' + } + }; + }); diff --git a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive.spec(coffee).coffee b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive.spec(coffee).coffee new file mode 100644 index 000000000..903d05476 --- /dev/null +++ b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive.spec(coffee).coffee @@ -0,0 +1,51 @@ +'use strict' + +describe 'Directive: oauthButtons', -> + # load the directive's module and view + beforeEach module('<%= scriptAppName %>') + beforeEach module('components/oauth-buttons/oauth-buttons.html') + + element = null + parentScope = null + elementScope = null + + compileDirective = (template) -> + inject ($compile) -> + element = angular.element template + element = $compile(element) parentScope + parentScope.$digest() + elementScope = element.isolateScope() + + beforeEach inject ($rootScope) -> + parentScope = $rootScope.$new() + + it 'should contain anchor buttons', -> + compileDirective ''<% if (filters.jasmine) { %> + expect(element.find('a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>').length).toBeGreaterThan 0<% } if (filters.mocha) { %> + <%= expect() %>element.find('a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>').length<%= to() %>.be.at.least 1<% } %> + return + + it 'should evaluate and bind the classes attribute to scope.classes', -> + parentScope.scopedClass = 'scopedClass1' + compileDirective ''<% if (filters.jasmine) { %> + expect(elementScope.classes).toEqual 'testClass1 scopedClass1'<% } if (filters.mocha) { %> + <%= expect() %>elementScope.classes<%= to() %>.equal 'testClass1 scopedClass1'<% } %> + return + + it 'should bind scope.classes to class names on the anchor buttons', -> + compileDirective '' + + # Add classes + elementScope.classes = 'testClass1 testClass2' + elementScope.$digest()<% if (filters.jasmine) { %> + expect(element.find('a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.testClass1.testClass2').length).toBeGreaterThan 0<% } if (filters.mocha) { %> + <%= expect() %>element.find('a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.testClass1.testClass2').length<%= to() %>.be.at.least 1<% } %> + + # Remove classes + elementScope.classes = '' + elementScope.$digest()<% if (filters.jasmine) { %> + expect(element.find('a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.testClass1.testClass2').length).toEqual 0<% } if (filters.mocha) { %> + <%= expect() %>element.find('a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.testClass1.testClass2').length<%= to() %>.equal 0<% } %> + + return + return diff --git a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive.spec(js).js b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive.spec(js).js new file mode 100644 index 000000000..14682cc6e --- /dev/null +++ b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive.spec(js).js @@ -0,0 +1,51 @@ +'use strict'; + +describe('Directive: oauthButtons', function() { + + // load the directive's module and view + beforeEach(module('<%= scriptAppName %>')); + beforeEach(module('components/oauth-buttons/oauth-buttons.html')); + + var element, parentScope, elementScope; + + var compileDirective = function(template) { + inject(function($compile) { + element = angular.element(template); + element = $compile(element)(parentScope); + parentScope.$digest(); + elementScope = element.isolateScope(); + }); + }; + + beforeEach(inject(function($rootScope) { + parentScope = $rootScope.$new(); + })); + + it('should contain anchor buttons', function() { + compileDirective('');<% if (filters.jasmine) { %> + expect(element.find('a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>').length).toBeGreaterThan(0);<% } if (filters.mocha) { %> + <%= expect() %>element.find('a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>').length<%= to() %>.be.at.least(1);<% } %> + }); + + it('should evaluate and bind the classes attribute to scope.classes', function() { + parentScope.scopedClass = 'scopedClass1'; + compileDirective('');<% if (filters.jasmine) { %> + expect(elementScope.classes).toEqual('testClass1 scopedClass1');<% } if (filters.mocha) { %> + <%= expect() %>elementScope.classes<%= to() %>.equal('testClass1 scopedClass1');<% } %> + }); + + it('should bind scope.classes to class names on the anchor buttons', function() { + compileDirective(''); + // Add classes + elementScope.classes = 'testClass1 testClass2'; + elementScope.$digest();<% if (filters.jasmine) { %> + expect(element.find('a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.testClass1.testClass2').length).toBeGreaterThan(0);<% } if (filters.mocha) { %> + <%= expect() %>element.find('a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.testClass1.testClass2').length<%= to() %>.be.at.least(1);<% } %> + + // Remove classes + elementScope.classes = ''; + elementScope.$digest();<% if (filters.jasmine) { %> + expect(element.find('a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.testClass1.testClass2').length).toEqual(0);<% } if (filters.mocha) { %> + <%= expect() %>element.find('a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.testClass1.testClass2').length<%= to() %>.equal(0);<% } %> + }); +}); diff --git a/app/templates/e2e/account(auth)/login/login.po.js b/app/templates/e2e/account(auth)/login/login.po.js index 1186cdb6b..045204754 100644 --- a/app/templates/e2e/account(auth)/login/login.po.js +++ b/app/templates/e2e/account(auth)/login/login.po.js @@ -6,20 +6,21 @@ 'use strict'; var LoginPage = function() { - this.form = element(by.css('.form')); - this.form.email = this.form.element(by.model('user.email')); - this.form.password = this.form.element(by.model('user.password')); - this.form.submit = this.form.element(by.css('.btn-login')); + var form = this.form = element(by.css('.form')); + form.email = form.element(by.model('user.email')); + form.password = form.element(by.model('user.password')); + form.submit = form.element(by.css('.btn-login'));<% if (filters.oauth) { %> + form.oauthButtons = require('../../components/oauth-buttons/oauth-buttons.po').oauthButtons;<% } %> this.login = function(data) { for (var prop in data) { - var formElem = this.form[prop]; + var formElem = form[prop]; if (data.hasOwnProperty(prop) && formElem && typeof formElem.sendKeys === 'function') { formElem.sendKeys(data[prop]); } } - this.form.submit.click(); + form.submit.click(); }; }; diff --git a/app/templates/e2e/account(auth)/login/login.spec(jasmine).js b/app/templates/e2e/account(auth)/login/login.spec(jasmine).js index 568074ccc..6a65fc7cb 100644 --- a/app/templates/e2e/account(auth)/login/login.spec(jasmine).js +++ b/app/templates/e2e/account(auth)/login/login.spec(jasmine).js @@ -36,7 +36,16 @@ describe('Login View', function() { expect(page.form.password.getAttribute('name')).toBe('password'); expect(page.form.submit.getAttribute('type')).toBe('submit'); expect(page.form.submit.getText()).toBe('Login'); - }); + });<% if (filters.oauth) { %> + + it('should include oauth buttons with correct classes applied', function() {<% if (filters.facebookAuth) { %> + expect(page.form.oauthButtons.facebook.getText()).toBe('Connect with Facebook'); + expect(page.form.oauthButtons.facebook.getAttribute('class')).toMatch('btn-block');<% } if (filters.googleAuth) { %> + expect(page.form.oauthButtons.google.getText()).toBe('Connect with Google+'); + expect(page.form.oauthButtons.google.getAttribute('class')).toMatch('btn-block');<% } if (filters.twitterAuth) { %> + expect(page.form.oauthButtons.twitter.getText()).toBe('Connect with Twitter'); + expect(page.form.oauthButtons.twitter.getAttribute('class')).toMatch('btn-block');<% } %> + });<% } %> describe('with local auth', function() { diff --git a/app/templates/e2e/account(auth)/login/login.spec(mocha).js b/app/templates/e2e/account(auth)/login/login.spec(mocha).js index 94268a12e..1fefea5d0 100644 --- a/app/templates/e2e/account(auth)/login/login.spec(mocha).js +++ b/app/templates/e2e/account(auth)/login/login.spec(mocha).js @@ -41,7 +41,16 @@ describe('Login View', function() { <%= expect() %>page.form.password.getAttribute('name')<%= to() %>.eventually.equal('password'); <%= expect() %>page.form.submit.getAttribute('type')<%= to() %>.eventually.equal('submit'); <%= expect() %>page.form.submit.getText()<%= to() %>.eventually.equal('Login'); - }); + });<% if (filters.oauth) { %> + + it('should include oauth buttons with correct classes applied', function() {<% if (filters.facebookAuth) { %> + <%= expect() %>page.form.oauthButtons.facebook.getText()<%= to() %>.eventually.equal('Connect with Facebook'); + <%= expect() %>page.form.oauthButtons.facebook.getAttribute('class')<%= to() %>.eventually.contain('btn-block');<% } if (filters.googleAuth) { %> + <%= expect() %>page.form.oauthButtons.google.getText()<%= to() %>.eventually.equal('Connect with Google+'); + <%= expect() %>page.form.oauthButtons.google.getAttribute('class')<%= to() %>.eventually.contain('btn-block');<% } if (filters.twitterAuth) { %> + <%= expect() %>page.form.oauthButtons.twitter.getText()<%= to() %>.eventually.equal('Connect with Twitter'); + <%= expect() %>page.form.oauthButtons.twitter.getAttribute('class')<%= to() %>.eventually.contain('btn-block');<% } %> + });<% } %> describe('with local auth', function() { diff --git a/app/templates/e2e/account(auth)/signup/signup.po.js b/app/templates/e2e/account(auth)/signup/signup.po.js index e57536915..3a812266c 100644 --- a/app/templates/e2e/account(auth)/signup/signup.po.js +++ b/app/templates/e2e/account(auth)/signup/signup.po.js @@ -6,22 +6,23 @@ 'use strict'; var SignupPage = function() { - this.form = element(by.css('.form')); - this.form.name = this.form.element(by.model('user.name')); - this.form.email = this.form.element(by.model('user.email')); - this.form.password = this.form.element(by.model('user.password')); - this.form.confirmPassword = this.form.element(by.model('user.confirmPassword')) - this.form.submit = this.form.element(by.css('.btn-register')); + var form = this.form = element(by.css('.form')); + form.name = form.element(by.model('user.name')); + form.email = form.element(by.model('user.email')); + form.password = form.element(by.model('user.password')); + form.confirmPassword = form.element(by.model('user.confirmPassword')); + form.submit = form.element(by.css('.btn-register'));<% if (filters.oauth) { %> + form.oauthButtons = require('../../components/oauth-buttons/oauth-buttons.po').oauthButtons;<% } %> this.signup = function(data) { for (var prop in data) { - var formElem = this.form[prop]; + var formElem = form[prop]; if (data.hasOwnProperty(prop) && formElem && typeof formElem.sendKeys === 'function') { formElem.sendKeys(data[prop]); } } - this.form.submit.click(); + form.submit.click(); }; }; diff --git a/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js b/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js index b86749330..903c89817 100644 --- a/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js +++ b/app/templates/e2e/account(auth)/signup/signup.spec(jasmine).js @@ -35,7 +35,16 @@ describe('Signup View', function() { expect(page.form.confirmPassword.getAttribute('name')).toBe('confirmPassword'); expect(page.form.submit.getAttribute('type')).toBe('submit'); expect(page.form.submit.getText()).toBe('Sign up'); - }); + });<% if (filters.oauth) { %> + + it('should include oauth buttons with correct classes applied', function() {<% if (filters.facebookAuth) { %> + expect(page.form.oauthButtons.facebook.getText()).toBe('Connect with Facebook'); + expect(page.form.oauthButtons.facebook.getAttribute('class')).toMatch('btn-block');<% } if (filters.googleAuth) { %> + expect(page.form.oauthButtons.google.getText()).toBe('Connect with Google+'); + expect(page.form.oauthButtons.google.getAttribute('class')).toMatch('btn-block');<% } if (filters.twitterAuth) { %> + expect(page.form.oauthButtons.twitter.getText()).toBe('Connect with Twitter'); + expect(page.form.oauthButtons.twitter.getAttribute('class')).toMatch('btn-block');<% } %> + });<% } %> describe('with local auth', function() { diff --git a/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js b/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js index e15385192..7578d2796 100644 --- a/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js +++ b/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js @@ -40,7 +40,16 @@ describe('Signup View', function() { <%= expect() %>page.form.confirmPassword.getAttribute('name')<%= to() %>.eventually.equal('confirmPassword'); <%= expect() %>page.form.submit.getAttribute('type')<%= to() %>.eventually.equal('submit'); <%= expect() %>page.form.submit.getText()<%= to() %>.eventually.equal('Sign up'); - }); + });<% if (filters.oauth) { %> + + it('should include oauth buttons with correct classes applied', function() {<% if (filters.facebookAuth) { %> + <%= expect() %>page.form.oauthButtons.facebook.getText()<%= to() %>.eventually.equal('Connect with Facebook'); + <%= expect() %>page.form.oauthButtons.facebook.getAttribute('class')<%= to() %>.eventually.contain('btn-block');<% } if (filters.googleAuth) { %> + <%= expect() %>page.form.oauthButtons.google.getText()<%= to() %>.eventually.equal('Connect with Google+'); + <%= expect() %>page.form.oauthButtons.google.getAttribute('class')<%= to() %>.eventually.contain('btn-block');<% } if (filters.twitterAuth) { %> + <%= expect() %>page.form.oauthButtons.twitter.getText()<%= to() %>.eventually.equal('Connect with Twitter'); + <%= expect() %>page.form.oauthButtons.twitter.getAttribute('class')<%= to() %>.eventually.contain('btn-block');<% } %> + });<% } %> describe('with local auth', function() { diff --git a/app/templates/e2e/components/oauth-buttons(oauth)/oauth-buttons.po.js b/app/templates/e2e/components/oauth-buttons(oauth)/oauth-buttons.po.js new file mode 100644 index 000000000..c25d2b994 --- /dev/null +++ b/app/templates/e2e/components/oauth-buttons(oauth)/oauth-buttons.po.js @@ -0,0 +1,15 @@ +/** + * This file uses the Page Object pattern to define the main page for tests + * https://docs.google.com/presentation/d/1B6manhG0zEXkC-H-tPo2vwU06JhL8w9-XCF9oehXzAQ + */ + +'use strict'; + +var OauthButtons = function() { + var oauthButtons = this.oauthButtons = element(by.css('oauth-buttons'));<% if (filters.facebookAuth) { %> + oauthButtons.facebook = oauthButtons.element(by.css('.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.btn-facebook'));<% } if (filters.googleAuth) { %> + oauthButtons.google = oauthButtons.element(by.css('.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.btn-google'));<% } if (filters.twitterAuth) { %> + oauthButtons.twitter = oauthButtons.element(by.css('.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.btn-twitter'));<% } %> +}; + +module.exports = new OauthButtons(); diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 1f2162142..cca66a78f 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -258,7 +258,6 @@ describe('angular-fullstack generator', function () { files = files.concat([ 'client/app/account/account.' + script, 'client/app/account/login/login.' + markup, - 'client/app/account/login/login.' + stylesheet, 'client/app/account/login/login.controller.' + script, 'client/app/account/settings/settings.' + markup, 'client/app/account/settings/settings.controller.' + script, @@ -290,11 +289,22 @@ describe('angular-fullstack generator', function () { ]); } - /* OAuth (see oauthFiles function above) */ - if (ops.oauth) { + if (ops.oauth && ops.oauth.length) { + /* OAuth (see oauthFiles function above) */ ops.oauth.forEach(function(type, i) { files = files.concat(oauthFiles(type.replace('Auth', ''))); }); + + + files = files.concat([ + 'client/components/oauth-buttons/oauth-buttons.' + stylesheet, + 'client/components/oauth-buttons/oauth-buttons.' + markup, + 'client/components/oauth-buttons/oauth-buttons.controller.' + script, + 'client/components/oauth-buttons/oauth-buttons.controller.spec.' + script, + 'client/components/oauth-buttons/oauth-buttons.directive.' + script, + 'client/components/oauth-buttons/oauth-buttons.directive.spec.' + script, + 'e2e/components/oauth-buttons/oauth-buttons.po.js' + ]); } /* Socket.IO */ From 8e21ce983daa839bbeb6429957a16006fbf07a45 Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 8 Sep 2015 17:14:27 -0400 Subject: [PATCH 0258/1357] fix(app): add `jasmine` to `.jshintrc` globals --- app/templates/client/.jshintrc | 3 ++- app/templates/server/.jshintrc-spec | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/templates/client/.jshintrc b/app/templates/client/.jshintrc index 8c5c42c0a..07b9d3793 100644 --- a/app/templates/client/.jshintrc +++ b/app/templates/client/.jshintrc @@ -22,7 +22,8 @@ "console": true, "$": true, "_": true, - "moment": true, + "moment": true,<% if (filters.jasmine) { %> + "jasmine": true,<% } %> "describe": true, "beforeEach": true, "module": true, diff --git a/app/templates/server/.jshintrc-spec b/app/templates/server/.jshintrc-spec index b9390c374..8c9871ce0 100644 --- a/app/templates/server/.jshintrc-spec +++ b/app/templates/server/.jshintrc-spec @@ -1,6 +1,7 @@ { "extends": ".jshintrc", - "globals": { + "globals": {<% if (filters.jasmine) { %> + "jasmine": true,<% } %> "describe": true, "it": true, "before": true, From 53e9a22f92b5139bcd78f7ad1819ae4268fe1bab Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 8 Sep 2015 19:39:31 -0400 Subject: [PATCH 0259/1357] 3.0.0-rc7-patch.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3c7fad767..7c388605e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "generator-angular-fullstack", - "version": "3.0.0-rc7", + "version": "3.0.0-rc7-patch.0", "description": "Yeoman generator for creating MEAN stack applications, using MongoDB, Express, AngularJS, and Node", "keywords": [ "yeoman-generator", From 36593a533f6d868553f7a08dae93bd9b5e389c43 Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 8 Sep 2015 20:34:58 -0400 Subject: [PATCH 0260/1357] feat(gen): add `updateSubmodules` task and run it `beforeBump` --- Gruntfile.js | 59 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 64198cda7..47b889e8f 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -31,6 +31,7 @@ module.exports = function (grunt) { commitMessage: '<%= version %>', tagName: '<%= version %>', file: 'package.json', + beforeBump: ['updateSubmodules'], afterBump: ['updateFixtures:deps', 'commitNgFullstackDeps'], beforeRelease: ['stage'], push: false, @@ -38,6 +39,11 @@ module.exports = function (grunt) { npm: false } }, + updateSubmodules: { + options: { + modules: ['angular-fullstack-deps'] + } + }, commitNgFullstackDeps: { options: { cwd: 'angular-fullstack-deps', @@ -113,12 +119,47 @@ module.exports = function (grunt) { } }); - grunt.registerTask('stage', 'git add files before running the release task', function () { - var files = grunt.config('stage.options').files, done = this.async(); + function gitCmd(args, opts, done) { grunt.util.spawn({ cmd: process.platform === 'win32' ? 'git.cmd' : 'git', - args: ['add'].concat(files) + args: args, + opts: opts || {} }, done); + } + function gitCmdAsync(args, opts) { + return function() { + var deferred = Q.defer(); + gitCmd(args, opts, function(err) { + if (err) { return deferred.reject(err); } + deferred.resolve(); + }); + return deferred.promise; + }; + } + + grunt.registerTask('stage', 'git add files before running the release task', function () { + var files = grunt.config('stage.options').files; + gitCmd(['add'].concat(files), {}, this.async()); + }); + + grunt.registerTask('updateSubmodules', function() { + grunt.config.requires('updateSubmodules.options.modules'); + var modules = grunt.config.get('updateSubmodules').options.modules; + + Q() + .then(gitCmdAsync(['submodule', 'update', '--init', '--recursive'])) + .then(function() { + var thens = []; + for (var i = 0, modulesLength = modules.length; i < modulesLength; i++) { + var opts = {cwd: modules[i]}; + thens.push(gitCmdAsync(['checkout', 'master'], opts)); + thens.push(gitCmdAsync(['fetch'], opts)); + thens.push(gitCmdAsync(['pull'], opts)); + } + return thens.reduce(Q.when, Q()); + }) + .catch(grunt.fail.fatal.bind(grunt.fail)) + .finally(this.async()); }); grunt.registerTask('commitNgFullstackDeps', function() { @@ -129,15 +170,9 @@ module.exports = function (grunt) { var ops = grunt.config.get('commitNgFullstackDeps').options; var version = require('./package.json').version || 'NO VERSION SET'; if (Array.isArray(ops.files) && ops.files.length > 0) { - var done = this.async(); - var cwd = path.resolve(__dirname, ops.cwd); - grunt.util.spawn({ - cmd: process.platform === 'win32' ? 'git.cmd' : 'git', - args: ['commit', '-m', version].concat(ops.files), - opts: { - cwd: cwd - } - }, done); + gitCmd(['commit', '-m', version].concat(ops.files), { + cwd: path.resolve(__dirname, ops.cwd) + }, this.async()); } else { grunt.log.writeln('No files were commited'); } From f554c0dd0f465a499c73cc896241375284fc9978 Mon Sep 17 00:00:00 2001 From: Cody Mize Date: Tue, 8 Sep 2015 20:52:05 -0400 Subject: [PATCH 0261/1357] docs(gen): add releasing section --- contributing.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/contributing.md b/contributing.md index b46bd1c63..037a6b78f 100644 --- a/contributing.md +++ b/contributing.md @@ -70,3 +70,29 @@ reference GitHub issues that this commit **Closes**. A detailed explanation can be found in this [document][commit-message-format]. [commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y + +# Releasing +*(for contributors with push access)* + +The `grunt release` task will do most of the work for you, see [`grunt-release`](https://github.com/geddski/grunt-release) for semver usage. + +* Manually bump `package.json` version. + +*note: this step will be removed once `3.0.0` is released* + +* Run the release task `grunt release`. + +*note: once `3.0.0` is released you will need to use a valid `grunt-release` target, see [here](https://github.com/geddski/grunt-release#using-grunt-release)* + +* Push and publish the `angular-fullstack-deps` submodule. +```bash +$ cd angular-fullstack-deps +$ git push && npm publish +$ cd .. +``` + +* Push and publish `generator-angular-fullstack`. +```bash +$ git push && git push --tags +$ npm publish +``` From 4de144aabca9d1b3e0ea2c9ee803e8c46eb64e72 Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 8 Sep 2015 22:30:39 -0400 Subject: [PATCH 0262/1357] chore(all): update grunt-build-control to `^0.6.0` --- app/templates/_package.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index cfecfbbd6..8017603f3 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -68,7 +68,7 @@ "grunt-protractor-runner": "^2.0.0", "grunt-injector": "^0.6.0", "grunt-karma": "~0.12.0", - "grunt-build-control": "^0.5.0",<% if(filters.sass) { %> + "grunt-build-control": "^0.6.0",<% if(filters.sass) { %> "grunt-contrib-sass": "^0.9.0",<% } %><% if(filters.stylus) { %> "grunt-contrib-stylus": "latest",<% } %> "jit-grunt": "^0.9.1", diff --git a/package.json b/package.json index 7c388605e..f8e004ed3 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "devDependencies": { "chai": "^3.2.0", "grunt": "~0.4.1", - "grunt-build-control": "^0.5.0", + "grunt-build-control": "^0.6.0", "grunt-contrib-clean": "^0.6.0", "grunt-contrib-jshint": "^0.11.2", "grunt-conventional-changelog": "~1.0.0", From ed974c23515d886d4c6549376ff5fe071053912a Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 8 Sep 2015 21:59:49 -0400 Subject: [PATCH 0263/1357] chore(gen): ensure description is above the fold [ci skip] --- readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index c1a5793f6..f4ccb9ba7 100644 --- a/readme.md +++ b/readme.md @@ -4,10 +4,11 @@ [![Dependency Status](https://david-dm.org/daftmonk/generator-angular-fullstack.svg)](https://david-dm.org/daftmonk/generator-angular-fullstack) [![Dev-Dependency Status](https://david-dm.org/daftmonk/generator-angular-fullstack/dev-status.svg)](https://david-dm.org/daftmonk/generator-angular-fullstack#info=devDependencies) [![Gitter chat](https://badges.gitter.im/DaftMonk/generator-angular-fullstack.svg)](https://gitter.im/DaftMonk/generator-angular-fullstack) +> Yeoman generator for creating MEAN stack applications, using MongoDB, Express, AngularJS, and Node - lets you quickly set up a project following best practices. + #### Generated project: [![Dependency Status](https://david-dm.org/angular-fullstack/angular-fullstack-deps.svg)](https://david-dm.org/angular-fullstack/angular-fullstack-deps) [![Dev-Dependency Status](https://david-dm.org/angular-fullstack/angular-fullstack-deps/dev-status.svg)](https://david-dm.org/angular-fullstack/angular-fullstack-deps#info=devDependencies) -> Yeoman generator for creating MEAN stack applications, using MongoDB, Express, AngularJS, and Node - lets you quickly set up a project following best practices. ## Example project From eabd140bd3d483a26697949b2b0a919222414b75 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 9 Sep 2015 00:25:26 -0400 Subject: [PATCH 0264/1357] fix(grunt): remove old duplicate 'test' task --- Gruntfile.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 64198cda7..62df55738 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -275,11 +275,6 @@ module.exports = function (grunt) { }); }); - grunt.registerTask('test', [ - 'updateFixtures', - 'installFixtures', - 'mochaTest' - ]); grunt.registerTask('test', function(target, option) { if (target === 'fast') { grunt.task.run([ From 2c98c914ad00f44f147464576119333e47044ece Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 9 Sep 2015 03:15:53 -0400 Subject: [PATCH 0265/1357] chore(gen): update yeoman-generator to `~0.20.3` --- app/generator.js | 1 - app/templates/Gruntfile.js | 2 +- app/templates/README.md | 2 +- app/templates/client/app/app(coffee).coffee | 2 +- app/templates/client/app/app(js).js | 2 +- .../client/components/footer/footer(html).html | 2 +- .../client/components/footer/footer(jade).jade | 2 +- generator-base.js | 9 +++------ package.json | 2 +- util.js | 18 ++++-------------- 10 files changed, 14 insertions(+), 28 deletions(-) diff --git a/app/generator.js b/app/generator.js index f8721854b..915d5d380 100644 --- a/app/generator.js +++ b/app/generator.js @@ -30,7 +30,6 @@ export default class Generator extends Base { return { init: function () { - this.pkg = require('../package.json'); this.filters = {}; // init shared generator properies and methods diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 483be9b3e..e480ee3ea 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -1,4 +1,4 @@ -// Generated on <%= (new Date).toISOString().split('T')[0] %> using <%= pkg.name %> <%= pkg.version %> +// Generated on <%= (new Date).toISOString().split('T')[0] %> using <%= rootGeneratorName() %> <%= rootGeneratorVersion() %> 'use strict'; module.exports = function (grunt) { diff --git a/app/templates/README.md b/app/templates/README.md index e5ec70428..6cf5065f8 100644 --- a/app/templates/README.md +++ b/app/templates/README.md @@ -1,6 +1,6 @@ # <%= lodash.slugify(lodash.humanize(appname)) %> -This project was generated with the [Angular Full-Stack Generator](https://github.com/DaftMonk/generator-angular-fullstack) version <%= pkg.version %>. +This project was generated with the [Angular Full-Stack Generator](https://github.com/DaftMonk/generator-angular-fullstack) version <%= rootGeneratorVersion() %>. ## Getting Started diff --git a/app/templates/client/app/app(coffee).coffee b/app/templates/client/app/app(coffee).coffee index f0c1bd129..6458ca920 100644 --- a/app/templates/client/app/app(coffee).coffee +++ b/app/templates/client/app/app(coffee).coffee @@ -1,6 +1,6 @@ 'use strict' -angular.module '<%= scriptAppName %>', [<%= angularModules %>] +angular.module '<%= scriptAppName %>', [<%- angularModules %>] <% if (filters.ngroute) { %>.config ($routeProvider, $locationProvider<% if (filters.auth) { %>, $httpProvider<% } %>) -> $routeProvider .otherwise diff --git a/app/templates/client/app/app(js).js b/app/templates/client/app/app(js).js index 27410af8a..0c8ec39e8 100644 --- a/app/templates/client/app/app(js).js +++ b/app/templates/client/app/app(js).js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('<%= scriptAppName %>', [<%= angularModules %>]) +angular.module('<%= scriptAppName %>', [<%- angularModules %>]) <% if (filters.ngroute) { %>.config(function($routeProvider, $locationProvider<% if (filters.auth) { %>, $httpProvider<% } %>) { $routeProvider .otherwise({ diff --git a/app/templates/client/components/footer/footer(html).html b/app/templates/client/components/footer/footer(html).html index 3f9f7ffb9..35225475d 100644 --- a/app/templates/client/components/footer/footer(html).html +++ b/app/templates/client/components/footer/footer(html).html @@ -1,5 +1,5 @@
-

Angular Fullstack v<%= pkg.version %> | +

Angular Fullstack v<%= rootGeneratorVersion() %> | @tyhenkel | Issues

diff --git a/app/templates/client/components/footer/footer(jade).jade b/app/templates/client/components/footer/footer(jade).jade index a0bd84a1d..31c5ca960 100644 --- a/app/templates/client/components/footer/footer(jade).jade +++ b/app/templates/client/components/footer/footer(jade).jade @@ -1,6 +1,6 @@ .container p - | Angular Fullstack v<%= pkg.version %> + | Angular Fullstack v<%= rootGeneratorVersion() %> = ' | ' a(href='https://twitter.com/tyhenkel') @tyhenkel = ' | ' diff --git a/generator-base.js b/generator-base.js index 2abbaa0f7..30a43e643 100644 --- a/generator-base.js +++ b/generator-base.js @@ -16,12 +16,9 @@ export function genBase(self) { self.lodash = lodash; self.yoWelcome = yoWelcome; - try { - self.appname = require(path.join(process.cwd(), 'bower.json')).name; - } catch (e) { - self.appname = self.name || path.basename(process.cwd()); - } - self.appname = lodash.camelize(lodash.slugify(lodash.humanize(self.appname))); + self.appname = lodash.camelize(lodash.slugify( + lodash.humanize(self.determineAppname()) + )); self.scriptAppName = self.appname + genUtils.appSuffix(self); self.filters = self.filters || self.config.get('filters'); diff --git a/package.json b/package.json index f8e004ed3..6c10dbd61 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "glob": "^5.0.14", "lodash": "^3.10.1", "underscore.string": "^3.1.1", - "yeoman-generator": "~0.19.2", + "yeoman-generator": "~0.20.3", "yeoman-welcome": "^1.0.1" }, "devDependencies": { diff --git a/util.js b/util.js index ce7b7733b..529920364 100644 --- a/util.js +++ b/util.js @@ -68,19 +68,9 @@ export function appSuffix(self) { return (typeof suffix === 'string') ? self.lodash.classify(suffix) : ''; } -function destinationPath(self, filepath) { - filepath = path.normalize(filepath); - if (!path.isAbsolute(filepath)) { - filepath = path.join(self.destinationRoot(), filepath); - } - - return filepath; -} - export function relativeRequire(to, fr) { - var self = this; - fr = destinationPath(self, fr || self.filePath); - to = destinationPath(self, to); + fr = this.destinationPath(fr || this.filePath); + to = this.destinationPath(to); return path.relative(path.dirname(fr), to) .replace(/\\/g, '/') // convert win32 separator to posix .replace(/^(?!\.\.)(.*)/, './$1') // prefix non parent path with ./ @@ -148,10 +138,10 @@ export function processDirectory(source, destination) { if(templateIsUsable(self, filteredFile)) { if(copy) { - self.copy(src, dest); + self.fs.copy(src, dest); } else { self.filePath = dest; - self.template(src, dest); + self.fs.copyTpl(src, dest, self); delete self.filePath; } } From a43e7127eed02fc294331d7c51853667e36008ac Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 9 Sep 2015 06:43:55 -0400 Subject: [PATCH 0266/1357] chore(gen): update grunt-conventional-changelog to `^4.1.0` --- Gruntfile.js | 41 ++++++------- package.json | 2 +- task-utils/changelog-templates/commit.hbs | 6 ++ task-utils/grunt.js | 73 +++++++++++++++++++++++ 4 files changed, 98 insertions(+), 24 deletions(-) create mode 100644 task-utils/changelog-templates/commit.hbs create mode 100644 task-utils/grunt.js diff --git a/Gruntfile.js b/Gruntfile.js index 1004f931d..e776b3c48 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -4,14 +4,17 @@ var shell = require('shelljs'); var child_process = require('child_process'); var Q = require('q'); var helpers = require('yeoman-generator').test; +var gruntUtils = require('./task-utils/grunt'); var fs = require('fs'); var path = require('path'); +var gitCmd = gruntUtils.gitCmd; +var gitCmdAsync = gruntUtils.gitCmdAsync; + module.exports = function (grunt) { // Load grunt tasks automatically, when needed require('jit-grunt')(grunt, { - buildcontrol: 'grunt-build-control', - changelog: 'grunt-conventional-changelog' + buildcontrol: 'grunt-build-control' }); grunt.initConfig({ @@ -19,10 +22,20 @@ module.exports = function (grunt) { demo: 'demo' }, pkg: grunt.file.readJSON('package.json'), - changelog: { + conventionalChangelog: { options: { - dest: 'CHANGELOG.md', - versionFile: 'package.json' + changelogOpts: { + // conventional-changelog options go here + preset: 'angular' + }, + writerOpts: { + // conventional-changelog-writer options go here + finalizeContext: gruntUtils.conventionalChangelog.finalizeContext, + commitPartial: gruntUtils.conventionalChangelog.commitPartial + } + }, + release: { + src: 'CHANGELOG.md' } }, release: { @@ -119,24 +132,6 @@ module.exports = function (grunt) { } }); - function gitCmd(args, opts, done) { - grunt.util.spawn({ - cmd: process.platform === 'win32' ? 'git.cmd' : 'git', - args: args, - opts: opts || {} - }, done); - } - function gitCmdAsync(args, opts) { - return function() { - var deferred = Q.defer(); - gitCmd(args, opts, function(err) { - if (err) { return deferred.reject(err); } - deferred.resolve(); - }); - return deferred.promise; - }; - } - grunt.registerTask('stage', 'git add files before running the release task', function () { var files = grunt.config('stage.options').files; gitCmd(['add'].concat(files), {}, this.async()); diff --git a/package.json b/package.json index f8e004ed3..ce601b42f 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "grunt-build-control": "^0.6.0", "grunt-contrib-clean": "^0.6.0", "grunt-contrib-jshint": "^0.11.2", - "grunt-conventional-changelog": "~1.0.0", + "grunt-conventional-changelog": "^4.1.0", "grunt-david": "~0.5.0", "grunt-env": "^0.4.1", "grunt-mocha-test": "^0.12.7", diff --git a/task-utils/changelog-templates/commit.hbs b/task-utils/changelog-templates/commit.hbs new file mode 100644 index 000000000..2438d8d3d --- /dev/null +++ b/task-utils/changelog-templates/commit.hbs @@ -0,0 +1,6 @@ +{{#if subScope}} {{/if}}*{{#if scope}}{{#unless subScope}} **{{index}}{{scope}}:**{{/unless}}{{/if}} {{#unless leadScope}}{{#if subject}}{{subject}}{{else}}{{header}}{{/if}}{{/unless}}{{#if leadScope}}{{#if subject}} + * {{subject}}{{else}}{{header}}{{/if}}{{/if}} + +{{~!-- commit hash --}} {{#if @root.linkReferences}}([{{hash}}]({{@root.host}}/{{#if @root.owner}}{{@root.owner}}/{{/if}}{{@root.repository}}/{{@root.commit}}/{{hash}})){{else}}{{hash~}}{{/if}} + +{{~!-- commit references --}}{{#if references}}, closes{{~#each references}} {{#if @root.linkReferences}}[{{#if this.owner}}{{this.owner}}/{{/if}}{{this.repository}}#{{this.issue}}]({{@root.host}}/{{#if this.repository}}{{#if this.owner}}{{this.owner}}/{{/if}}{{this.repository}}{{else}}{{#if @root.owner}}{{@root.owner}}/{{/if}}{{@root.repository}}{{/if}}/{{@root.issue}}/{{this.issue}}){{else}}{{this.repository}}#{{this.issue}}{{/if}}{{/each}}{{/if}} diff --git a/task-utils/grunt.js b/task-utils/grunt.js new file mode 100644 index 000000000..70a598b8b --- /dev/null +++ b/task-utils/grunt.js @@ -0,0 +1,73 @@ +'use strict'; + +var path = require('path'); +var fs = require('fs'); + +exports = module.exports = { + gitCmd: function gitCmd(args, opts, done) { + grunt.util.spawn({ + cmd: process.platform === 'win32' ? 'git.cmd' : 'git', + args: args, + opts: opts || {} + }, done); + }, + + gitCmdAsync: function gitCmdAsync(args, opts) { + return function() { + var deferred = Q.defer(); + gitCmd(args, opts, function(err) { + if (err) { return deferred.reject(err); } + deferred.resolve(); + }); + return deferred.promise; + }; + }, + + conventionalChangelog: { + finalizeContext: function(context, writerOpts, commits, keyCommit) { + var gitSemverTags = context.gitSemverTags; + var commitGroups = context.commitGroups; + + if ((!context.currentTag || !context.previousTag) && keyCommit) { + var match = /tag:\s*(.+?)[,\)]/gi.exec(keyCommit.gitTags); + var currentTag = context.currentTag = context.currentTag || match ? match[1] : null; + var index = gitSemverTags.indexOf(currentTag); + var previousTag = context.previousTag = gitSemverTags[index + 1]; + + if (!previousTag) { + if (options.append) { + context.previousTag = context.previousTag || commits[0] ? commits[0].hash : null; + } else { + context.previousTag = context.previousTag || commits[commits.length - 1] ? commits[commits.length - 1].hash : null; + } + } + } else { + context.previousTag = context.previousTag || gitSemverTags[0]; + context.currentTag = context.currentTag || 'v' + context.version; + } + + if (typeof context.linkCompare !== 'boolean' && context.previousTag && context.currentTag) { + context.linkCompare = true; + } + + if (Array.isArray(commitGroups)) { + for (var i = 0, commitGroupsLength = commitGroups.length; i < commitGroupsLength; i++) { + var commits = commitGroups[i].commits; + if (Array.isArray(commits)) { + for (var n = 1, commitsLength = commits.length; n < commitsLength; n++) { + var commit = commits[n], prevCommit = commits[n - 1]; + if (commit.scope && commit.scope === prevCommit.scope) { + commit.subScope = true; + if (prevCommit.scope && !prevCommit.subScope) { + prevCommit.leadScope = true; + } + } + } + } + } + } + return context; + }, + commitPartial: fs.readFileSync(path.resolve(__dirname, 'changelog-templates', 'commit.hbs')).toString() + } +}; From 83385d65c9222a598147663453dffe88f35e4eb8 Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 9 Sep 2015 07:24:51 -0400 Subject: [PATCH 0267/1357] chore(gen): update `CHANGELOG.md` --- CHANGELOG.md | 340 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 217 insertions(+), 123 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d265082f..0b47eb6f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,196 +1,290 @@ - -## v2.1.1 (2015-07-29) + +## [2.1.1](https://github.com/DaftMonk/generator-angular-fullstack/compare/2.1.0...2.1.1) (2015-07-29) -#### Bug Fixes +### Bug Fixes -* **app:** use 0.0.0.0 for default IP ([2cd1c24d](http://github.com/DaftMonk/generator-angular-fullstack/commit/2cd1c24d2224e46fa68f8da834e86ac3ed80de8e)) +* **app:** + * correct grunt clean glob ([8e8ae96](https://github.com/DaftMonk/generator-angular-fullstack/commit/8e8ae96)) + * ensure all files end with a newline ([8511260](https://github.com/DaftMonk/generator-angular-fullstack/commit/8511260)) + * fix folder depth in rev and usemin globs ([18f8d31](https://github.com/DaftMonk/generator-angular-fullstack/commit/18f8d31)) + * update sequelize syntax in seed.js ([a9372a1](https://github.com/DaftMonk/generator-angular-fullstack/commit/a9372a1)) + * use 0.0.0.0 for default IP ([2cd1c24](https://github.com/DaftMonk/generator-angular-fullstack/commit/2cd1c24)), closes [DaftMonk/generator-angular-fullstack#1071](https://github.com/DaftMonk/generator-angular-fullstack/issues/1071) +* **app:test:** include `client/components` in babel preprocessing ([6b575d1](https://github.com/DaftMonk/generator-angular-fullstack/commit/6b575d1)), closes [DaftMonk/generator-angular-fullstack#1081](https://github.com/DaftMonk/generator-angular-fullstack/issues/1081) +* **build:** exclued `bower_components` from the grunt rev and usemin blocks ([7ae43ae](https://github.com/DaftMonk/generator-angular-fullstack/commit/7ae43ae)), closes [#522](https://github.com/DaftMonk/generator-angular-fullstack/issues/522) +* **test:** + * update protractor test for angular 1.4 ([f5acad0](https://github.com/DaftMonk/generator-angular-fullstack/commit/f5acad0)) + * use proper controlFlow in protractor tests ([8dce663](https://github.com/DaftMonk/generator-angular-fullstack/commit/8dce663)) + +### Features - -## v2.1.0 (2015-07-15) +* **app:** + * improve `Gruntfile.js` file globbing ([5874dfd](https://github.com/DaftMonk/generator-angular-fullstack/commit/5874dfd)) + * merge H5BP updates to index.html ([4a88551](https://github.com/DaftMonk/generator-angular-fullstack/commit/4a88551)) + * watch integration tests for changes ([a81aeb1](https://github.com/DaftMonk/generator-angular-fullstack/commit/a81aeb1)) +* **build:** switch to grunt-filerev ([cd28298](https://github.com/DaftMonk/generator-angular-fullstack/commit/cd28298)) +* **test:** add jasmine-spec-reporter ([f34e8f3](https://github.com/DaftMonk/generator-angular-fullstack/commit/f34e8f3)) -#### Bug Fixes -* **app:** missing event.preventDefault ([c90d7621](http://github.com/DaftMonk/generator-angular-fullstack/commit/c90d7621b8f17f6e74f8a59f02fd78a8fcf628aa)) -* **demo:** include bootstrap in demo ([19e21331](http://github.com/DaftMonk/generator-angular-fullstack/commit/19e213319ecdf27041948133fe4c9642184133d8)) -* **express:** support new options of updated connect-mongo ([727d6616](http://github.com/DaftMonk/generator-angular-fullstack/commit/727d661642441d5ee76e4fba9ebcbba134e43058)) -* **jshint:** Removed 'regexp' from server and client jshintrc (I couldn't find it in the docs ([e02f0940](http://github.com/DaftMonk/generator-angular-fullstack/commit/e02f09405de2423d7be92e5ca0f9be740becb693)) -* **travis:** - * Remove unicode stuff from file creation test expectations, and add nodejs 0.12 t ([bf9a9737](http://github.com/DaftMonk/generator-angular-fullstack/commit/bf9a9737721d1ea72f3f7b9689d6781e78b4c606)) - * Add nodejs 12 to travis.yml ([acecde9d](http://github.com/DaftMonk/generator-angular-fullstack/commit/acecde9d0e02b579d4b0a2a33d7c0f24067258ec)) + +# [2.1.0](https://github.com/DaftMonk/generator-angular-fullstack/compare/v2.0.13...2.1.0) (2015-07-15) -#### Features +### Bug Fixes -* **app:** - * additional app generator option for ES6 preprocessing using babel ([cbb06a48](http://github.com/DaftMonk/generator-angular-fullstack/commit/cbb06a48e28c594a53f61e49857cbb711bd74ce9)) - * additional app generator option for ES6 preprocessing using babel ([bc03aba9](http://github.com/DaftMonk/generator-angular-fullstack/commit/bc03aba9ee82812f29f4ec9f86daf3b8d1c531b8)) - * add mongodb error handling to quit app if unable to connect with mongodb server ([31bee73c](http://github.com/DaftMonk/generator-angular-fullstack/commit/31bee73c1085c3a3f3c8e4e6f1f45db28fa9f94b)) -* **build:** add gitter webhook for travis ([6b88efdf](http://github.com/DaftMonk/generator-angular-fullstack/commit/6b88efdfb1d6b3b2dcbf47e0517bfc5117247d12)) -* **gen:** Remove global jQuery dependency ([a9230ca2](http://github.com/DaftMonk/generator-angular-fullstack/commit/a9230ca2ba1b2727abdc466a11096ec513fd7085)) -* **readme:** add david-dm badge & move badges to new line ([f8f32f4f](http://github.com/DaftMonk/generator-angular-fullstack/commit/f8f32f4f67938a5f7416e2a07d7b24d71a12585f)) +* **app:** missing event.preventDefault ([c90d762](https://github.com/DaftMonk/generator-angular-fullstack/commit/c90d762)) +* **app-logout:** add blank templates to logout route/state ([650d244](https://github.com/DaftMonk/generator-angular-fullstack/commit/650d244)), closes [#570](https://github.com/DaftMonk/generator-angular-fullstack/issues/570) +* **app-signup:** switch button classes ([5898e0c](https://github.com/DaftMonk/generator-angular-fullstack/commit/5898e0c)) +* **demo:** include bootstrap in demo ([19e2133](https://github.com/DaftMonk/generator-angular-fullstack/commit/19e2133)) +* **deps:** use angular ~1.2 before migrated to 1.3 ([6a196e2](https://github.com/DaftMonk/generator-angular-fullstack/commit/6a196e2)), closes [#654](https://github.com/DaftMonk/generator-angular-fullstack/issues/654) +* **endpoint:** + * fully support sequelize models ([df82d17](https://github.com/DaftMonk/generator-angular-fullstack/commit/df82d17)) + * refactor handleError for promise use ([0af7c3e](https://github.com/DaftMonk/generator-angular-fullstack/commit/0af7c3e)) +* **endpoint:thing:** use Express 4 syntax ([c7b48a5](https://github.com/DaftMonk/generator-angular-fullstack/commit/c7b48a5)) +* **endpoint:user:** refactor validationError for promise use ([c98cb5d](https://github.com/DaftMonk/generator-angular-fullstack/commit/c98cb5d)) +* **express:** support new options of updated connect-mongo ([727d661](https://github.com/DaftMonk/generator-angular-fullstack/commit/727d661)) +* **gen:** + * camelCase endpoint name when used in variable name ([7362080](https://github.com/DaftMonk/generator-angular-fullstack/commit/7362080)), closes [#540](https://github.com/DaftMonk/generator-angular-fullstack/issues/540) + * Check that answers.odms exists ([342606c](https://github.com/DaftMonk/generator-angular-fullstack/commit/342606c)) + * filter `client/components/socket` js files ([49d5bbd](https://github.com/DaftMonk/generator-angular-fullstack/commit/49d5bbd)), closes [#530](https://github.com/DaftMonk/generator-angular-fullstack/issues/530) +* **gen:build:** Adds missing slash ([bb4d92e](https://github.com/DaftMonk/generator-angular-fullstack/commit/bb4d92e)) +* **gen:endpoint:** Fix JSCS stuff and use Express 4 syntax ([1bcffd6](https://github.com/DaftMonk/generator-angular-fullstack/commit/1bcffd6)) +* **git:** Remove old text=auto ([e0350cc](https://github.com/DaftMonk/generator-angular-fullstack/commit/e0350cc)) +* **jshint:** Removed 'regexp' from server and client jshintrc (I couldn't find it in the docs ([e02f094](https://github.com/DaftMonk/generator-angular-fullstack/commit/e02f094)) +* **model:** fix update bugs with mongoose and sequelize ([1805975](https://github.com/DaftMonk/generator-angular-fullstack/commit/1805975)) +* **npm:** Remove git diff comment ([349b6d3](https://github.com/DaftMonk/generator-angular-fullstack/commit/349b6d3)) +* **oauth:** + * Facebook API updated ([f6e7a12](https://github.com/DaftMonk/generator-angular-fullstack/commit/f6e7a12)) + * Google scopes deprecated ([136f15e](https://github.com/DaftMonk/generator-angular-fullstack/commit/136f15e)) +* return a 404 when no user is found fixes #711 ([38c0d7c](https://github.com/DaftMonk/generator-angular-fullstack/commit/38c0d7c)), closes [#711](https://github.com/DaftMonk/generator-angular-fullstack/issues/711) +* **openshift:** fix processing of rhc app show output ([dedf46c](https://github.com/DaftMonk/generator-angular-fullstack/commit/dedf46c)) +* **server:** server should launch in dev mode if production env var is not specified ([9cdcc90](https://github.com/DaftMonk/generator-angular-fullstack/commit/9cdcc90)), closes [#590](https://github.com/DaftMonk/generator-angular-fullstack/issues/590) +* **server-tests:** `test:coverage` task ([5198685](https://github.com/DaftMonk/generator-angular-fullstack/commit/5198685)) +* **test:** + * change `protractor.getInstance` to `browser` ([c7f6c36](https://github.com/DaftMonk/generator-angular-fullstack/commit/c7f6c36)) + * remove package.json and bower.json ([0ec2e18](https://github.com/DaftMonk/generator-angular-fullstack/commit/0ec2e18)) + * update sequelize destroy usage ([8df9992](https://github.com/DaftMonk/generator-angular-fullstack/commit/8df9992)) +* **travis:** + * Add nodejs 12 to travis.yml ([acecde9](https://github.com/DaftMonk/generator-angular-fullstack/commit/acecde9)) + * remove node v0.11 from testing ([dae69cf](https://github.com/DaftMonk/generator-angular-fullstack/commit/dae69cf)) + * Remove unicode stuff from file creation test expectations, and add nodejs 0.12 t ([bf9a973](https://github.com/DaftMonk/generator-angular-fullstack/commit/bf9a973)) + +### Features - -### v2.0.13 (2014-08-29) +* **app:** + * add grunt jscs task for maintaining consistent code style ([8a1a245](https://github.com/DaftMonk/generator-angular-fullstack/commit/8a1a245)) + * add mongodb error handling to quit app if unable to connect with mongodb server ([31bee73](https://github.com/DaftMonk/generator-angular-fullstack/commit/31bee73)) + * additional app generator option for ES6 preprocessing using babel ([bc03aba](https://github.com/DaftMonk/generator-angular-fullstack/commit/bc03aba)) + * additional app generator option for ES6 preprocessing using babel ([cbb06a4](https://github.com/DaftMonk/generator-angular-fullstack/commit/cbb06a4)) + * implement footer as directive ([cf298a7](https://github.com/DaftMonk/generator-angular-fullstack/commit/cf298a7)) + * implement navbar as directive ([24171aa](https://github.com/DaftMonk/generator-angular-fullstack/commit/24171aa)) +* **app-auth:** Improve client-side Auth service ([65d03fc](https://github.com/DaftMonk/generator-angular-fullstack/commit/65d03fc)), closes [#456](https://github.com/DaftMonk/generator-angular-fullstack/issues/456) +* **app-routing:** improve app routing ([6aadee6](https://github.com/DaftMonk/generator-angular-fullstack/commit/6aadee6)), closes [#331](https://github.com/DaftMonk/generator-angular-fullstack/issues/331) +* **build:** add gitter webhook for travis ([6b88efd](https://github.com/DaftMonk/generator-angular-fullstack/commit/6b88efd)) +* **gen:** + * add README.md ([f07b09c](https://github.com/DaftMonk/generator-angular-fullstack/commit/f07b09c)) + * Remove global jQuery dependency ([a9230ca](https://github.com/DaftMonk/generator-angular-fullstack/commit/a9230ca)), closes [#547](https://github.com/DaftMonk/generator-angular-fullstack/issues/547) + * unify testing framework ([654de87](https://github.com/DaftMonk/generator-angular-fullstack/commit/654de87)) + * use common endpoint templates for thing route ([6dc8130](https://github.com/DaftMonk/generator-angular-fullstack/commit/6dc8130)) +* **generator:** use sauce labs for running e2e tests with travis CI ([50ca41d](https://github.com/DaftMonk/generator-angular-fullstack/commit/50ca41d)), closes [#572](https://github.com/DaftMonk/generator-angular-fullstack/issues/572) +* **model:** abstract model events to a standard EventEmitter ([91657d7](https://github.com/DaftMonk/generator-angular-fullstack/commit/91657d7)), closes [#857](https://github.com/DaftMonk/generator-angular-fullstack/issues/857) [#490](https://github.com/DaftMonk/generator-angular-fullstack/issues/490) +* **readme:** add david-dm badge & move badges to new line ([f8f32f4](https://github.com/DaftMonk/generator-angular-fullstack/commit/f8f32f4)) +* **server:** + * add support for sequelize ([943120e](https://github.com/DaftMonk/generator-angular-fullstack/commit/943120e)), closes [#414](https://github.com/DaftMonk/generator-angular-fullstack/issues/414) + * implement server-side ES6 via babel ([60334a8](https://github.com/DaftMonk/generator-angular-fullstack/commit/60334a8)) +* **server-tests:** code coverage and e2e ([dbbaa20](https://github.com/DaftMonk/generator-angular-fullstack/commit/dbbaa20)) +* **travis-ci:** enable container builds and caching ([00317a8](https://github.com/DaftMonk/generator-angular-fullstack/commit/00317a8)) -#### Bug Fixes -* **gen:** - * use bool for bootstrap filters ([a5decbc3](http://github.com/DaftMonk/generator-angular-fullstack/commit/a5decbc36e933f94c69d9e9bb58bd8e07148c34d), closes [#496](http://github.com/DaftMonk/generator-angular-fullstack/issues/496)) - * fix build when not selecting socket.io ([fdf063c6](http://github.com/DaftMonk/generator-angular-fullstack/commit/fdf063c6cc2ec4eeef252f13b2e0d301931fa83c)) + +## [2.0.13](https://github.com/DaftMonk/generator-angular-fullstack/compare/v2.0.12...v2.0.13) (2014-08-29) - -### v2.0.12 (2014-08-25) -#### Bug Fixes +### Bug Fixes -* revert multiple strategies per account, which shouldn't go in a patch release +* **gen:** + * fix build when not selecting socket.io ([fdf063c](https://github.com/DaftMonk/generator-angular-fullstack/commit/fdf063c)) + * use bool for bootstrap filters ([a5decbc](https://github.com/DaftMonk/generator-angular-fullstack/commit/a5decbc)), closes [#496](https://github.com/DaftMonk/generator-angular-fullstack/issues/496) - -### v2.0.11 (2014-08-25) +### Features +* **auth:** make crypto async ([6aecdf7](https://github.com/DaftMonk/generator-angular-fullstack/commit/6aecdf7)) -#### Bug Fixes -* **app:** Use parentheses to fix string concat in config ([c6a50ce7](http://github.com/DaftMonk/generator-angular-fullstack/commit/c6a50ce791ab633a17654ce9b0090007d7152463), closes [#466](http://github.com/DaftMonk/generator-angular-fullstack/issues/466)) - * improve jshint usage ([35fcf490](http://github.com/DaftMonk/generator-angular-fullstack/commit/35fcf4902dbbdab2ca6b394ab87ef8e3cc3d052b), closes [#463](http://github.com/DaftMonk/generator-angular-fullstack/issues/463), [#486](http://github.com/DaftMonk/generator-angular-fullstack/issues/486)) -* **gen:** use more restrictive version range for ng-component ([19698973](http://github.com/DaftMonk/generator-angular-fullstack/commit/196989730c8922fa5e1dc9caa45eb85052535e30)) + +## [2.0.11](https://github.com/DaftMonk/generator-angular-fullstack/compare/v2.0.10...v2.0.11) (2014-08-26) -#### Features -* **socket.io:** build socket.io into vendor.js ([06f2e46e](http://github.com/DaftMonk/generator-angular-fullstack/commit/06f2e46ef382b5af1691f34b6cf504f1e5640b86)) -* **docs:** Inform users/developers of the `canary` branch ([74693623](http://github.com/DaftMonk/generator-angular-fullstack/commit/74693623eb23c9399495a3baff7e3479a1d9f3ba)) -* **gen:** make generator tests faster, and easier to run ([84acb744](http://github.com/DaftMonk/generator-angular-fullstack/commit/84acb7448ccc7c55b72bdd19bfae50c33d527296)) -* **app:** add additional node version to travis.yml ([e4f00b08](http://github.com/DaftMonk/generator-angular-fullstack/commit/e4f00b083a880713ca563e3447b9fb3f56a54ebc)) -* **uibootstrap:** add basic modal service and template when using uibootstrap ([7c14bed4](http://github.com/DaftMonk/generator-angular-fullstack/commit/7c14bed4873b92124bcbe422fed918836b8f5df5)) +### Bug Fixes - -### v2.0.10 (2014-08-16) +* **app-config:** Use parentheses to fix string concat in config ([c6a50ce](https://github.com/DaftMonk/generator-angular-fullstack/commit/c6a50ce)), closes [#466](https://github.com/DaftMonk/generator-angular-fullstack/issues/466) +* **app-jshint:** improve jshint usage ([35fcf49](https://github.com/DaftMonk/generator-angular-fullstack/commit/35fcf49)), closes [#463](https://github.com/DaftMonk/generator-angular-fullstack/issues/463) [#486](https://github.com/DaftMonk/generator-angular-fullstack/issues/486) +* **gen:** use more restrictive version range for ng-component ([1969897](https://github.com/DaftMonk/generator-angular-fullstack/commit/1969897)) +### Features -#### Bug Fixes +* **app-socket.io:** build socket.io into vendor.js ([06f2e46](https://github.com/DaftMonk/generator-angular-fullstack/commit/06f2e46)) +* **docs:** Inform users/developers of the `canary` branch ([7469362](https://github.com/DaftMonk/generator-angular-fullstack/commit/7469362)) +* **gen:** make generator tests faster, and easier to run ([84acb74](https://github.com/DaftMonk/generator-angular-fullstack/commit/84acb74)) +* **gen-travis:** add additional node version to travis.yml ([e4f00b0](https://github.com/DaftMonk/generator-angular-fullstack/commit/e4f00b0)) -* **server:** undefined domain env variable causing issues ([cb683dde](http://github.com/DaftMonk/generator-angular-fullstack/commit/cb683dde6814959328a58267215ce477aa723e35)) - -### v2.0.9 (2014-08-15) + +## [2.0.10](https://github.com/DaftMonk/generator-angular-fullstack/compare/v2.0.9...v2.0.10) (2014-08-16) -#### Bug Fixes -* **app:** - * add .idea folder to gitignore ([2e1f1182](http://github.com/DaftMonk/generator-angular-fullstack/commit/2e1f1182684594300ac5ca85ffab175bfcafd3ec)) - * Missing user response code ([c1766604](http://github.com/DaftMonk/generator-angular-fullstack/commit/c1766604d7ae7ab1eb8713f37285d13341dc8ae1)) - * use `''` instead `null` as URL to open ioSocket ([0f0d0fdc](http://github.com/DaftMonk/generator-angular-fullstack/commit/0f0d0fdce38d42f04f71d9e1174400adfb699061)) - * save the version of the generator that was used ([2b76b17b](http://github.com/DaftMonk/generator-angular-fullstack/commit/2b76b17bb5fa1980b449498beec87ab58ceee012)) -* **gruntfile:** incorrect path to index.html for cdnify ([0ad646cb](http://github.com/DaftMonk/generator-angular-fullstack/commit/0ad646cbd48dbb2f65fc00b930a9f243174611be)) -* **openshift:** fix issues with openshift deployment ([ace07238](http://github.com/DaftMonk/generator-angular-fullstack/commit/ace07238e3299d6002337ba12f7862ce84beafd8)) +### Bug Fixes +* **server:** undefined domain env variable causing issues ([cb683dd](https://github.com/DaftMonk/generator-angular-fullstack/commit/cb683dd)) -#### Features -* **gen:** add automatic demo releases with grunt task ([44852233](http://github.com/DaftMonk/generator-angular-fullstack/commit/44852233fcf28d5ff8681fcabc3bfb4130778a22)) -* **gruntfile:** add grunt buildcontrol tasks to app, for easier deployment ([036478df](http://github.com/DaftMonk/generator-angular-fullstack/commit/036478dfd7067d38ab19ca86c0c5196678412799)) -* **heroku:** provide prompt to set the deployment region ([13cd5e7d](http://github.com/DaftMonk/generator-angular-fullstack/commit/13cd5e7d42f2845268f38ba19e0d253ae675c594)) -* **server:** add sample env config file that can be tracked by git ([c9f80bcd](http://github.com/DaftMonk/generator-angular-fullstack/commit/c9f80bcd67d6e3eef2c78ccbceff78f763ae88d1)) - -### v2.0.8 (2014-07-31) + +## [2.0.9](https://github.com/DaftMonk/generator-angular-fullstack/compare/v2.0.8...v2.0.9) (2014-08-16) -#### Bug Fixes +### Bug Fixes -* **coffee:** update socket service to match javascript version ([c27cefe2](http://github.com/DaftMonk/generator-angular-fullstack/commit/c27cefe24d8ec64d905f908c66a56bf602303dce)) -* **gen:** Fixed missing `oauth` property in `.yo-rc.json` after 2.0.5 update ([11d324b9](http://github.com/DaftMonk/generator-angular-fullstack/commit/11d324b95992b68bd19f402401e98f5936cdb343)) -* **travis:** install sass gem if sass is enabled ([ceeac27b](http://github.com/DaftMonk/generator-angular-fullstack/commit/ceeac27b8f912aa6dec2caf3bf20dd7551f2d754)) -* **twitter:** revert mongoose connection change ([8675a002](http://github.com/DaftMonk/generator-angular-fullstack/commit/8675a002e301957569374fdcad87aab0bff6b3b4)) +* **app:** + * add .idea folder to gitignore ([2e1f118](https://github.com/DaftMonk/generator-angular-fullstack/commit/2e1f118)) + * save the version of the generator that was used ([2b76b17](https://github.com/DaftMonk/generator-angular-fullstack/commit/2b76b17)) +* **app:api:user:** Missing user response code ([c176660](https://github.com/DaftMonk/generator-angular-fullstack/commit/c176660)), closes [#438](https://github.com/DaftMonk/generator-angular-fullstack/issues/438) +* **gen:app:socket:** use `''` instead `null` as URL to open ioSocket ([0f0d0fd](https://github.com/DaftMonk/generator-angular-fullstack/commit/0f0d0fd)) +* **gruntfile:** incorrect path to index.html for cdnify ([0ad646c](https://github.com/DaftMonk/generator-angular-fullstack/commit/0ad646c)) +* **openshift:** fix issues with openshift deployment ([ace0723](https://github.com/DaftMonk/generator-angular-fullstack/commit/ace0723)) +### Features -#### Features +* **gen:** add automatic demo releases with grunt task ([4485223](https://github.com/DaftMonk/generator-angular-fullstack/commit/4485223)) +* **server:** add sample env config file that can be tracked by git ([c9f80bc](https://github.com/DaftMonk/generator-angular-fullstack/commit/c9f80bc)) +* **uibootstrap-modal:** add basic modal service and template when using uibootstrap ([7c14bed](https://github.com/DaftMonk/generator-angular-fullstack/commit/7c14bed)) -* **user-management:** use the User $resource to populate users for the admin page ([708f0729](http://github.com/DaftMonk/generator-angular-fullstack/commit/708f07290d98d6bd73723f9db49cce7758c3d12b)) - -### v2.0.7 (2014-07-27) + +## [2.0.8](https://github.com/DaftMonk/generator-angular-fullstack/compare/v2.0.7...v2.0.8) (2014-07-31) -#### Bug Fixes -* **gruntfile:** grunt tasks should run if no local config exists ([422d6bca](http://github.com/DaftMonk/generator-angular-fullstack/commit/422d6bca07283057b0fa275dba0de447c9f4f167)) -* **server:** fix setting TTL index on collection : sessions error ([0581ed09](http://github.com/DaftMonk/generator-angular-fullstack/commit/0581ed094b2c6141ab9e0c016eda22aa49e1d075)) +### Bug Fixes - -### v2.0.6 (2014-07-27) +* **coffee:** update socket service to match javascript version ([c27cefe](https://github.com/DaftMonk/generator-angular-fullstack/commit/c27cefe)) +* **gen:** Fixed missing `oauth` property in `.yo-rc.json` after 2.0.5 update ([11d324b](https://github.com/DaftMonk/generator-angular-fullstack/commit/11d324b)) +* **travis:** install sass gem if sass is enabled ([ceeac27](https://github.com/DaftMonk/generator-angular-fullstack/commit/ceeac27)) +* **twitter:** revert mongoose connection change ([8675a00](https://github.com/DaftMonk/generator-angular-fullstack/commit/8675a00)) +### Features -#### Bug Fixes +* **user-management:** use the User $resource to populate users for the admin page ([708f072](https://github.com/DaftMonk/generator-angular-fullstack/commit/708f072)) -* **app:** - * `things` made a little bit more responsive ([58aa7a48](http://github.com/DaftMonk/generator-angular-fullstack/commit/58aa7a489ae28c22be59b3a61db027ccf2f1ae46)) -* **dependencies:** change ngmin to ng-annotate ([dd023fa5](http://github.com/DaftMonk/generator-angular-fullstack/commit/dd023fa5fd90b8b541b8cc60c87186ee619e4844)) -* **bootstrap:** removed styles breaking responsiveness for high-res screens ([053fedb8](http://github.com/DaftMonk/generator-angular-fullstack/commit/053fedb89f64294a55538ad9b806b2d7de4d1c7f)) -* **socketio:** fallback for servers where `socket.handshake.address` is not provided ([f6a19348](http://github.com/DaftMonk/generator-angular-fullstack/commit/f6a19348ad404aa72c31eef8dc84aac8db0e904a)) -* **stylus:** remove bootstrap css import in stylus when bootstrap is not selected ([f7c3d0ad](http://github.com/DaftMonk/generator-angular-fullstack/commit/f7c3d0ad41da5f0072c2cf64ff5c9a894052d194), closes [#368](http://github.com/DaftMonk/generator-angular-fullstack/issues/368)) -#### Features + +## [2.0.7](https://github.com/DaftMonk/generator-angular-fullstack/compare/v2.0.6...v2.0.7) (2014-07-28) -* **oauth:** remove code according to user prompts ([316bd9dd](http://github.com/DaftMonk/generator-angular-fullstack/commit/316bd9dd3632622b0fb434cacfc4150f01d18e4c)) - -### v2.0.5 (2014-07-17) +### Bug Fixes -#### Bug Fixes +* **gruntfile:** grunt tasks should run if no local config exists ([422d6bc](https://github.com/DaftMonk/generator-angular-fullstack/commit/422d6bc)) +* **server:** fix setting TTL index on collection : sessions error ([0581ed0](https://github.com/DaftMonk/generator-angular-fullstack/commit/0581ed0)) -* **account:** add authentication requirement for settings view ([9105c0fd](http://github.com/DaftMonk/generator-angular-fullstack/commit/9105c0fdbabdbde68fb6cf0fe0d6993ead6e7095), closes [#327](http://github.com/DaftMonk/generator-angular-fullstack/issues/327)) -* **app:** - * use correct path for font awesome and glyphicons ([1917ba31](http://github.com/DaftMonk/generator-angular-fullstack/commit/1917ba31264fc90bea0fce36b8d144f897e8bf08)) - * wait for currentUser to resolve before checking if logged in on route changes ([6d6090d9](http://github.com/DaftMonk/generator-angular-fullstack/commit/6d6090d9c4dcd5d8a1f6ecb2cf5dc0bb4c8598fe)) - * bootstrap glyphicons not correctly linked on grunt build ([53d193d0](http://github.com/DaftMonk/generator-angular-fullstack/commit/53d193d011c7c1ea8c9477e8f17ad56cc4214362)) -* **dependencies:** include certain dependencies only when answering yes to their respective prompts ([040c57de](http://github.com/DaftMonk/generator-angular-fullstack/commit/040c57de8689f2e0fc35410d0b6935363aaa8458)) -* **server:** - * fix seeding of db in test mode causing tests to randomly fail ([05f7f433](http://github.com/DaftMonk/generator-angular-fullstack/commit/05f7f43372bc3bd54bead811952b775adeec1f05)) - * make user tests run more consistently ([addb5061](http://github.com/DaftMonk/generator-angular-fullstack/commit/addb5061f62696c7a0078a8d2c7443d428e69376)) - * warnings that express was using deprecated features ([8dc2f1e4](http://github.com/DaftMonk/generator-angular-fullstack/commit/8dc2f1e48503c27cbd2aac3c455adac7781a6539)) - * missing `res` param for handleError ([eb7d50c8](http://github.com/DaftMonk/generator-angular-fullstack/commit/eb7d50c8d27820a6b26caf2a1aaa0e4fa8eee367)) -#### Features + +## [2.0.6](https://github.com/DaftMonk/generator-angular-fullstack/compare/v2.0.5...v2.0.6) (2014-07-27) + + +### Bug Fixes + +* **app-dependency:** change ngmin to ng-annotate ([dd023fa](https://github.com/DaftMonk/generator-angular-fullstack/commit/dd023fa)) +* **bootstrap:** removed styles breaking responsiveness for high-res screens ([053fedb](https://github.com/DaftMonk/generator-angular-fullstack/commit/053fedb)) +* **responsive:** `things` made a little bit more responsive ([58aa7a4](https://github.com/DaftMonk/generator-angular-fullstack/commit/58aa7a4)) +* **socketio:** fallback for servers where `socket.handshake.address` is not provided ([f6a1934](https://github.com/DaftMonk/generator-angular-fullstack/commit/f6a1934)) +* **stylus:** remove bootstrap css import in stylus when bootstrap is not selected ([f7c3d0a](https://github.com/DaftMonk/generator-angular-fullstack/commit/f7c3d0a)), closes [#368](https://github.com/DaftMonk/generator-angular-fullstack/issues/368) + +### Features + +* **heroku:** provide prompt to set the deployment region ([13cd5e7](https://github.com/DaftMonk/generator-angular-fullstack/commit/13cd5e7)) +* **oauth:** multiple strategies per account; changeable email ([ef06272](https://github.com/DaftMonk/generator-angular-fullstack/commit/ef06272)) + + + + +## [2.0.5](https://github.com/DaftMonk/generator-angular-fullstack/compare/v2.0.4...v2.0.5) (2014-07-18) + + +### Bug Fixes + +* **account:** add authentication requirement for settings view ([9105c0f](https://github.com/DaftMonk/generator-angular-fullstack/commit/9105c0f)), closes [#327](https://github.com/DaftMonk/generator-angular-fullstack/issues/327) * **app:** - * added oath buttons to signup page ([a408f58e](http://github.com/DaftMonk/generator-angular-fullstack/commit/a408f58edb923cd14bf7c7b3411b874dce5f0724)) - * upgrade socket.io to use v1.0.6 -* **gen:** - * add option for Stylus as a preprocessor ([1b90c448](http://github.com/DaftMonk/generator-angular-fullstack/commit/1b90c448fbf374287fe07f782f9788dfb9a23613)) - * make bootstrap and bootstrap ui optional ([f50d0942](http://github.com/DaftMonk/generator-angular-fullstack/commit/f50d094226fdbf6a7e65ba3783a26efc8544ba08)) + * bootstrap glyphicons not correctly linked on grunt build ([53d193d](https://github.com/DaftMonk/generator-angular-fullstack/commit/53d193d)), closes [#333](https://github.com/DaftMonk/generator-angular-fullstack/issues/333) + * wait for currentUser to resolve before checking if logged in on route changes ([6d6090d](https://github.com/DaftMonk/generator-angular-fullstack/commit/6d6090d)), closes [#306](https://github.com/DaftMonk/generator-angular-fullstack/issues/306) [#294](https://github.com/DaftMonk/generator-angular-fullstack/issues/294) +* **app:server:thing.controller:** missing `res` param for handleError added ([eb7d50c](https://github.com/DaftMonk/generator-angular-fullstack/commit/eb7d50c)) +* **app:styles:** use correct path for font awesome and glyphicons ([1917ba3](https://github.com/DaftMonk/generator-angular-fullstack/commit/1917ba3)) +* **dependencies:** include certain dependencies only when answering yes to their respective prompts ([040c57d](https://github.com/DaftMonk/generator-angular-fullstack/commit/040c57d)) +* **server:** + * fix seeding of db in test mode causing tests to randomly fail ([05f7f43](https://github.com/DaftMonk/generator-angular-fullstack/commit/05f7f43)), closes [#352](https://github.com/DaftMonk/generator-angular-fullstack/issues/352) + * make user tests run more consistently ([addb506](https://github.com/DaftMonk/generator-angular-fullstack/commit/addb506)), closes [#346](https://github.com/DaftMonk/generator-angular-fullstack/issues/346) - -### v2.0.4 (2014-07-08) +### Features +* **app:** added oath buttons to signup page ([a408f58](https://github.com/DaftMonk/generator-angular-fullstack/commit/a408f58)) +* **gen:** + * Generate CSS from Stylus ([1b90c44](https://github.com/DaftMonk/generator-angular-fullstack/commit/1b90c44)) + * Generate CSS from Stylus ([9d87a2c](https://github.com/DaftMonk/generator-angular-fullstack/commit/9d87a2c)) +* **oauth:** remove code according to user prompts ([316bd9d](https://github.com/DaftMonk/generator-angular-fullstack/commit/316bd9d)) -#### Bug Fixes -* **app:** fix dependency injection minsafe problem in auth service coffeescript. ([03742a80](http://github.com/DaftMonk/generator-angular-fullstack/commit/03742a8000f19efdf14791ff1aae52a90e86c149)) -* **gen:** heroku and openshift generators requiring .yo-rc file to work ([88ebfc8c](http://github.com/DaftMonk/generator-angular-fullstack/commit/88ebfc8c835ac6ec04b6d42fcf9357cfb0bcc47d)) - -### v2.0.3 (2014-07-04) + +## [2.0.4](https://github.com/DaftMonk/generator-angular-fullstack/compare/v2.0.3...v2.0.4) (2014-07-09) -#### Bug Fixes +### Bug Fixes -* **server:** only enable sessions if twitter oauth was selected ([bcd00dc0](http://github.com/DaftMonk/generator-angular-fullstack/commit/bcd00dc02d270486adafe6dbf973a4ec25499a5e)) +* **app:** fix dependency injection minsafe problem in auth service ([03742a8](https://github.com/DaftMonk/generator-angular-fullstack/commit/03742a8)) +* **gen:** heroku and openshift generators requiring .yo-rc file to work ([88ebfc8](https://github.com/DaftMonk/generator-angular-fullstack/commit/88ebfc8)), closes [#318](https://github.com/DaftMonk/generator-angular-fullstack/issues/318) - -### v2.0.2 (2014-07-02) -#### Bug Fixes -* **gen:endpoint** - * fix endpoint spec not properly adjusting to users route url - * fix some valid route urls causing failing tests + +## [2.0.3](https://github.com/DaftMonk/generator-angular-fullstack/compare/v2.0.2...v2.0.3) (2014-07-04) + + +### Bug Fixes + +* **server:** only enable sessions if twitter oauth was selected ([bcd00dc](https://github.com/DaftMonk/generator-angular-fullstack/commit/bcd00dc)) + +### Features + +* **gen:** make bootstrap and bootstrap ui optional ([f50d094](https://github.com/DaftMonk/generator-angular-fullstack/commit/f50d094)) + + + + +## [2.0.2](https://github.com/DaftMonk/generator-angular-fullstack/compare/v2.0.1...v2.0.2) (2014-07-03) + + +### Bug Fixes + +* **gen:endpoint:** + * fix endpoint spec not adjusting from route url ([163cacf](https://github.com/DaftMonk/generator-angular-fullstack/commit/163cacf)), closes [#298](https://github.com/DaftMonk/generator-angular-fullstack/issues/298) + * fix some urls failing for api creation ([3fe80bd](https://github.com/DaftMonk/generator-angular-fullstack/commit/3fe80bd)) + + + + +## [2.0.1](https://github.com/DaftMonk/generator-angular-fullstack/compare/v2.0.0...v2.0.1) (2014-07-02) + + +### Bug Fixes + +* **server:** local env not being copied ([f65b393](https://github.com/DaftMonk/generator-angular-fullstack/commit/f65b393)) + + ## v2.0.0 (2014-07-02) From 07a158e3368a608f134bd98a8351d1b9deb2c15f Mon Sep 17 00:00:00 2001 From: kingcody Date: Thu, 10 Sep 2015 08:46:46 -0400 Subject: [PATCH 0268/1357] docs(gen): update generated endpoint files [ci skip] --- readme.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index f4ccb9ba7..0e997b633 100644 --- a/readme.md +++ b/readme.md @@ -139,9 +139,11 @@ yo angular-fullstack:endpoint message Produces: server/api/message/index.js - server/api/message/message.spec.js + server/api/message/index.spec.js server/api/message/message.controller.js + server/api/message/message.integration.js server/api/message/message.model.js (optional) + server/api/message/message.events.js (optional) server/api/message/message.socket.js (optional) ### Route From 90f4b05521f4e91ea98bba5750c482c5adeca654 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Thu, 10 Sep 2015 13:27:09 -0400 Subject: [PATCH 0269/1357] feat(gen): remove CoffeeScript --- app/generator.js | 6 +- app/templates/.buildignore | 1 - app/templates/Gruntfile.js | 34 +--- app/templates/_package.json | 4 +- .../app/account(auth)/account(coffee).coffee | 59 ------- .../login/login.controller(coffee).coffee | 20 --- .../settings.controller(coffee).coffee | 17 -- .../signup/signup.controller(coffee).coffee | 33 ---- .../app/admin(auth)/admin(coffee).coffee | 15 -- .../admin.controller(coffee).coffee | 10 -- app/templates/client/app/app(coffee).coffee | 42 ----- .../client/app/main/main(coffee).coffee | 15 -- .../app/main/main.controller(coffee).coffee | 22 --- .../main/main.controller.spec(coffee).coffee | 32 ---- .../auth(auth)/auth.service(coffee).coffee | 150 ------------------ .../auth(auth)/user.service(coffee).coffee | 17 -- .../footer/footer.directive(coffee).coffee | 8 - .../modal.service(coffee).coffee | 71 --------- .../mongoose-error.directive(coffee).coffee | 12 -- .../navbar/navbar.controller(coffee).coffee | 15 -- .../navbar/navbar.directive(coffee).coffee | 7 - .../oauth-buttons.controller(coffee).coffee | 7 - ...uth-buttons.controller.spec(coffee).coffee | 20 --- .../oauth-buttons.directive(coffee).coffee | 9 -- ...auth-buttons.directive.spec(coffee).coffee | 51 ------ .../socket.mock(coffee).coffee | 15 -- .../socket.service(coffee).coffee | 67 -------- .../ui-router.mock(coffee).coffee | 26 --- app/templates/karma.conf.js | 6 +- app/templates/server/config/seed(models).js | 4 +- readme.md | 3 +- test/fixtures/.yo-rc.json | 2 +- test/test-file-creation.js | 10 +- 33 files changed, 16 insertions(+), 794 deletions(-) delete mode 100644 app/templates/client/app/account(auth)/account(coffee).coffee delete mode 100644 app/templates/client/app/account(auth)/login/login.controller(coffee).coffee delete mode 100644 app/templates/client/app/account(auth)/settings/settings.controller(coffee).coffee delete mode 100644 app/templates/client/app/account(auth)/signup/signup.controller(coffee).coffee delete mode 100644 app/templates/client/app/admin(auth)/admin(coffee).coffee delete mode 100644 app/templates/client/app/admin(auth)/admin.controller(coffee).coffee delete mode 100644 app/templates/client/app/app(coffee).coffee delete mode 100644 app/templates/client/app/main/main(coffee).coffee delete mode 100644 app/templates/client/app/main/main.controller(coffee).coffee delete mode 100644 app/templates/client/app/main/main.controller.spec(coffee).coffee delete mode 100644 app/templates/client/components/auth(auth)/auth.service(coffee).coffee delete mode 100644 app/templates/client/components/auth(auth)/user.service(coffee).coffee delete mode 100644 app/templates/client/components/footer/footer.directive(coffee).coffee delete mode 100644 app/templates/client/components/modal(uibootstrap)/modal.service(coffee).coffee delete mode 100644 app/templates/client/components/mongoose-error(auth)/mongoose-error.directive(coffee).coffee delete mode 100644 app/templates/client/components/navbar/navbar.controller(coffee).coffee delete mode 100644 app/templates/client/components/navbar/navbar.directive(coffee).coffee delete mode 100644 app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller(coffee).coffee delete mode 100644 app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller.spec(coffee).coffee delete mode 100644 app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive(coffee).coffee delete mode 100644 app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive.spec(coffee).coffee delete mode 100644 app/templates/client/components/socket(socketio)/socket.mock(coffee).coffee delete mode 100644 app/templates/client/components/socket(socketio)/socket.service(coffee).coffee delete mode 100644 app/templates/client/components/ui-router(uirouter)/ui-router.mock(coffee).coffee diff --git a/app/generator.js b/app/generator.js index 915d5d380..a7d323b91 100644 --- a/app/generator.js +++ b/app/generator.js @@ -86,12 +86,11 @@ export default class Generator extends Base { type: 'list', name: 'script', message: 'What would you like to write scripts with?', - choices: [ 'JavaScript', 'JavaScript + Babel', 'CoffeeScript'], + choices: [ 'JavaScript', 'JavaScript + Babel'], filter: function( val ) { return { 'JavaScript': 'js', - 'JavaScript + Babel': 'babel', - 'CoffeeScript': 'coffee' + 'JavaScript + Babel': 'babel' }[val]; } }, { @@ -340,7 +339,6 @@ export default class Generator extends Base { if(this.filters.ngroute) filters.push('ngroute'); if(this.filters.uirouter) filters.push('uirouter'); if(this.filters.babel) extensions.push('babel'); - if(this.filters.coffee) extensions.push('coffee'); if(this.filters.js) extensions.push('js'); if(this.filters.html) extensions.push('html'); if(this.filters.jade) extensions.push('jade'); diff --git a/app/templates/.buildignore b/app/templates/.buildignore index 3ae6d06a2..e69de29bb 100644 --- a/app/templates/.buildignore +++ b/app/templates/.buildignore @@ -1 +0,0 @@ -*.coffee diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index e480ee3ea..1168d75b0 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -106,14 +106,6 @@ module.exports = function (grunt) { jade: { files: ['<%%= yeoman.client %>/{app,components}/**/*.jade'], tasks: ['jade'] - },<% } if (filters.coffee) { %> - coffee: { - files: ['<%%= yeoman.client %>/{app,components}/**/!(*.spec).{coffee,litcoffee,coffee.md}'], - tasks: ['newer:coffee', 'injector:scripts'] - }, - coffeeTest: { - files: ['<%%= yeoman.client %>/{app,components}/**/*.spec.{coffee,litcoffee,coffee.md}'], - tasks: ['karma'] },<% } %> gruntfile: { files: ['Gruntfile.js'] @@ -431,16 +423,14 @@ module.exports = function (grunt) { // Run some tasks in parallel to speed up the build process concurrent: { - server: [<% if(filters.coffee) { %> - 'coffee',<% } if(filters.babel) { %> + server: [<% if(filters.babel) { %> 'newer:babel:client',<% } if(filters.jade) { %> 'jade',<% } if(filters.stylus) { %> 'stylus',<% } if(filters.sass) { %> 'sass',<% } if(filters.less) { %> 'less',<% } %> ], - test: [<% if(filters.coffee) { %> - 'coffee',<% } if(filters.babel) { %> + test: [<% if(filters.babel) { %> 'newer:babel:client',<% } if(filters.jade) { %> 'jade',<% } if(filters.stylus) { %> 'stylus',<% } if(filters.sass) { %> @@ -456,8 +446,7 @@ module.exports = function (grunt) { logConcurrentOutput: true } }, - dist: [<% if(filters.coffee) { %> - 'coffee',<% } if(filters.babel) { %> + dist: [<% if(filters.babel) { %> 'newer:babel:client',<% } if(filters.jade) { %> 'jade',<% } if(filters.stylus) { %> 'stylus',<% } if(filters.sass) { %> @@ -565,23 +554,6 @@ module.exports = function (grunt) { ext: '.html' }] } - },<% } if (filters.coffee) { %> - - // Compiles CoffeeScript to JavaScript - coffee: { - options: { - sourceMap: true, - sourceRoot: '' - }, - server: { - files: [{ - expand: true, - cwd: 'client', - src: ['{app,components}/**/!(*.spec).coffee'], - dest: '.tmp', - ext: '.js' - }] - } },<% } %> // Compiles ES6 to JavaScript using Babel diff --git a/app/templates/_package.json b/app/templates/_package.json index 8017603f3..a53bc8991 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -48,8 +48,7 @@ "grunt-contrib-imagemin": "^0.9.4", "grunt-contrib-jshint": "~0.11.2", "grunt-contrib-uglify": "^0.9.1", - "grunt-contrib-watch": "~0.6.1",<% if (filters.coffee) { %> - "grunt-contrib-coffee": "^0.13.0",<% } %><% if (filters.jade) { %> + "grunt-contrib-watch": "~0.6.1",<% if (filters.jade) { %> "grunt-contrib-jade": "^0.15.0",<% } %><% if (filters.less) { %> "grunt-contrib-less": "^1.0.0",<% } %><% if(filters.babel) { %> "karma-babel-preprocessor": "^5.2.1", @@ -99,7 +98,6 @@ "karma-chrome-launcher": "~0.2.0", "requirejs": "~2.1.11", "karma-requirejs": "~0.2.2", - "karma-coffee-preprocessor": "~0.3.0", "karma-jade-preprocessor": "0.0.11", "karma-phantomjs-launcher": "~0.2.0", "karma": "~0.13.3", diff --git a/app/templates/client/app/account(auth)/account(coffee).coffee b/app/templates/client/app/account(auth)/account(coffee).coffee deleted file mode 100644 index c794d7f04..000000000 --- a/app/templates/client/app/account(auth)/account(coffee).coffee +++ /dev/null @@ -1,59 +0,0 @@ -'use strict' - -angular.module '<%= scriptAppName %>' -<% if (filters.ngroute) { %>.config ($routeProvider) -> - $routeProvider - .when '/login', - templateUrl: 'app/account/login/login.html' - controller: 'LoginCtrl' - - .when '/logout', - name: 'logout' - referrer: '/' - controller: ($location, $route, Auth) -> - referrer = $route.current.params.referrer or $route.current.referrer or "/" - Auth.logout() - $location.path referrer - - .when '/signup', - templateUrl: 'app/account/signup/signup.html' - controller: 'SignupCtrl' - - .when '/settings', - templateUrl: 'app/account/settings/settings.html' - controller: 'SettingsCtrl' - authenticate: true - -.run ($rootScope) -> - $rootScope.$on '$routeChangeStart', (event, next, current) -> - next.referrer = current.originalPath if next.name is "logout" and current and current.originalPath and not current.authenticate -<% } %><% if (filters.uirouter) { %>.config ($stateProvider) -> - $stateProvider - .state 'login', - url: '/login' - templateUrl: 'app/account/login/login.html' - controller: 'LoginCtrl' - - .state 'logout', - url: '/logout?referrer' - referrer: 'main' - controller: ($state, Auth) -> - referrer = $state.params.referrer or $state.current.referrer or "main" - Auth.logout() - $state.go referrer - - .state 'signup', - url: '/signup' - templateUrl: 'app/account/signup/signup.html' - controller: 'SignupCtrl' - - .state 'settings', - url: '/settings' - templateUrl: 'app/account/settings/settings.html' - controller: 'SettingsCtrl' - authenticate: true - -.run ($rootScope) -> - $rootScope.$on '$stateChangeStart', (event, next, nextParams, current) -> - next.referrer = current.name if next.name is "logout" and current and current.name and not current.authenticate -<% } %> diff --git a/app/templates/client/app/account(auth)/login/login.controller(coffee).coffee b/app/templates/client/app/account(auth)/login/login.controller(coffee).coffee deleted file mode 100644 index 2ba501a42..000000000 --- a/app/templates/client/app/account(auth)/login/login.controller(coffee).coffee +++ /dev/null @@ -1,20 +0,0 @@ -'use strict' - -angular.module '<%= scriptAppName %>' -.controller 'LoginCtrl', ($scope, Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %>) -> - $scope.user = {} - $scope.errors = {} - $scope.login = (form) -> - $scope.submitted = true - - if form.$valid - # Logged in, redirect to home - Auth.login - email: $scope.user.email - password: $scope.user.password - - .then -> - <% if (filters.ngroute) { %>$location.path '/'<% } %><% if (filters.uirouter) { %>$state.go 'main'<% } %> - - .catch (err) -> - $scope.errors.other = err.message diff --git a/app/templates/client/app/account(auth)/settings/settings.controller(coffee).coffee b/app/templates/client/app/account(auth)/settings/settings.controller(coffee).coffee deleted file mode 100644 index e058f167e..000000000 --- a/app/templates/client/app/account(auth)/settings/settings.controller(coffee).coffee +++ /dev/null @@ -1,17 +0,0 @@ -'use strict' - -angular.module '<%= scriptAppName %>' -.controller 'SettingsCtrl', ($scope, User, Auth) -> - $scope.errors = {} - $scope.changePassword = (form) -> - $scope.submitted = true - - if form.$valid - Auth.changePassword $scope.user.oldPassword, $scope.user.newPassword - .then -> - $scope.message = 'Password successfully changed.' - - .catch -> - form.password.$setValidity 'mongoose', false - $scope.errors.other = 'Incorrect password' - $scope.message = '' diff --git a/app/templates/client/app/account(auth)/signup/signup.controller(coffee).coffee b/app/templates/client/app/account(auth)/signup/signup.controller(coffee).coffee deleted file mode 100644 index 68952a74d..000000000 --- a/app/templates/client/app/account(auth)/signup/signup.controller(coffee).coffee +++ /dev/null @@ -1,33 +0,0 @@ -'use strict' - -angular.module '<%= scriptAppName %>' -.controller 'SignupCtrl', ($scope, Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %>) -> - $scope.user = {} - $scope.errors = {} - $scope.register = (form) -> - $scope.submitted = true - - if form.$valid - # Account created, redirect to home - Auth.createUser - name: $scope.user.name - email: $scope.user.email - password: $scope.user.password - - .then -> - <% if (filters.ngroute) { %>$location.path '/'<% } %><% if (filters.uirouter) { %>$state.go 'main'<% } %> - - .catch (err) -> - err = err.data - $scope.errors = {} -<% if (filters.mongooseModels) { %> - # Update validity of form fields that match the mongoose errors - angular.forEach err.errors, (error, field) -> - form[field].$setValidity 'mongoose', false - $scope.errors[field] = error.message<% } - if (filters.sequelizeModels) { %> - # Update validity of form fields that match the sequelize errors - if err.name - angular.forEach err.fields, (field) -> - form[field].$setValidity 'mongoose', false - $scope.errors[field] = err.message<% } %> diff --git a/app/templates/client/app/admin(auth)/admin(coffee).coffee b/app/templates/client/app/admin(auth)/admin(coffee).coffee deleted file mode 100644 index 99b49177f..000000000 --- a/app/templates/client/app/admin(auth)/admin(coffee).coffee +++ /dev/null @@ -1,15 +0,0 @@ -'use strict' - -angular.module '<%= scriptAppName %>' -<% if (filters.ngroute) { %>.config ($routeProvider) -> - $routeProvider - .when '/admin', - templateUrl: 'app/admin/admin.html' - controller: 'AdminCtrl' -<% } %><% if (filters.uirouter) { %>.config ($stateProvider) -> - $stateProvider - .state 'admin', - url: '/admin' - templateUrl: 'app/admin/admin.html' - controller: 'AdminCtrl' -<% } %> diff --git a/app/templates/client/app/admin(auth)/admin.controller(coffee).coffee b/app/templates/client/app/admin(auth)/admin.controller(coffee).coffee deleted file mode 100644 index 04af43178..000000000 --- a/app/templates/client/app/admin(auth)/admin.controller(coffee).coffee +++ /dev/null @@ -1,10 +0,0 @@ -'use strict' - -angular.module '<%= scriptAppName %>' -.controller 'AdminCtrl', ($scope, $http, Auth, User) -> - - $scope.users = User.query() - - $scope.delete = (user) -> - User.remove id: user._id - $scope.users.splice @$index, 1 diff --git a/app/templates/client/app/app(coffee).coffee b/app/templates/client/app/app(coffee).coffee deleted file mode 100644 index 6458ca920..000000000 --- a/app/templates/client/app/app(coffee).coffee +++ /dev/null @@ -1,42 +0,0 @@ -'use strict' - -angular.module '<%= scriptAppName %>', [<%- angularModules %>] -<% if (filters.ngroute) { %>.config ($routeProvider, $locationProvider<% if (filters.auth) { %>, $httpProvider<% } %>) -> - $routeProvider - .otherwise - redirectTo: '/' - - $locationProvider.html5Mode true<% if (filters.auth) { %> - $httpProvider.interceptors.push 'authInterceptor'<% } %> -<% } %><% if (filters.uirouter) { %>.config ($stateProvider, $urlRouterProvider, $locationProvider<% if (filters.auth) { %>, $httpProvider<% } %>) -> - $urlRouterProvider - .otherwise '/' - - $locationProvider.html5Mode true<% if (filters.auth) { %> - $httpProvider.interceptors.push 'authInterceptor'<% } %> -<% } %><% if (filters.auth) { %> -.factory 'authInterceptor', ($rootScope, $q, $cookies<% if (filters.ngroute) { %>, $location<% } if (filters.uirouter) { %>, $injector<% } %>) -> - <% if (filters.uirouter) { %>state = null - <% } %># Add authorization token to headers - request: (config) -> - config.headers = config.headers or {} - config.headers.Authorization = 'Bearer ' + $cookies.get 'token' if $cookies.get 'token' - config - - # Intercept 401s and redirect you to login - responseError: (response) -> - if response.status is 401 - <% if (filters.ngroute) { %>$location.path '/login'<% } if (filters.uirouter) { %>(state || state = $injector.get '$state').go 'login'<% } %> - # remove any stale tokens - $cookies.remove 'token' - - $q.reject response - -.run ($rootScope<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %>, Auth) -> - # Redirect to login if route requires auth and the user is not logged in - $rootScope.$on <% if (filters.ngroute) { %>'$routeChangeStart'<% } %><% if (filters.uirouter) { %>'$stateChangeStart'<% } %>, (event, next) -> - if next.authenticate - Auth.isLoggedIn (loggedIn) -> - if !loggedIn - event.preventDefault() - <% if (filters.ngroute) { %>$location.path '/login'<% } %><% if (filters.uirouter) { %>$state.go 'login'<% }} %> diff --git a/app/templates/client/app/main/main(coffee).coffee b/app/templates/client/app/main/main(coffee).coffee deleted file mode 100644 index 04cd367bb..000000000 --- a/app/templates/client/app/main/main(coffee).coffee +++ /dev/null @@ -1,15 +0,0 @@ -'use strict' - -angular.module '<%= scriptAppName %>' -<% if (filters.ngroute) { %>.config ($routeProvider) -> - $routeProvider - .when '/', - templateUrl: 'app/main/main.html' - controller: 'MainCtrl' -<% } %><% if (filters.uirouter) { %>.config ($stateProvider) -> - $stateProvider - .state 'main', - url: '/' - templateUrl: 'app/main/main.html' - controller: 'MainCtrl' -<% } %> diff --git a/app/templates/client/app/main/main.controller(coffee).coffee b/app/templates/client/app/main/main.controller(coffee).coffee deleted file mode 100644 index fdd03c644..000000000 --- a/app/templates/client/app/main/main.controller(coffee).coffee +++ /dev/null @@ -1,22 +0,0 @@ -'use strict' - -angular.module '<%= scriptAppName %>' -.controller 'MainCtrl', ($scope, $http<% if (filters.socketio) { %>, socket<% } %>) -> - $scope.awesomeThings = [] - - $http.get('/api/things').then (response) -> - $scope.awesomeThings = response.data - <% if (filters.socketio) { %>socket.syncUpdates 'thing', $scope.awesomeThings<% } %> -<% if (filters.models) { %> - $scope.addThing = -> - return if $scope.newThing is '' - $http.post '/api/things', - name: $scope.newThing - - $scope.newThing = '' - - $scope.deleteThing = (thing) -> - $http.delete '/api/things/' + thing._id<% } %><% if (filters.socketio) { %> - - $scope.$on '$destroy', -> - socket.unsyncUpdates 'thing'<% } %> diff --git a/app/templates/client/app/main/main.controller.spec(coffee).coffee b/app/templates/client/app/main/main.controller.spec(coffee).coffee deleted file mode 100644 index 0284253d7..000000000 --- a/app/templates/client/app/main/main.controller.spec(coffee).coffee +++ /dev/null @@ -1,32 +0,0 @@ -'use strict' - -describe 'Controller: MainCtrl', -> - - # load the controller's module - beforeEach module '<%= scriptAppName %>' <% if (filters.uirouter) {%> - beforeEach module 'stateMock' <% } %><% if (filters.socketio) {%> - beforeEach module 'socketMock' <% } %> - - MainCtrl = undefined - scope = undefined<% if (filters.uirouter) {%> - state = undefined<% } %> - $httpBackend = undefined - - # Initialize the controller and a mock scope - beforeEach inject (_$httpBackend_, $controller, $rootScope<% if (filters.uirouter) {%>, $state<% } %>) -> - $httpBackend = _$httpBackend_ - $httpBackend.expectGET('/api/things').respond [ - 'HTML5 Boilerplate' - 'AngularJS' - 'Karma' - 'Express' - ] - scope = $rootScope.$new()<% if (filters.uirouter) {%> - state = $state<% } %> - MainCtrl = $controller 'MainCtrl', - $scope: scope - - it 'should attach a list of things to the scope', -> - $httpBackend.flush()<% if (filters.jasmine) { %> - expect(scope.awesomeThings.length).toBe 4 <% } if (filters.mocha) { %> - <%= expect() %>scope.awesomeThings.length<%= to() %>.equal 4<% } %> diff --git a/app/templates/client/components/auth(auth)/auth.service(coffee).coffee b/app/templates/client/components/auth(auth)/auth.service(coffee).coffee deleted file mode 100644 index 2892d04ed..000000000 --- a/app/templates/client/components/auth(auth)/auth.service(coffee).coffee +++ /dev/null @@ -1,150 +0,0 @@ -'use strict' - -angular.module '<%= scriptAppName %>' -.factory 'Auth', ($http, User, $cookies, $q) -> - currentUser = if $cookies.get 'token' then User.get() else {} - - ### - Authenticate user and save token - - @param {Object} user - login info - @param {Function} callback - optional, function(error, user) - @return {Promise} - ### - login: (user, callback) -> - $http.post '/auth/local', - email: user.email - password: user.password - - .then (res) -> - $cookies.put 'token', res.data.token - currentUser = User.get() - currentUser.$promise - - .then (user) -> - callback? null, user - user - - .catch (err) => - @logout() - callback? err.data - $q.reject err.data - - - ### - Delete access token and user info - ### - logout: -> - $cookies.remove 'token' - currentUser = {} - return - - - ### - Create a new user - - @param {Object} user - user info - @param {Function} callback - optional, function(error, user) - @return {Promise} - ### - createUser: (user, callback) -> - User.save user, - (data) -> - $cookies.put 'token', data.token - currentUser = User.get() - callback? null, user - - , (err) => - @logout() - callback? err - - .$promise - - - ### - Change password - - @param {String} oldPassword - @param {String} newPassword - @param {Function} callback - optional, function(error, user) - @return {Promise} - ### - changePassword: (oldPassword, newPassword, callback) -> - User.changePassword - id: currentUser._id - , - oldPassword: oldPassword - newPassword: newPassword - - , () -> - callback? null - - , (err) -> - callback? err - - .$promise - - - ### - Gets all available info on a user - (synchronous|asynchronous) - - @param {Function|*} callback - optional, funciton(user) - @return {Object|Promise} - ### - getCurrentUser: (callback) -> - return currentUser if arguments.length is 0 - - value = if (currentUser.hasOwnProperty("$promise")) then currentUser.$promise else currentUser - $q.when value - - .then (user) -> - callback? user - user - - , -> - callback? {} - {} - - - ### - Check if a user is logged in - (synchronous|asynchronous) - - @param {Function|*} callback - optional, function(is) - @return {Bool|Promise} - ### - isLoggedIn: (callback) -> - return currentUser.hasOwnProperty("role") if arguments.length is 0 - - @getCurrentUser null - - .then (user) -> - is_ = user.hasOwnProperty("role") - callback? is_ - is_ - - - ### - Check if a user is an admin - (synchronous|asynchronous) - - @param {Function|*} callback - optional, function(is) - @return {Bool|Promise} - ### - isAdmin: (callback) -> - return currentUser.role is "admin" if arguments.length is 0 - - @getCurrentUser null - - .then (user) -> - is_ = user.role is "admin" - callback? is_ - is_ - - - ### - Get auth token - ### - getToken: -> - $cookies.get 'token' diff --git a/app/templates/client/components/auth(auth)/user.service(coffee).coffee b/app/templates/client/components/auth(auth)/user.service(coffee).coffee deleted file mode 100644 index e0dc2e839..000000000 --- a/app/templates/client/components/auth(auth)/user.service(coffee).coffee +++ /dev/null @@ -1,17 +0,0 @@ -'use strict' - -angular.module '<%= scriptAppName %>' -.factory 'User', ($resource) -> - $resource '/api/users/:id/:controller', - id: '@_id' - , - changePassword: - method: 'PUT' - params: - controller: 'password' - - get: - method: 'GET' - params: - id: 'me' - diff --git a/app/templates/client/components/footer/footer.directive(coffee).coffee b/app/templates/client/components/footer/footer.directive(coffee).coffee deleted file mode 100644 index 467006759..000000000 --- a/app/templates/client/components/footer/footer.directive(coffee).coffee +++ /dev/null @@ -1,8 +0,0 @@ -'use strict' - -angular.module '<%= scriptAppName %>' -.directive 'footer', -> - templateUrl: 'components/footer/footer.html' - restrict: 'E', - link: (scope, element) -> - element.addClass('footer') diff --git a/app/templates/client/components/modal(uibootstrap)/modal.service(coffee).coffee b/app/templates/client/components/modal(uibootstrap)/modal.service(coffee).coffee deleted file mode 100644 index eae01f69f..000000000 --- a/app/templates/client/components/modal(uibootstrap)/modal.service(coffee).coffee +++ /dev/null @@ -1,71 +0,0 @@ -'use strict' - -angular.module '<%= scriptAppName %>' -.factory 'Modal', ($rootScope, $modal) -> - - ### - Opens a modal - @param {Object} scope - an object to be merged with modal's scope - @param {String} modalClass - (optional) class(es) to be applied to the modal - @return {Object} - the instance $modal.open() returns - ### - openModal = (scope, modalClass) -> - modalScope = $rootScope.$new() - scope = scope or {} - modalClass = modalClass or 'modal-default' - angular.extend modalScope, scope - $modal.open - templateUrl: 'components/modal/modal.html' - windowClass: modalClass - scope: modalScope - - - # Public API here - - # Confirmation modals - confirm: - - ### - Create a function to open a delete confirmation modal (ex. ng-click='myModalFn(name, arg1, arg2...)') - @param {Function} del - callback, ran when delete is confirmed - @return {Function} - the function to open the modal (ex. myModalFn) - ### - delete: (del) -> - del = del or angular.noop - - ### - Open a delete confirmation modal - @param {String} name - name or info to show on modal - @param {All} - any additional args are passed staight to del callback - ### - -> - args = Array::slice.call arguments - name = args.shift() - deleteModal = undefined - deleteModal = openModal( - modal: - dismissable: true - title: 'Confirm Delete' - html: '

Are you sure you want to delete ' + name + ' ?

' - buttons: [ - { - classes: 'btn-danger' - text: 'Delete' - click: (e) -> - deleteModal.close e - return - } - { - classes: 'btn-default' - text: 'Cancel' - click: (e) -> - deleteModal.dismiss e - return - } - ] - , 'modal-danger') - deleteModal.result.then (event) -> - del.apply event, args - return - - return diff --git a/app/templates/client/components/mongoose-error(auth)/mongoose-error.directive(coffee).coffee b/app/templates/client/components/mongoose-error(auth)/mongoose-error.directive(coffee).coffee deleted file mode 100644 index cf0e1ccf0..000000000 --- a/app/templates/client/components/mongoose-error(auth)/mongoose-error.directive(coffee).coffee +++ /dev/null @@ -1,12 +0,0 @@ -'use strict' - -### -Removes server error when user updates input -### -angular.module '<%= scriptAppName %>' -.directive 'mongooseError', -> - restrict: 'A' - require: 'ngModel' - link: (scope, element, attrs, ngModel) -> - element.on 'keydown', -> - ngModel.$setValidity 'mongoose', true diff --git a/app/templates/client/components/navbar/navbar.controller(coffee).coffee b/app/templates/client/components/navbar/navbar.controller(coffee).coffee deleted file mode 100644 index 98eaf2213..000000000 --- a/app/templates/client/components/navbar/navbar.controller(coffee).coffee +++ /dev/null @@ -1,15 +0,0 @@ -'use strict' - -angular.module '<%= scriptAppName %>' -.controller 'NavbarCtrl', ($scope<% if(!filters.uirouter) { %>, $location<% } %><% if (filters.auth) {%>, Auth<% } %>) -> - $scope.menu = [ - title: 'Home' - <% if (filters.uirouter) { %>state: 'main'<% } else { %>link: '/'<% } %> - ] - $scope.isCollapsed = true<% if (filters.auth) {%> - $scope.isLoggedIn = Auth.isLoggedIn - $scope.isAdmin = Auth.isAdmin - $scope.getCurrentUser = Auth.getCurrentUser<% } %><% if(!filters.uirouter) { %> - - $scope.isActive = (route) -> - route is $location.path()<% } %> diff --git a/app/templates/client/components/navbar/navbar.directive(coffee).coffee b/app/templates/client/components/navbar/navbar.directive(coffee).coffee deleted file mode 100644 index bea476822..000000000 --- a/app/templates/client/components/navbar/navbar.directive(coffee).coffee +++ /dev/null @@ -1,7 +0,0 @@ -'use strict' - -angular.module '<%= scriptAppName %>' -.directive 'navbar', -> - templateUrl: 'components/navbar/navbar.html' - restrict: 'E' - controller: 'NavbarCtrl' diff --git a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller(coffee).coffee b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller(coffee).coffee deleted file mode 100644 index 4dca2832f..000000000 --- a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller(coffee).coffee +++ /dev/null @@ -1,7 +0,0 @@ -'use strict' - -angular.module('<%= scriptAppName %>') -.controller 'OauthButtonsCtrl', ($window) -> - @loginOauth = (provider) -> - $window.location.href = '/auth/' + provider - return; diff --git a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller.spec(coffee).coffee b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller.spec(coffee).coffee deleted file mode 100644 index 59b4dd9e4..000000000 --- a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller.spec(coffee).coffee +++ /dev/null @@ -1,20 +0,0 @@ -'use strict' - -describe 'Controller: OauthButtonsCtrl', -> - # load the controller's module - beforeEach module('<%= scriptAppName %>') - - OauthButtonsCtrl = null - $window = null - - # Initialize the controller and a mock $window - beforeEach inject ($controller) -> - $window = location: {} - OauthButtonsCtrl = $controller 'OauthButtonsCtrl', $window: $window - return - - it 'should attach loginOauth', -><% if (filters.jasmine) { %> - expect(OauthButtonsCtrl.loginOauth).toEqual jasmine.any Function<% } if (filters.mocha) { %> - <%= expect() %>OauthButtonsCtrl.loginOauth<%= to() %>.be.a 'function' <% } %> - return - return diff --git a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive(coffee).coffee b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive(coffee).coffee deleted file mode 100644 index f009e5b1d..000000000 --- a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive(coffee).coffee +++ /dev/null @@ -1,9 +0,0 @@ -'use strict' - -angular.module('<%= scriptAppName %>') -.directive 'oauthButtons', -> - templateUrl: 'components/oauth-buttons/oauth-buttons.html' - restrict: 'EA' - controller: 'OauthButtonsCtrl' - controllerAs: 'OauthButtons' - scope: classes: '@' diff --git a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive.spec(coffee).coffee b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive.spec(coffee).coffee deleted file mode 100644 index 903d05476..000000000 --- a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive.spec(coffee).coffee +++ /dev/null @@ -1,51 +0,0 @@ -'use strict' - -describe 'Directive: oauthButtons', -> - # load the directive's module and view - beforeEach module('<%= scriptAppName %>') - beforeEach module('components/oauth-buttons/oauth-buttons.html') - - element = null - parentScope = null - elementScope = null - - compileDirective = (template) -> - inject ($compile) -> - element = angular.element template - element = $compile(element) parentScope - parentScope.$digest() - elementScope = element.isolateScope() - - beforeEach inject ($rootScope) -> - parentScope = $rootScope.$new() - - it 'should contain anchor buttons', -> - compileDirective ''<% if (filters.jasmine) { %> - expect(element.find('a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>').length).toBeGreaterThan 0<% } if (filters.mocha) { %> - <%= expect() %>element.find('a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>').length<%= to() %>.be.at.least 1<% } %> - return - - it 'should evaluate and bind the classes attribute to scope.classes', -> - parentScope.scopedClass = 'scopedClass1' - compileDirective ''<% if (filters.jasmine) { %> - expect(elementScope.classes).toEqual 'testClass1 scopedClass1'<% } if (filters.mocha) { %> - <%= expect() %>elementScope.classes<%= to() %>.equal 'testClass1 scopedClass1'<% } %> - return - - it 'should bind scope.classes to class names on the anchor buttons', -> - compileDirective '' - - # Add classes - elementScope.classes = 'testClass1 testClass2' - elementScope.$digest()<% if (filters.jasmine) { %> - expect(element.find('a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.testClass1.testClass2').length).toBeGreaterThan 0<% } if (filters.mocha) { %> - <%= expect() %>element.find('a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.testClass1.testClass2').length<%= to() %>.be.at.least 1<% } %> - - # Remove classes - elementScope.classes = '' - elementScope.$digest()<% if (filters.jasmine) { %> - expect(element.find('a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.testClass1.testClass2').length).toEqual 0<% } if (filters.mocha) { %> - <%= expect() %>element.find('a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.testClass1.testClass2').length<%= to() %>.equal 0<% } %> - - return - return diff --git a/app/templates/client/components/socket(socketio)/socket.mock(coffee).coffee b/app/templates/client/components/socket(socketio)/socket.mock(coffee).coffee deleted file mode 100644 index 6f565bbc2..000000000 --- a/app/templates/client/components/socket(socketio)/socket.mock(coffee).coffee +++ /dev/null @@ -1,15 +0,0 @@ -'use strict' - -angular.module 'socketMock', [] -.factory 'socket', -> - socket: - connect: -> - - on: -> - - emit: -> - - receive: -> - - syncUpdates: -> - unsyncUpdates: -> diff --git a/app/templates/client/components/socket(socketio)/socket.service(coffee).coffee b/app/templates/client/components/socket(socketio)/socket.service(coffee).coffee deleted file mode 100644 index 3fef1c00e..000000000 --- a/app/templates/client/components/socket(socketio)/socket.service(coffee).coffee +++ /dev/null @@ -1,67 +0,0 @@ -# global io - -'use strict' - -angular.module '<%= scriptAppName %>' -.factory 'socket', (socketFactory) -> - - # socket.io now auto-configures its connection when we omit a connection url - ioSocket = io '', - # Send auth token on connection, you will need to DI the Auth service above - # 'query': 'token=' + Auth.getToken() - path: '/socket.io-client' - - socket = socketFactory ioSocket: ioSocket - - socket: socket - - ### - Register listeners to sync an array with updates on a model - - Takes the array we want to sync, the model name that socket updates are sent from, - and an optional callback function after new items are updated. - - @param {String} modelName - @param {Array} array - @param {Function} callback - ### - syncUpdates: (modelName, array, callback) -> - - ### - Syncs item creation/updates on 'model:save' - ### - socket.on modelName + ':save', (item) -> - oldItem = _.find array, - _id: item._id - - index = array.indexOf oldItem - event = 'created' - - # replace oldItem if it exists - # otherwise just add item to the collection - if oldItem - array.splice index, 1, item - event = 'updated' - else - array.push item - - callback? event, item, array - - ### - Syncs removed items on 'model:remove' - ### - socket.on modelName + ':remove', (item) -> - event = 'deleted' - _.remove array, - _id: item._id - - callback? event, item, array - - ### - Removes listeners for a models updates on the socket - - @param modelName - ### - unsyncUpdates: (modelName) -> - socket.removeAllListeners modelName + ':save' - socket.removeAllListeners modelName + ':remove' diff --git a/app/templates/client/components/ui-router(uirouter)/ui-router.mock(coffee).coffee b/app/templates/client/components/ui-router(uirouter)/ui-router.mock(coffee).coffee deleted file mode 100644 index ff3937c35..000000000 --- a/app/templates/client/components/ui-router(uirouter)/ui-router.mock(coffee).coffee +++ /dev/null @@ -1,26 +0,0 @@ -'use strict' - -angular.module 'stateMock', [] -angular.module('stateMock').service '$state', ($q) -> - @expectedTransitions = [] - - @transitionTo = (stateName) -> - if @expectedTransitions.length > 0 - expectedState = @expectedTransitions.shift() - throw Error('Expected transition to state: ' + expectedState + ' but transitioned to ' + stateName) if expectedState isnt stateName - else - throw Error('No more transitions were expected! Tried to transition to ' + stateName) - console.log 'Mock transition to: ' + stateName - deferred = $q.defer() - promise = deferred.promise - deferred.resolve() - promise - - @go = @transitionTo - - @expectTransitionTo = (stateName) -> - @expectedTransitions.push stateName - - @ensureAllTransitionsHappened = -> - throw Error('Not all transitions happened!') if @expectedTransitions.length > 0 - @ diff --git a/app/templates/karma.conf.js b/app/templates/karma.conf.js index 9b46a3a22..61aa87b74 100644 --- a/app/templates/karma.conf.js +++ b/app/templates/karma.conf.js @@ -22,11 +22,8 @@ module.exports = function(config) { // endbower<% if (filters.socketio) { %> 'node_modules/socket.io-client/socket.io.js',<% } %> 'client/app/app.js', - 'client/app/app.coffee', 'client/app/**/*.js', - 'client/app/**/*.coffee', 'client/components/**/*.js', - 'client/components/**/*.coffee', 'client/app/**/*.jade', 'client/components/**/*.jade', 'client/app/**/*.html', @@ -36,8 +33,7 @@ module.exports = function(config) { preprocessors: { '**/*.jade': 'ng-jade2js', '**/*.html': 'html2js',<% if(filters.babel) { %> - 'client/{app,components}/**/*.js': 'babel',<% } %> - '**/*.coffee': 'coffee', + 'client/{app,components}/**/*.js': 'babel'<% } %> }, ngHtml2JsPreprocessor: { diff --git a/app/templates/server/config/seed(models).js b/app/templates/server/config/seed(models).js index a0e5edb76..81f3c6b5c 100644 --- a/app/templates/server/config/seed(models).js +++ b/app/templates/server/config/seed(models).js @@ -19,9 +19,9 @@ var User = sqldb.User;<% } %><% } %> <% if (filters.mongooseModels) { %>Thing.create({<% } if (filters.sequelizeModels) { %>Thing.bulkCreate([{<% } %> name: 'Development Tools', - info: 'Integration with popular tools such as Bower, Grunt, Karma, ' + + info: 'Integration with popular tools such as Bower, Grunt, Babel, Karma, ' + 'Mocha, JSHint, Node Inspector, Livereload, Protractor, Jade, ' + - 'Stylus, Sass, CoffeeScript, and Less.' + 'Stylus, Sass, and Less.' }, { name: 'Server and Client integration', info: 'Built with a powerful and fun stack: MongoDB, Express, ' + diff --git a/readme.md b/readme.md index f4ccb9ba7..d00f531cd 100644 --- a/readme.md +++ b/readme.md @@ -43,7 +43,7 @@ Run `grunt` for building, `grunt serve` for preview, and `grunt serve:dist` for **Client** -* Scripts: `JavaScript`, `CoffeeScript`, `Babel` +* Scripts: `JavaScript`, `Babel` * Markup: `HTML`, `Jade` * Stylesheets: `CSS`, `Stylus`, `Sass`, `Less`, * Angular Routers: `ngRoute`, `ui-router` @@ -64,7 +64,6 @@ A grunt task looks for new files in your `client/app` and `client/components` fo * `stylus` files into `client/app.styl` * `css` files into `client/index.html` * `js` files into `client/index.html` -* `coffeescript` temp `js` files into `client/index.html` * `babel` temp `js` files into `client/index.html` ## Generators diff --git a/test/fixtures/.yo-rc.json b/test/fixtures/.yo-rc.json index 01d568984..716e42b6c 100644 --- a/test/fixtures/.yo-rc.json +++ b/test/fixtures/.yo-rc.json @@ -13,7 +13,7 @@ "registerModelsFile": "server/sqldb/index.js", "modelsNeedle": "// Insert models below", "filters": { - "coffee": true, + "babel": true, "html": true, "less": true, "uirouter": true, diff --git a/test/test-file-creation.js b/test/test-file-creation.js index cca66a78f..bfcfebe5a 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -136,8 +136,7 @@ describe('angular-fullstack generator', function () { html: 'html' }, script: { - js: 'js', - coffee: 'coffee' + js: 'js' } }, files = []; @@ -475,7 +474,6 @@ describe('angular-fullstack generator', function () { gen.run(function () { assert.file([ 'client/app/main/main.less', - 'client/app/main/main.coffee', 'server/auth/google/passport.js' ]); done(); @@ -508,7 +506,8 @@ describe('angular-fullstack generator', function () { describe('with other preprocessors and oauth', function() { var testOptions = { - script: 'coffee', + script: 'js', + babel: true, markup: 'jade', stylesheet: 'less', router: 'uirouter', @@ -652,7 +651,8 @@ describe('angular-fullstack generator', function () { describe('with other preprocessors and no server options', function() { var testOptions = { - script: 'coffee', + script: 'js', + babel: true, markup: 'jade', stylesheet: 'stylus', router: 'ngroute', From 4cee3186fb3d3b536b3932757f6cc0e17e3d3acf Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Thu, 10 Sep 2015 21:30:52 -0400 Subject: [PATCH 0270/1357] feat(gen): add note about being prerelease version --- app/generator.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/generator.js b/app/generator.js index 915d5d380..548240e0b 100644 --- a/app/generator.js +++ b/app/generator.js @@ -37,6 +37,12 @@ export default class Generator extends Base { }, info: function () { + this.log(chalk.red(` +################################################################ +# NOTE: You are using a pre-release version of +# generator-angular-fullstack. For a more stable version, run +# \`npm install -g generator-angular-fullstack@^2.0.0\` +################################################################`)); this.log(this.yoWelcome); this.log('Out of the box I create an AngularJS app with an Express server.\n'); }, From f56ab60c03434c52bd8f1ed5d82c4e89fd310d6a Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Thu, 10 Sep 2015 21:17:16 -0400 Subject: [PATCH 0271/1357] feat(gen): Show gen version in console & add to .yo-rc.json --- app/generator.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/generator.js b/app/generator.js index 548240e0b..a68fa0b35 100644 --- a/app/generator.js +++ b/app/generator.js @@ -30,6 +30,7 @@ export default class Generator extends Base { return { init: function () { + this.config.set('generatorVersion', this.rootGeneratorVersion()); this.filters = {}; // init shared generator properies and methods @@ -43,6 +44,7 @@ export default class Generator extends Base { # generator-angular-fullstack. For a more stable version, run # \`npm install -g generator-angular-fullstack@^2.0.0\` ################################################################`)); + this.log('You\'re using the Angular Full-Stack Generator, version ' + this.rootGeneratorVersion()); this.log(this.yoWelcome); this.log('Out of the box I create an AngularJS app with an Express server.\n'); }, From 7a2c01eb7c26cdc69a0c76a05e58e6bfb2ab8b4b Mon Sep 17 00:00:00 2001 From: kingcody Date: Fri, 11 Sep 2015 00:29:26 -0400 Subject: [PATCH 0272/1357] fix(gen): require `q` and `grunt` in gruntUtils --- Gruntfile.js | 8 ++-- task-utils/grunt.js | 112 +++++++++++++++++++++++--------------------- 2 files changed, 62 insertions(+), 58 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index e776b3c48..64e407a11 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -4,14 +4,14 @@ var shell = require('shelljs'); var child_process = require('child_process'); var Q = require('q'); var helpers = require('yeoman-generator').test; -var gruntUtils = require('./task-utils/grunt'); var fs = require('fs'); var path = require('path'); -var gitCmd = gruntUtils.gitCmd; -var gitCmdAsync = gruntUtils.gitCmdAsync; - module.exports = function (grunt) { + var gruntUtils = require('./task-utils/grunt')(grunt); + var gitCmd = gruntUtils.gitCmd; + var gitCmdAsync = gruntUtils.gitCmdAsync; + // Load grunt tasks automatically, when needed require('jit-grunt')(grunt, { buildcontrol: 'grunt-build-control' diff --git a/task-utils/grunt.js b/task-utils/grunt.js index 70a598b8b..973a01073 100644 --- a/task-utils/grunt.js +++ b/task-utils/grunt.js @@ -2,72 +2,76 @@ var path = require('path'); var fs = require('fs'); +var Q = require('q'); -exports = module.exports = { - gitCmd: function gitCmd(args, opts, done) { - grunt.util.spawn({ - cmd: process.platform === 'win32' ? 'git.cmd' : 'git', - args: args, - opts: opts || {} - }, done); - }, +exports = module.exports = function(grunt) { + var self; + return self = { + gitCmd: function(args, opts, done) { + grunt.util.spawn({ + cmd: process.platform === 'win32' ? 'git.cmd' : 'git', + args: args, + opts: opts || {} + }, done); + }, - gitCmdAsync: function gitCmdAsync(args, opts) { - return function() { - var deferred = Q.defer(); - gitCmd(args, opts, function(err) { - if (err) { return deferred.reject(err); } - deferred.resolve(); - }); - return deferred.promise; - }; - }, + gitCmdAsync: function(args, opts) { + return function() { + var deferred = Q.defer(); + self.gitCmd(args, opts, function(err) { + if (err) { return deferred.reject(err); } + deferred.resolve(); + }); + return deferred.promise; + }; + }, - conventionalChangelog: { - finalizeContext: function(context, writerOpts, commits, keyCommit) { - var gitSemverTags = context.gitSemverTags; - var commitGroups = context.commitGroups; + conventionalChangelog: { + finalizeContext: function(context, writerOpts, commits, keyCommit) { + var gitSemverTags = context.gitSemverTags; + var commitGroups = context.commitGroups; - if ((!context.currentTag || !context.previousTag) && keyCommit) { - var match = /tag:\s*(.+?)[,\)]/gi.exec(keyCommit.gitTags); - var currentTag = context.currentTag = context.currentTag || match ? match[1] : null; - var index = gitSemverTags.indexOf(currentTag); - var previousTag = context.previousTag = gitSemverTags[index + 1]; + if ((!context.currentTag || !context.previousTag) && keyCommit) { + var match = /tag:\s*(.+?)[,\)]/gi.exec(keyCommit.gitTags); + var currentTag = context.currentTag = context.currentTag || match ? match[1] : null; + var index = gitSemverTags.indexOf(currentTag); + var previousTag = context.previousTag = gitSemverTags[index + 1]; - if (!previousTag) { - if (options.append) { - context.previousTag = context.previousTag || commits[0] ? commits[0].hash : null; - } else { - context.previousTag = context.previousTag || commits[commits.length - 1] ? commits[commits.length - 1].hash : null; + if (!previousTag) { + if (options.append) { + context.previousTag = context.previousTag || commits[0] ? commits[0].hash : null; + } else { + context.previousTag = context.previousTag || commits[commits.length - 1] ? commits[commits.length - 1].hash : null; + } } + } else { + context.previousTag = context.previousTag || gitSemverTags[0]; + context.currentTag = context.currentTag || 'v' + context.version; } - } else { - context.previousTag = context.previousTag || gitSemverTags[0]; - context.currentTag = context.currentTag || 'v' + context.version; - } - if (typeof context.linkCompare !== 'boolean' && context.previousTag && context.currentTag) { - context.linkCompare = true; - } + if (typeof context.linkCompare !== 'boolean' && context.previousTag && context.currentTag) { + context.linkCompare = true; + } - if (Array.isArray(commitGroups)) { - for (var i = 0, commitGroupsLength = commitGroups.length; i < commitGroupsLength; i++) { - var commits = commitGroups[i].commits; - if (Array.isArray(commits)) { - for (var n = 1, commitsLength = commits.length; n < commitsLength; n++) { - var commit = commits[n], prevCommit = commits[n - 1]; - if (commit.scope && commit.scope === prevCommit.scope) { - commit.subScope = true; - if (prevCommit.scope && !prevCommit.subScope) { - prevCommit.leadScope = true; + if (Array.isArray(commitGroups)) { + for (var i = 0, commitGroupsLength = commitGroups.length; i < commitGroupsLength; i++) { + var commits = commitGroups[i].commits; + if (Array.isArray(commits)) { + for (var n = 1, commitsLength = commits.length; n < commitsLength; n++) { + var commit = commits[n], prevCommit = commits[n - 1]; + if (commit.scope && commit.scope === prevCommit.scope) { + commit.subScope = true; + if (prevCommit.scope && !prevCommit.subScope) { + prevCommit.leadScope = true; + } } } } } } - } - return context; - }, - commitPartial: fs.readFileSync(path.resolve(__dirname, 'changelog-templates', 'commit.hbs')).toString() - } + return context; + }, + commitPartial: fs.readFileSync(path.resolve(__dirname, 'changelog-templates', 'commit.hbs')).toString() + } + }; }; From a958f90ca4243109e13f1ee5cccbb646cf33d961 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Fri, 11 Sep 2015 16:55:26 -0400 Subject: [PATCH 0273/1357] fix(npm): always include grunt-babel Closes #1282 --- app/templates/_package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 8017603f3..212759cf1 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -52,8 +52,8 @@ "grunt-contrib-coffee": "^0.13.0",<% } %><% if (filters.jade) { %> "grunt-contrib-jade": "^0.15.0",<% } %><% if (filters.less) { %> "grunt-contrib-less": "^1.0.0",<% } %><% if(filters.babel) { %> - "karma-babel-preprocessor": "^5.2.1", - "grunt-babel": "~5.0.0",<% } %> + "karma-babel-preprocessor": "^5.2.1",<% } %> + "grunt-babel": "~5.0.0", "grunt-google-cdn": "~0.4.0", "grunt-jscs": "^2.0.0", "grunt-newer": "^1.1.1", From 7d7daee655d3ebb76a0f6b9f1e25d0af687688d9 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 2 Sep 2015 19:48:11 -0400 Subject: [PATCH 0274/1357] refactor(client:main): use controller as, named function, new name controller as main, MainCtrl -> MainController --- app/templates/client/app/main/main(html).html | 8 ++-- app/templates/client/app/main/main(jade).jade | 8 ++-- app/templates/client/app/main/main(js).js | 6 ++- .../client/app/main/main.controller(js).js | 48 +++++++++++-------- .../app/main/main.controller.spec(js).js | 14 +++--- 5 files changed, 46 insertions(+), 38 deletions(-) diff --git a/app/templates/client/app/main/main(html).html b/app/templates/client/app/main/main(html).html index 0d745d9a8..4f85aa54e 100644 --- a/app/templates/client/app/main/main(html).html +++ b/app/templates/client/app/main/main(html).html @@ -12,8 +12,8 @@

'Allo, 'Allo!

<% if (filters.socketio) { %> @@ -21,9 +21,9 @@

Features:

- + - +

<% } %> diff --git a/app/templates/client/app/main/main(jade).jade b/app/templates/client/app/main/main(jade).jade index 3277e7b05..54d1d7e9c 100644 --- a/app/templates/client/app/main/main(jade).jade +++ b/app/templates/client/app/main/main(jade).jade @@ -10,17 +10,17 @@ header#banner.hero-unit .row .col-lg-12 h1.page-header Features: - ul.nav.nav-tabs.nav-stacked.col-md-4.col-lg-4.col-sm-6(ng-repeat='thing in awesomeThings') + ul.nav.nav-tabs.nav-stacked.col-md-4.col-lg-4.col-sm-6(ng-repeat='thing in main.awesomeThings') li a(href='#', tooltip='{{thing.info}}') | {{thing.name}}<% if (filters.socketio) { %> - button.close(type='button', ng-click='deleteThing(thing)') ×<% } %><% if (filters.socketio) { %> + button.close(type='button', ng-click='main.deleteThing(thing)') ×<% } %><% if (filters.socketio) { %> form.thing-form label Syncs in realtime across clients p.input-group - input.form-control(type='text', placeholder='Add a new thing here.', ng-model='newThing') + input.form-control(type='text', placeholder='Add a new thing here.', ng-model='main.newThing') span.input-group-btn - button.btn.btn-primary(type='submit', ng-click='addThing()') Add New<% } %> + button.btn.btn-primary(type='submit', ng-click='main.addThing()') Add New<% } %> footer diff --git a/app/templates/client/app/main/main(js).js b/app/templates/client/app/main/main(js).js index 165181ffe..a22d74e4e 100644 --- a/app/templates/client/app/main/main(js).js +++ b/app/templates/client/app/main/main(js).js @@ -5,13 +5,15 @@ angular.module('<%= scriptAppName %>') $routeProvider .when('/', { templateUrl: 'app/main/main.html', - controller: 'MainCtrl' + controller: 'MainController', + conterollerAs: 'main' }); });<% } %><% if (filters.uirouter) { %>.config(function($stateProvider) { $stateProvider .state('main', { url: '/', templateUrl: 'app/main/main.html', - controller: 'MainCtrl' + controller: 'MainController', + conterollerAs: 'main' }); });<% } %> diff --git a/app/templates/client/app/main/main.controller(js).js b/app/templates/client/app/main/main.controller(js).js index 91ba5d131..35fd95951 100644 --- a/app/templates/client/app/main/main.controller(js).js +++ b/app/templates/client/app/main/main.controller(js).js @@ -1,27 +1,33 @@ 'use strict'; +(function() { -angular.module('<%= scriptAppName %>') - .controller('MainCtrl', function($scope, $http<% if (filters.socketio) { %>, socket<% } %>) { - $scope.awesomeThings = []; +function MainController($scope, $http<% if (filters.socketio) { %>, socket<% } %>) { + var self = this; + this.awesomeThings = []; - $http.get('/api/things').then(function(response) { - $scope.awesomeThings = response.data;<% if (filters.socketio) { %> - socket.syncUpdates('thing', $scope.awesomeThings);<% } %> - }); + $http.get('/api/things').then(function(response) { + self.awesomeThings = response.data;<% if (filters.socketio) { %> + socket.syncUpdates('thing', self.awesomeThings);<% } %> + }); <% if (filters.models) { %> - $scope.addThing = function() { - if ($scope.newThing === '') { - return; - } - $http.post('/api/things', { name: $scope.newThing }); - $scope.newThing = ''; - }; + this.addThing = function() { + if (self.newThing === '') { + return; + } + $http.post('/api/things', { name: self.newThing }); + self.newThing = ''; + }; - $scope.deleteThing = function(thing) { - $http.delete('/api/things/' + thing._id); - };<% } %><% if (filters.socketio) { %> + this.deleteThing = function(thing) { + $http.delete('/api/things/' + thing._id); + };<% } %><% if (filters.socketio) { %> - $scope.$on('$destroy', function() { - socket.unsyncUpdates('thing'); - });<% } %> - }); + $scope.$on('$destroy', function() { + socket.unsyncUpdates('thing'); + });<% } %> +} + +angular.module('<%= scriptAppName %>') + .controller('MainController', MainController); + +})(); diff --git a/app/templates/client/app/main/main.controller.spec(js).js b/app/templates/client/app/main/main.controller.spec(js).js index b8a652a79..42b1ea135 100644 --- a/app/templates/client/app/main/main.controller.spec(js).js +++ b/app/templates/client/app/main/main.controller.spec(js).js @@ -1,14 +1,14 @@ 'use strict'; -describe('Controller: MainCtrl', function() { +describe('Controller: MainController', function() { // load the controller's module beforeEach(module('<%= scriptAppName %>'));<% if (filters.uirouter) {%> beforeEach(module('stateMock'));<% } %><% if (filters.socketio) {%> beforeEach(module('socketMock'));<% } %> - var MainCtrl; - var scope;<% if (filters.uirouter) {%> + var scope; + var MainController;<% if (filters.uirouter) {%> var state;<% } %> var $httpBackend; @@ -20,14 +20,14 @@ describe('Controller: MainCtrl', function() { scope = $rootScope.$new();<% if (filters.uirouter) {%> state = $state;<% } %> - MainCtrl = $controller('MainCtrl', { + MainController = $controller('MainController', { $scope: scope }); })); - it('should attach a list of things to the scope', function() { + it('should attach a list of things to the controller', function() { $httpBackend.flush();<% if (filters.jasmine) { %> - expect(scope.awesomeThings.length).toBe(4);<% } if (filters.mocha) { %> - <%= expect() %>scope.awesomeThings.length<%= to() %>.equal(4);<% } %> + expect(MainController.awesomeThings.length).toBe(4);<% } if (filters.mocha) { %> + <%= expect() %>MainController.awesomeThings.length<%= to() %>.equal(4);<% } %> }); }); From 87774071f6bc148d75d3d8289a5face81bc0bda2 Mon Sep 17 00:00:00 2001 From: kingcody Date: Sat, 12 Sep 2015 17:22:31 -0400 Subject: [PATCH 0275/1357] fix(app): correct `controllerAs` property --- app/templates/client/app/main/main(js).js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/client/app/main/main(js).js b/app/templates/client/app/main/main(js).js index a22d74e4e..43206bce4 100644 --- a/app/templates/client/app/main/main(js).js +++ b/app/templates/client/app/main/main(js).js @@ -6,7 +6,7 @@ angular.module('<%= scriptAppName %>') .when('/', { templateUrl: 'app/main/main.html', controller: 'MainController', - conterollerAs: 'main' + controllerAs: 'main' }); });<% } %><% if (filters.uirouter) { %>.config(function($stateProvider) { $stateProvider @@ -14,6 +14,6 @@ angular.module('<%= scriptAppName %>') url: '/', templateUrl: 'app/main/main.html', controller: 'MainController', - conterollerAs: 'main' + controllerAs: 'main' }); });<% } %> From 68e5be20154793a64d30446bd2ff768950a0fa04 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 13 Sep 2015 01:56:33 -0400 Subject: [PATCH 0276/1357] docs(gen:README): fix paths for css in injection section Closes #645 --- readme.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/readme.md b/readme.md index e0e31f120..b63bc9562 100644 --- a/readme.md +++ b/readme.md @@ -59,9 +59,9 @@ Run `grunt` for building, `grunt serve` for preview, and `grunt serve:dist` for A grunt task looks for new files in your `client/app` and `client/components` folder and automatically injects them in the appropriate places based on an injection block. -* `less` files into `client/app.less` -* `scss` files into `client/app.scss` -* `stylus` files into `client/app.styl` +* `less` files into `client/app/app.less` +* `scss` files into `client/app/app.scss` +* `stylus` files into `client/app/app.styl` * `css` files into `client/index.html` * `js` files into `client/index.html` * `babel` temp `js` files into `client/index.html` From 23379553e114e446f6146db8e480461a178cfbfc Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 13 Sep 2015 16:53:01 -0400 Subject: [PATCH 0277/1357] fix(oauth-buttons): fix template name Fixes #1286 --- .../{oath-buttons(html).html => oauth-buttons(html).html} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/templates/client/components/oauth-buttons(oauth)/{oath-buttons(html).html => oauth-buttons(html).html} (100%) diff --git a/app/templates/client/components/oauth-buttons(oauth)/oath-buttons(html).html b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons(html).html similarity index 100% rename from app/templates/client/components/oauth-buttons(oauth)/oath-buttons(html).html rename to app/templates/client/components/oauth-buttons(oauth)/oauth-buttons(html).html From 33eea65bdfd816942c93bc9853de765221514483 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 13 Sep 2015 18:39:55 -0400 Subject: [PATCH 0278/1357] 3.0.0-rc8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7a6abd472..caad04a6b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "generator-angular-fullstack", - "version": "3.0.0-rc7-patch.0", + "version": "3.0.0-rc8", "description": "Yeoman generator for creating MEAN stack applications, using MongoDB, Express, AngularJS, and Node", "keywords": [ "yeoman-generator", From 3d67df25a9b39c98c52604f33c3c3153b8245ea5 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 13 Sep 2015 20:57:14 -0400 Subject: [PATCH 0279/1357] chore(npm): update sqlite3 to ~3.1.0 --- app/templates/_package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 01f57c1bd..771c37c95 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -21,7 +21,7 @@ "bluebird": "^2.9.34", "connect-mongo": "^0.8.1",<% } %><% if (filters.sequelize) { %> "sequelize": "^3.5.1", - "sqlite3": "~3.0.2", + "sqlite3": "~3.1.0", "express-sequelize-session": "0.4.0",<% } %><% if (filters.auth) { %> "jsonwebtoken": "^5.0.0", "express-jwt": "^3.0.0", From 0870e01bc7c2577a953ebca5c15d221a233a922d Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 13 Sep 2015 21:11:39 -0400 Subject: [PATCH 0280/1357] docs(README): add note about `grunt serve:debug` --- readme.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/readme.md b/readme.md index b63bc9562..aab821a0f 100644 --- a/readme.md +++ b/readme.md @@ -390,6 +390,10 @@ The coverage taget has 3 available options: * *when no option is given `test:coverage` runs all options in the above order* +**Debugging** + +Use `grunt serve:debug` for a more debugging-friendly environment. + ## Environment Variables Keeping your app secrets and other sensitive information in source control isn't a good idea. To have grunt launch your app with specific environment variables, add them to the git ignored environment config file: `server/config/local.env.js`. From 7b940dab5ddb5cf73ce3ed231e0867b57c947b0c Mon Sep 17 00:00:00 2001 From: kingcody Date: Sun, 13 Sep 2015 23:50:49 -0400 Subject: [PATCH 0281/1357] chore(app:grunt): improve grunt config template usage --- app/templates/Gruntfile.js | 47 +++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 1168d75b0..e98e6006a 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -265,9 +265,9 @@ module.exports = function (grunt) { filerev: { dist: { src: [ - '<%%= yeoman.dist %>/client/!(bower_components){,*/}*.{js,css}', - '<%%= yeoman.dist %>/client/assets/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}', - '<%%= yeoman.dist %>/client/assets/fonts/*' + '<%%= yeoman.dist %>/<%%= yeoman.client %>/!(bower_components){,*/}*.{js,css}', + '<%%= yeoman.dist %>/<%%= yeoman.client %>/assets/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}', + '<%%= yeoman.dist %>/<%%= yeoman.client %>/assets/fonts/*' ] } }, @@ -278,19 +278,19 @@ module.exports = function (grunt) { useminPrepare: { html: ['<%%= yeoman.client %>/index.html'], options: { - dest: '<%%= yeoman.dist %>/client' + dest: '<%%= yeoman.dist %>/<%%= yeoman.client %>' } }, // Performs rewrites based on rev and the useminPrepare configuration usemin: { - html: ['<%%= yeoman.dist %>/client/{,!(bower_components)/**/}*.html'], - css: ['<%%= yeoman.dist %>/client/!(bower_components){,*/}*.css'], - js: ['<%%= yeoman.dist %>/client/!(bower_components){,*/}*.js'], + html: ['<%%= yeoman.dist %>/<%%= yeoman.client %>/{,!(bower_components)/**/}*.html'], + css: ['<%%= yeoman.dist %>/<%%= yeoman.client %>/!(bower_components){,*/}*.css'], + js: ['<%%= yeoman.dist %>/<%%= yeoman.client %>/!(bower_components){,*/}*.js'], options: { assetsDirs: [ - '<%%= yeoman.dist %>/client', - '<%%= yeoman.dist %>/client/assets/images' + '<%%= yeoman.dist %>/<%%= yeoman.client %>', + '<%%= yeoman.dist %>/<%%= yeoman.client %>/assets/images' ], // This is so we update image references in our ng-templates patterns: { @@ -308,7 +308,7 @@ module.exports = function (grunt) { expand: true, cwd: '<%%= yeoman.client %>/assets/images', src: '{,*/}*.{png,jpg,jpeg,gif,svg}', - dest: '<%%= yeoman.dist %>/client/assets/images' + dest: '<%%= yeoman.dist %>/<%%= yeoman.client %>/assets/images' }] } }, @@ -357,7 +357,7 @@ module.exports = function (grunt) { // Replace Google CDN references cdnify: { dist: { - html: ['<%%= yeoman.dist %>/client/*.html'] + html: ['<%%= yeoman.dist %>/<%%= yeoman.client %>/*.html'] } }, @@ -368,7 +368,7 @@ module.exports = function (grunt) { expand: true, dot: true, cwd: '<%%= yeoman.client %>', - dest: '<%%= yeoman.dist %>/client', + dest: '<%%= yeoman.dist %>/<%%= yeoman.client %>', src: [ '*.{ico,png,txt}', '.htaccess', @@ -380,7 +380,7 @@ module.exports = function (grunt) { }, { expand: true, cwd: '.tmp/images', - dest: '<%%= yeoman.dist %>/client/assets/images', + dest: '<%%= yeoman.dist %>/<%%= yeoman.client %>/assets/images', src: ['generated/*'] }, { expand: true, @@ -623,7 +623,8 @@ module.exports = function (grunt) { scripts: { options: { transform: function(filePath) { - filePath = filePath.replace('/client/', ''); + var yoClient = grunt.config.get('yeoman.client'); + filePath = filePath.replace('/' + yoClient + '/', ''); filePath = filePath.replace('/.tmp/', ''); return ''; }, @@ -645,8 +646,9 @@ module.exports = function (grunt) { stylus: { options: { transform: function(filePath) { - filePath = filePath.replace('/client/app/', ''); - filePath = filePath.replace('/client/components/', '../components/'); + var yoClient = grunt.config.get('yeoman.client'); + filePath = filePath.replace('/' + yoClient + '/app/', ''); + filePath = filePath.replace('/' + yoClient + '/components/', '../components/'); return '@import \'' + filePath + '\';'; }, starttag: '// injector', @@ -664,8 +666,9 @@ module.exports = function (grunt) { sass: { options: { transform: function(filePath) { - filePath = filePath.replace('/client/app/', ''); - filePath = filePath.replace('/client/components/', '../components/'); + var yoClient = grunt.config.get('yeoman.client'); + filePath = filePath.replace('/' + yoClient + '/app/', ''); + filePath = filePath.replace('/' + yoClient + '/components/', '../components/'); return '@import \'' + filePath + '\';'; }, starttag: '// injector', @@ -683,8 +686,9 @@ module.exports = function (grunt) { less: { options: { transform: function(filePath) { - filePath = filePath.replace('/client/app/', ''); - filePath = filePath.replace('/client/components/', '../components/'); + var yoClient = grunt.config.get('yeoman.client'); + filePath = filePath.replace('/' + yoClient + '/app/', ''); + filePath = filePath.replace('/' + yoClient + '/components/', '../components/'); return '@import \'' + filePath + '\';'; }, starttag: '// injector', @@ -702,7 +706,8 @@ module.exports = function (grunt) { css: { options: { transform: function(filePath) { - filePath = filePath.replace('/client/', ''); + var yoClient = grunt.config.get('yeoman.client'); + filePath = filePath.replace('/' + yoClient + '/', ''); filePath = filePath.replace('/.tmp/', ''); return ''; }, From 109e45d68ccb0131d2fc5e7d2a88689914c134c5 Mon Sep 17 00:00:00 2001 From: kingcody Date: Mon, 14 Sep 2015 00:49:14 -0400 Subject: [PATCH 0282/1357] feat(app): dynamically generate angular constant `appConfig` --- app/generator.js | 1 + app/templates/Gruntfile.js | 64 ++++++++++++------- app/templates/_package.json | 1 + .../server/config/environment/index.js | 4 +- .../server/config/environment/shared.js | 6 ++ test/test-file-creation.js | 1 + 6 files changed, 52 insertions(+), 25 deletions(-) create mode 100644 app/templates/server/config/environment/shared.js diff --git a/app/generator.js b/app/generator.js index e0465a299..907df7234 100644 --- a/app/generator.js +++ b/app/generator.js @@ -371,6 +371,7 @@ export default class Generator extends Base { ngModules: function() { var angModules = [ + `'${this.scriptAppName}.constants'`, "'ngCookies'", "'ngResource'", "'ngSanitize'" diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index e98e6006a..1a8bd012f 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -17,7 +17,8 @@ module.exports = function (grunt) { cdnify: 'grunt-google-cdn', protractor: 'grunt-protractor-runner', buildcontrol: 'grunt-build-control', - istanbul_check_coverage: 'grunt-mocha-istanbul' + istanbul_check_coverage: 'grunt-mocha-istanbul', + ngconstant: 'grunt-ng-constant' }); // Time how long tasks take. Can help when optimizing build times @@ -60,6 +61,10 @@ module.exports = function (grunt) { files: ['<%%= yeoman.client %>/{app,components}/**/!(*.spec|*.mock).js'], tasks: ['newer:babel:client'] },<% } %> + ngconstant: { + files: ['<%%= yeoman.server %>/config/environment/shared.js'], + tasks: ['ngconstant'] + }, injectJS: { files: [ '<%%= yeoman.client %>/{app,components}/**/!(*.spec|*.mock).js', @@ -241,7 +246,7 @@ module.exports = function (grunt) { // Automatically inject Bower components into the app and karma.conf.js wiredep: { options: { - exclude: [ <% if(filters.uibootstrap) { %> + exclude: [<% if(filters.uibootstrap) { %> /bootstrap.js/,<% } %> '/json3/', '/es5-shim/'<% if(!filters.css) { %>, @@ -326,6 +331,25 @@ module.exports = function (grunt) { } }, + // Dynamically generate angular constant `appConfig` from + // `server/config/environment/shared.js` + ngconstant: { + options: { + name: '<%= scriptAppName %>.constants', + dest: '<%%= yeoman.client %>/app/app.constant.js', + deps: [], + wrap: true, + configPath: '<%%= yeoman.server %>/config/environment/shared' + }, + app: { + constants: function() { + return { + appConfig: require('./' + grunt.config.get('ngconstant.options.configPath')) + }; + } + } + }, + // Package all the html partials into a single javascript payload ngtemplates: { options: { @@ -423,6 +447,12 @@ module.exports = function (grunt) { // Run some tasks in parallel to speed up the build process concurrent: { + pre: [<% if (filters.stylus) { %> + 'injector:stylus',<% } if (filters.less) { %> + 'injector:less',<% } if (filters.sass) { %> + 'injector:sass',<% } %> + 'ngconstant' + ], server: [<% if(filters.babel) { %> 'newer:babel:client',<% } if(filters.jade) { %> 'jade',<% } if(filters.stylus) { %> @@ -747,10 +777,8 @@ module.exports = function (grunt) { if (target === 'debug') { return grunt.task.run([ 'clean:server', - 'env:all',<% if (filters.stylus) { %> - 'injector:stylus',<% } if (filters.less) { %> - 'injector:less',<% } if (filters.sass) { %> - 'injector:sass',<% } %> + 'env:all', + 'concurrent:pre', 'concurrent:server', 'injector', 'wiredep:client', @@ -761,10 +789,8 @@ module.exports = function (grunt) { grunt.task.run([ 'clean:server', - 'env:all',<% if (filters.stylus) { %> - 'injector:stylus',<% } if (filters.less) { %> - 'injector:less',<% } if (filters.sass) { %> - 'injector:sass',<% } %> + 'env:all', + 'concurrent:pre', 'concurrent:server', 'injector', 'wiredep:client', @@ -794,10 +820,8 @@ module.exports = function (grunt) { else if (target === 'client') { return grunt.task.run([ 'clean:server', - 'env:all',<% if (filters.stylus) { %> - 'injector:stylus',<% } if (filters.less) { %> - 'injector:less',<% } if (filters.sass) { %> - 'injector:sass',<% } %> + 'env:all', + 'concurrent:pre', 'concurrent:test', 'injector', 'postcss', @@ -822,10 +846,8 @@ module.exports = function (grunt) { return grunt.task.run([ 'clean:server', 'env:all', - 'env:test',<% if (filters.stylus) { %> - 'injector:stylus',<% } if (filters.less) { %> - 'injector:less',<% } if (filters.sass) { %> - 'injector:sass',<% } %> + 'env:test', + 'concurrent:pre', 'concurrent:test', 'injector', 'wiredep:client', @@ -878,10 +900,8 @@ module.exports = function (grunt) { }); grunt.registerTask('build', [ - 'clean:dist',<% if (filters.stylus) { %> - 'injector:stylus',<% } if (filters.less) { %> - 'injector:less',<% } if (filters.sass) { %> - 'injector:sass',<% } %> + 'clean:dist', + 'concurrent:pre', 'concurrent:dist', 'injector', 'wiredep:client', diff --git a/app/templates/_package.json b/app/templates/_package.json index 771c37c95..4d4b52a15 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -57,6 +57,7 @@ "grunt-jscs": "^2.0.0", "grunt-newer": "^1.1.1", "grunt-ng-annotate": "^1.0.1", + "grunt-ng-constant": "^1.1.0", "grunt-filerev": "^2.3.1", "grunt-usemin": "^3.0.0", "grunt-env": "~0.4.1", diff --git a/app/templates/server/config/environment/index.js b/app/templates/server/config/environment/index.js index 98c892d32..c6115a06d 100644 --- a/app/templates/server/config/environment/index.js +++ b/app/templates/server/config/environment/index.js @@ -32,9 +32,6 @@ var all = { session: '<%= lodash.slugify(lodash.humanize(appname)) + '-secret' %>' }, - // List of user roles - userRoles: ['guest', 'user', 'admin'], - // MongoDB connection options mongo: { options: { @@ -67,4 +64,5 @@ var all = { // ============================================== module.exports = _.merge( all, + require('./shared'), require('./' + process.env.NODE_ENV + '.js') || {}); diff --git a/app/templates/server/config/environment/shared.js b/app/templates/server/config/environment/shared.js new file mode 100644 index 000000000..64a5eab99 --- /dev/null +++ b/app/templates/server/config/environment/shared.js @@ -0,0 +1,6 @@ +'use strict'; + +exports = module.exports = { + // List of user roles + userRoles: ['guest', 'user', 'admin'] +}; diff --git a/test/test-file-creation.js b/test/test-file-creation.js index bfcfebe5a..dda6bfbd1 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -199,6 +199,7 @@ describe('angular-fullstack generator', function () { 'server/config/environment/development.js', 'server/config/environment/production.js', 'server/config/environment/test.js', + 'server/config/environment/shared.js', 'server/views/404.' + markup, 'e2e/main/main.po.js', 'e2e/main/main.spec.js', From 6147e764613e5744084bd2282287452e2ba9d231 Mon Sep 17 00:00:00 2001 From: kingcody Date: Mon, 14 Sep 2015 03:49:01 -0400 Subject: [PATCH 0283/1357] refactor(client:auth): use named function, create Auth reference --- .../client/app/main/main.controller(js).js | 57 ++++++++++--------- .../components/auth(auth)/auth.service(js).js | 28 +++++---- 2 files changed, 47 insertions(+), 38 deletions(-) diff --git a/app/templates/client/app/main/main.controller(js).js b/app/templates/client/app/main/main.controller(js).js index 35fd95951..bfbed15ec 100644 --- a/app/templates/client/app/main/main.controller(js).js +++ b/app/templates/client/app/main/main.controller(js).js @@ -1,33 +1,34 @@ 'use strict'; + (function() { -function MainController($scope, $http<% if (filters.socketio) { %>, socket<% } %>) { - var self = this; - this.awesomeThings = []; - - $http.get('/api/things').then(function(response) { - self.awesomeThings = response.data;<% if (filters.socketio) { %> - socket.syncUpdates('thing', self.awesomeThings);<% } %> - }); -<% if (filters.models) { %> - this.addThing = function() { - if (self.newThing === '') { - return; - } - $http.post('/api/things', { name: self.newThing }); - self.newThing = ''; - }; - - this.deleteThing = function(thing) { - $http.delete('/api/things/' + thing._id); - };<% } %><% if (filters.socketio) { %> - - $scope.$on('$destroy', function() { - socket.unsyncUpdates('thing'); - });<% } %> -} - -angular.module('<%= scriptAppName %>') - .controller('MainController', MainController); + function MainController($scope, $http<% if (filters.socketio) { %>, socket<% } %>) { + var self = this; + this.awesomeThings = []; + + $http.get('/api/things').then(function(response) { + self.awesomeThings = response.data;<% if (filters.socketio) { %> + socket.syncUpdates('thing', self.awesomeThings);<% } %> + });<% if (filters.models) { %> + + this.addThing = function() { + if (self.newThing === '') { + return; + } + $http.post('/api/things', { name: self.newThing }); + self.newThing = ''; + }; + + this.deleteThing = function(thing) { + $http.delete('/api/things/' + thing._id); + };<% } if (filters.socketio) { %> + + $scope.$on('$destroy', function() { + socket.unsyncUpdates('thing'); + });<% } %> + } + + angular.module('<%= scriptAppName %>') + .controller('MainController', MainController); })(); diff --git a/app/templates/client/components/auth(auth)/auth.service(js).js b/app/templates/client/components/auth(auth)/auth.service(js).js index 2a1fcb480..eb687a564 100644 --- a/app/templates/client/components/auth(auth)/auth.service(js).js +++ b/app/templates/client/components/auth(auth)/auth.service(js).js @@ -1,7 +1,8 @@ 'use strict'; -angular.module('<%= scriptAppName %>') - .factory('Auth', function Auth($http, User, $cookies, $q) { +(function() { + + function AuthService($http, User, $cookies, $q) { /** * Return a callback or noop function * @@ -18,7 +19,7 @@ angular.module('<%= scriptAppName %>') currentUser = User.get(); } - return { + var Auth = { /** * Authenticate user and save token @@ -42,10 +43,10 @@ angular.module('<%= scriptAppName %>') return user; }) .catch(function(err) { - this.logout(); + Auth.logout(); safeCb(callback)(err.data); return $q.reject(err.data); - }.bind(this)); + }); }, /** @@ -71,9 +72,9 @@ angular.module('<%= scriptAppName %>') return safeCb(callback)(null, user); }, function(err) { - this.logout(); + Auth.logout(); return safeCb(callback)(err); - }.bind(this)).$promise; + }).$promise; }, /** @@ -130,7 +131,7 @@ angular.module('<%= scriptAppName %>') return currentUser.hasOwnProperty('role'); } - return this.getCurrentUser(null) + return Auth.getCurrentUser(null) .then(function(user) { var is = user.hasOwnProperty('role'); safeCb(callback)(is); @@ -150,7 +151,7 @@ angular.module('<%= scriptAppName %>') return currentUser.role === 'admin'; } - return this.getCurrentUser(null) + return Auth.getCurrentUser(null) .then(function(user) { var is = user.role === 'admin'; safeCb(callback)(is); @@ -167,4 +168,11 @@ angular.module('<%= scriptAppName %>') return $cookies.get('token'); } }; - }); + + return Auth; + } + + angular.module('<%= scriptAppName %>') + .factory('Auth', AuthService); + +})(); From 9133296a3f5d04aa5c8a7f5b8f69a587c30ff589 Mon Sep 17 00:00:00 2001 From: kingcody Date: Mon, 14 Sep 2015 06:46:10 -0400 Subject: [PATCH 0284/1357] feat(injector): inject module definitions first --- app/templates/Gruntfile.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 1a8bd012f..cc3d414e0 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -658,6 +658,13 @@ module.exports = function (grunt) { filePath = filePath.replace('/.tmp/', ''); return ''; }, + sort: function(a, b) { + var module = /\.module\.js$/; + var aMod = module.test(a); + var bMod = module.test(b); + // inject *.module.js first + return (aMod === bMod) ? 0 : (aMod ? -1 : 1); + }, starttag: '', endtag: '' }, From d3d0f569d912f14e7d5b33269fdaca13472132df Mon Sep 17 00:00:00 2001 From: kingcody Date: Mon, 14 Sep 2015 06:54:58 -0400 Subject: [PATCH 0285/1357] feat(client:auth): implement auth components as a seperate module --- app/generator.js | 5 ++++- .../client/components/auth(auth)/auth.module(js).js | 5 +++++ .../client/components/auth(auth)/auth.service(js).js | 2 +- .../client/components/auth(auth)/user.service(js).js | 2 +- test/test-file-creation.js | 1 + 5 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 app/templates/client/components/auth(auth)/auth.module(js).js diff --git a/app/generator.js b/app/generator.js index 907df7234..00fad1ad5 100644 --- a/app/generator.js +++ b/app/generator.js @@ -380,7 +380,10 @@ export default class Generator extends Base { if(this.filters.socketio) angModules.push("'btford.socket-io'"); if(this.filters.uirouter) angModules.push("'ui.router'"); if(this.filters.uibootstrap) angModules.push("'ui.bootstrap'"); - if(this.filters.auth) angModules.push("'validation.match'"); + if(this.filters.auth) { + angModules.unshift(`'${this.scriptAppName}.auth'`); + angModules.push("'validation.match'"); + } this.angularModules = '\n ' + angModules.join(',\n ') +'\n'; } diff --git a/app/templates/client/components/auth(auth)/auth.module(js).js b/app/templates/client/components/auth(auth)/auth.module(js).js new file mode 100644 index 000000000..26a4bff0e --- /dev/null +++ b/app/templates/client/components/auth(auth)/auth.module(js).js @@ -0,0 +1,5 @@ +'use strict'; + +angular.module('<%= scriptAppName %>.auth', [ + 'ngCookies' +]); diff --git a/app/templates/client/components/auth(auth)/auth.service(js).js b/app/templates/client/components/auth(auth)/auth.service(js).js index eb687a564..6477075ff 100644 --- a/app/templates/client/components/auth(auth)/auth.service(js).js +++ b/app/templates/client/components/auth(auth)/auth.service(js).js @@ -172,7 +172,7 @@ return Auth; } - angular.module('<%= scriptAppName %>') + angular.module('<%= scriptAppName %>.auth') .factory('Auth', AuthService); })(); diff --git a/app/templates/client/components/auth(auth)/user.service(js).js b/app/templates/client/components/auth(auth)/user.service(js).js index aad887945..c0bf13513 100644 --- a/app/templates/client/components/auth(auth)/user.service(js).js +++ b/app/templates/client/components/auth(auth)/user.service(js).js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('<%= scriptAppName %>') +angular.module('<%= scriptAppName %>.auth') .factory('User', function ($resource) { return $resource('/api/users/:id/:controller', { id: '@_id' diff --git a/test/test-file-creation.js b/test/test-file-creation.js index dda6bfbd1..f89dd0b9f 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -267,6 +267,7 @@ describe('angular-fullstack generator', function () { 'client/app/admin/admin.' + stylesheet, 'client/app/admin/admin.' + script, 'client/app/admin/admin.controller.' + script, + 'client/components/auth/auth.module.' + script, 'client/components/auth/auth.service.' + script, 'client/components/auth/user.service.' + script, 'client/components/mongoose-error/mongoose-error.directive.' + script, From f350412cf66daf23a610d32dcafcf30545b7b168 Mon Sep 17 00:00:00 2001 From: kingcody Date: Mon, 14 Sep 2015 07:27:20 -0400 Subject: [PATCH 0286/1357] refactor(client:auth): move authInterceptor to auth module --- app/templates/client/app/app(js).js | 42 +++---------------- .../components/auth(auth)/auth.module(js).js | 9 +++- .../auth(auth)/interceptor.service(js).js | 35 ++++++++++++++++ test/test-file-creation.js | 1 + 4 files changed, 48 insertions(+), 39 deletions(-) create mode 100644 app/templates/client/components/auth(auth)/interceptor.service(js).js diff --git a/app/templates/client/app/app(js).js b/app/templates/client/app/app(js).js index 0c8ec39e8..d10f0808f 100644 --- a/app/templates/client/app/app(js).js +++ b/app/templates/client/app/app(js).js @@ -1,48 +1,16 @@ 'use strict'; angular.module('<%= scriptAppName %>', [<%- angularModules %>]) - <% if (filters.ngroute) { %>.config(function($routeProvider, $locationProvider<% if (filters.auth) { %>, $httpProvider<% } %>) { + .config(function(<% if (filters.ngroute) { %>$routeProvider<% } if (filters.uirouter) { %>$urlRouterProvider<% } %>, $locationProvider) {<% if (filters.ngroute) { %> $routeProvider .otherwise({ redirectTo: '/' - }); - - $locationProvider.html5Mode(true);<% if (filters.auth) { %> - $httpProvider.interceptors.push('authInterceptor');<% } %> - })<% } if (filters.uirouter) { %>.config(function($stateProvider, $urlRouterProvider, $locationProvider<% if (filters.auth) { %>, $httpProvider<% } %>) { + });<% } if (filters.uirouter) { %> $urlRouterProvider - .otherwise('/'); - - $locationProvider.html5Mode(true);<% if (filters.auth) { %> - $httpProvider.interceptors.push('authInterceptor');<% } %> - })<% } if (filters.auth) { %> + .otherwise('/');<% } %> - .factory('authInterceptor', function($rootScope, $q, $cookies<% if (filters.ngroute) { %>, $location<% } if (filters.uirouter) { %>, $injector<% } %>) { - <% if (filters.uirouter) { %>var state; - <% } %>return { - // Add authorization token to headers - request: function(config) { - config.headers = config.headers || {}; - if ($cookies.get('token')) { - config.headers.Authorization = 'Bearer ' + $cookies.get('token'); - } - return config; - }, - - // Intercept 401s and redirect you to login - responseError: function(response) { - if (response.status === 401) { - <% if (filters.ngroute) { %>$location.path('/login');<% } if (filters.uirouter) { %>(state || (state = $injector.get('$state'))).go('login');<% } %> - // remove any stale tokens - $cookies.remove('token'); - return $q.reject(response); - } - else { - return $q.reject(response); - } - } - }; - }) + $locationProvider.html5Mode(true); + })<% if (filters.auth) { %> .run(function($rootScope<% if (filters.ngroute) { %>, $location<% } if (filters.uirouter) { %>, $state<% } %>, Auth) { // Redirect to login if route requires auth and the user is not logged in diff --git a/app/templates/client/components/auth(auth)/auth.module(js).js b/app/templates/client/components/auth(auth)/auth.module(js).js index 26a4bff0e..dcb4ff7f3 100644 --- a/app/templates/client/components/auth(auth)/auth.module(js).js +++ b/app/templates/client/components/auth(auth)/auth.module(js).js @@ -1,5 +1,10 @@ 'use strict'; angular.module('<%= scriptAppName %>.auth', [ - 'ngCookies' -]); + 'ngCookies'<% if (filters.ngroute) { %>, + 'ngRoute'<% } if (filters.uirouter) { %>, + 'ui.router'<% } %> +]) + .config(function($httpProvider) { + $httpProvider.interceptors.push('authInterceptor'); + }); diff --git a/app/templates/client/components/auth(auth)/interceptor.service(js).js b/app/templates/client/components/auth(auth)/interceptor.service(js).js new file mode 100644 index 000000000..8843527b9 --- /dev/null +++ b/app/templates/client/components/auth(auth)/interceptor.service(js).js @@ -0,0 +1,35 @@ +'use strict'; + +(function() { + + function authInterceptor($rootScope, $q, $cookies<% if (filters.ngroute) { %>, $location<% } if (filters.uirouter) { %>, $injector<% } %>) { + <% if (filters.uirouter) { %>var state; + <% } %>return { + // Add authorization token to headers + request: function(config) { + config.headers = config.headers || {}; + if ($cookies.get('token')) { + config.headers.Authorization = 'Bearer ' + $cookies.get('token'); + } + return config; + }, + + // Intercept 401s and redirect you to login + responseError: function(response) { + if (response.status === 401) { + <% if (filters.ngroute) { %>$location.path('/login');<% } if (filters.uirouter) { %>(state || (state = $injector.get('$state'))).go('login');<% } %> + // remove any stale tokens + $cookies.remove('token'); + return $q.reject(response); + } + else { + return $q.reject(response); + } + } + }; + } + + angular.module('<%= scriptAppName %>.auth') + .factory('authInterceptor', authInterceptor); + +})(); diff --git a/test/test-file-creation.js b/test/test-file-creation.js index f89dd0b9f..26d47f8b2 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -269,6 +269,7 @@ describe('angular-fullstack generator', function () { 'client/app/admin/admin.controller.' + script, 'client/components/auth/auth.module.' + script, 'client/components/auth/auth.service.' + script, + 'client/components/auth/interceptor.service.' + script, 'client/components/auth/user.service.' + script, 'client/components/mongoose-error/mongoose-error.directive.' + script, 'server/api/user/index.js', From 533f20e663592b3f4b8911eb914c82ab7c8d5d54 Mon Sep 17 00:00:00 2001 From: kingcody Date: Mon, 14 Sep 2015 22:49:14 -0400 Subject: [PATCH 0287/1357] feat(client:auth): implement `Auth.hasRole` --- .../components/auth(auth)/auth.module(js).js | 1 + .../components/auth(auth)/auth.service(js).js | 42 ++++++++++++++----- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/app/templates/client/components/auth(auth)/auth.module(js).js b/app/templates/client/components/auth(auth)/auth.module(js).js index dcb4ff7f3..3e096aeb3 100644 --- a/app/templates/client/components/auth(auth)/auth.module(js).js +++ b/app/templates/client/components/auth(auth)/auth.module(js).js @@ -1,6 +1,7 @@ 'use strict'; angular.module('<%= scriptAppName %>.auth', [ + '<%= scriptAppName %>.constants', 'ngCookies'<% if (filters.ngroute) { %>, 'ngRoute'<% } if (filters.uirouter) { %>, 'ui.router'<% } %> diff --git a/app/templates/client/components/auth(auth)/auth.service(js).js b/app/templates/client/components/auth(auth)/auth.service(js).js index 6477075ff..0b771500a 100644 --- a/app/templates/client/components/auth(auth)/auth.service(js).js +++ b/app/templates/client/components/auth(auth)/auth.service(js).js @@ -2,7 +2,7 @@ (function() { - function AuthService($http, User, $cookies, $q) { + function AuthService($http, $cookies, $q, appConfig, User) { /** * Return a callback or noop function * @@ -13,7 +13,8 @@ return (angular.isFunction(cb)) ? cb : angular.noop; }, - currentUser = {}; + currentUser = {}, + userRoles = appConfig.userRoles || []; if ($cookies.get('token')) { currentUser = User.get(); @@ -108,7 +109,8 @@ return currentUser; } - var value = (currentUser.hasOwnProperty('$promise')) ? currentUser.$promise : currentUser; + var value = (currentUser.hasOwnProperty('$promise')) ? + currentUser.$promise : currentUser; return $q.when(value) .then(function(user) { safeCb(callback)(user); @@ -140,25 +142,43 @@ }, /** - * Check if a user is an admin + * Check if a user has a specified role or higher * (synchronous|asynchronous) * - * @param {Function|*} callback - optional, function(is) + * @param {String} role - the role to check against + * @param {Function|*} callback - optional, function(has) * @return {Bool|Promise} */ - isAdmin: function(callback) { - if (arguments.length === 0) { - return currentUser.role === 'admin'; + hasRole: function(role, callback) { + var hasRole = function(r, h) { + return userRoles.indexOf(r) >= userRoles.indexOf(h); + }; + + if (arguments.length < 2) { + return hasRole(currentUser.role, role); } return Auth.getCurrentUser(null) .then(function(user) { - var is = user.role === 'admin'; - safeCb(callback)(is); - return is; + var has = (user.hasOwnProperty('role')) ? + hasRole(user.role, role) : false; + safeCb(callback)(has); + return has; }); }, + /** + * Check if a user is an admin + * (synchronous|asynchronous) + * + * @param {Function|*} callback - optional, function(is) + * @return {Bool|Promise} + */ + isAdmin: function() { + return Auth.hasRole + .apply(Auth, [].concat.apply(['admin'], arguments)); + }, + /** * Get auth token * From f222cfb7c3cca098cf40e3cc7f64655858ca1799 Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 15 Sep 2015 00:14:05 -0400 Subject: [PATCH 0288/1357] feat(client:auth): implement router auth via router.decorator Changes: * move remaining auth code from app.js to auth module * the router param `authenticate` now accepts a string as a role requirement * admin route now uses role based auth --- .../client/app/admin(auth)/admin(js).js | 6 ++- app/templates/client/app/app(js).js | 16 +------- .../auth(auth)/router.decorator(js).js | 41 +++++++++++++++++++ test/test-file-creation.js | 1 + 4 files changed, 47 insertions(+), 17 deletions(-) create mode 100644 app/templates/client/components/auth(auth)/router.decorator(js).js diff --git a/app/templates/client/app/admin(auth)/admin(js).js b/app/templates/client/app/admin(auth)/admin(js).js index f37ba9fcc..510363868 100644 --- a/app/templates/client/app/admin(auth)/admin(js).js +++ b/app/templates/client/app/admin(auth)/admin(js).js @@ -5,13 +5,15 @@ angular.module('<%= scriptAppName %>') $routeProvider .when('/admin', { templateUrl: 'app/admin/admin.html', - controller: 'AdminCtrl' + controller: 'AdminCtrl', + authenticate: 'admin' }); });<% } %><% if (filters.uirouter) { %>.config(function($stateProvider) { $stateProvider .state('admin', { url: '/admin', templateUrl: 'app/admin/admin.html', - controller: 'AdminCtrl' + controller: 'AdminCtrl', + authenticate: 'admin' }); });<% } %> diff --git a/app/templates/client/app/app(js).js b/app/templates/client/app/app(js).js index d10f0808f..a9d9f2b09 100644 --- a/app/templates/client/app/app(js).js +++ b/app/templates/client/app/app(js).js @@ -10,18 +10,4 @@ angular.module('<%= scriptAppName %>', [<%- angularModules %>]) .otherwise('/');<% } %> $locationProvider.html5Mode(true); - })<% if (filters.auth) { %> - - .run(function($rootScope<% if (filters.ngroute) { %>, $location<% } if (filters.uirouter) { %>, $state<% } %>, Auth) { - // Redirect to login if route requires auth and the user is not logged in - $rootScope.$on(<% if (filters.ngroute) { %>'$routeChangeStart'<% } %><% if (filters.uirouter) { %>'$stateChangeStart'<% } %>, function(event, next) { - if (next.authenticate) { - Auth.isLoggedIn(function(loggedIn) { - if (!loggedIn) { - event.preventDefault(); - <% if (filters.ngroute) { %>$location.path('/login');<% } if (filters.uirouter) { %>$state.go('login');<% } %> - } - }); - } - }); - })<% } %>; + }); diff --git a/app/templates/client/components/auth(auth)/router.decorator(js).js b/app/templates/client/components/auth(auth)/router.decorator(js).js new file mode 100644 index 000000000..edd71d95e --- /dev/null +++ b/app/templates/client/components/auth(auth)/router.decorator(js).js @@ -0,0 +1,41 @@ +'use strict'; + +(function() { + + function routerDecorator(<%= filters.uirouter ? '$stateProvider' : '$provide' %>) { + var authDecorator = function(<%= filters.uirouter ? 'state' : 'route' %>) { + var auth = <%= filters.uirouter ? 'state' : 'route' %>.authenticate; + if (auth) { + <%= filters.uirouter ? 'state' : 'route' %>.resolve = <%= filters.uirouter ? 'state' : 'route' %>.resolve || {}; + <%= filters.uirouter ? 'state' : 'route' %>.resolve.user = function(<%= filters.uirouter ? '$state' : '$location' %>, $q, Auth) { + return Auth.getCurrentUser(true) + .then(function(user) { + if ((typeof auth !== 'string' && user._id) || + (typeof auth === 'string' && Auth.hasRole(auth))) { + return user; + }<% if (filters.ngroute) { %> + $location.path((user._id) ? '/' : '/login');<% } if (filters.uirouter) { %> + $state.go((user._id) ? 'main' : 'login');<% } %> + return $q.reject('not authorized'); + }); + }; + } + };<% if (filters.ngroute) { %> + + $provide.decorator('$route', function($delegate) { + for (var r in $delegate.routes) { + authDecorator($delegate.routes[r]); + } + return $delegate; + });<% } if (filters.uirouter) { %> + + $stateProvider.decorator('authenticate', function(state) { + authDecorator(state); + return state.authenticate; + });<% } %> + } + + angular.module('<%= scriptAppName %>.auth') + .config(routerDecorator); + +})(); diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 26d47f8b2..ae1dc0297 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -270,6 +270,7 @@ describe('angular-fullstack generator', function () { 'client/components/auth/auth.module.' + script, 'client/components/auth/auth.service.' + script, 'client/components/auth/interceptor.service.' + script, + 'client/components/auth/router.decorator.' + script, 'client/components/auth/user.service.' + script, 'client/components/mongoose-error/mongoose-error.directive.' + script, 'server/api/user/index.js', From cf38d627130f9bc9942767a099222476397d42c8 Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 15 Sep 2015 00:20:44 -0400 Subject: [PATCH 0289/1357] refactor(client:auth): use named function for user resource --- .../client/components/auth(auth)/user.service(js).js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/app/templates/client/components/auth(auth)/user.service(js).js b/app/templates/client/components/auth(auth)/user.service(js).js index c0bf13513..965f84566 100644 --- a/app/templates/client/components/auth(auth)/user.service(js).js +++ b/app/templates/client/components/auth(auth)/user.service(js).js @@ -1,7 +1,8 @@ 'use strict'; -angular.module('<%= scriptAppName %>.auth') - .factory('User', function ($resource) { +(function() { + + function UserResource($resource) { return $resource('/api/users/:id/:controller', { id: '@_id' }, @@ -19,4 +20,9 @@ angular.module('<%= scriptAppName %>.auth') } } }); - }); + } + + angular.module('<%= scriptAppName %>.auth') + .factory('User', UserResource); + +})(); From dafd65aee6fd919181da7fc629b9840a83c74cda Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 15 Sep 2015 01:32:01 -0400 Subject: [PATCH 0290/1357] fix(client:auth): exclued user fetching for logout route --- .../client/components/auth(auth)/auth.service(js).js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/client/components/auth(auth)/auth.service(js).js b/app/templates/client/components/auth(auth)/auth.service(js).js index 0b771500a..0310e1198 100644 --- a/app/templates/client/components/auth(auth)/auth.service(js).js +++ b/app/templates/client/components/auth(auth)/auth.service(js).js @@ -2,7 +2,7 @@ (function() { - function AuthService($http, $cookies, $q, appConfig, User) { + function AuthService($location, $http, $cookies, $q, appConfig, User) { /** * Return a callback or noop function * @@ -16,7 +16,7 @@ currentUser = {}, userRoles = appConfig.userRoles || []; - if ($cookies.get('token')) { + if ($cookies.get('token') && $location.path() !== '/logout') { currentUser = User.get(); } From 650a5295c44dcf0935872f599b302700a88f7dc6 Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 15 Sep 2015 19:50:10 -0400 Subject: [PATCH 0291/1357] style(app): flatten IIFEs --- .../client/app/main/main.controller(js).js | 56 +-- .../components/auth(auth)/auth.service(js).js | 358 +++++++++--------- .../auth(auth)/interceptor.service(js).js | 52 +-- .../auth(auth)/router.decorator(js).js | 64 ++-- .../components/auth(auth)/user.service(js).js | 38 +- 5 files changed, 284 insertions(+), 284 deletions(-) diff --git a/app/templates/client/app/main/main.controller(js).js b/app/templates/client/app/main/main.controller(js).js index bfbed15ec..db9bbd5c3 100644 --- a/app/templates/client/app/main/main.controller(js).js +++ b/app/templates/client/app/main/main.controller(js).js @@ -2,33 +2,33 @@ (function() { - function MainController($scope, $http<% if (filters.socketio) { %>, socket<% } %>) { - var self = this; - this.awesomeThings = []; - - $http.get('/api/things').then(function(response) { - self.awesomeThings = response.data;<% if (filters.socketio) { %> - socket.syncUpdates('thing', self.awesomeThings);<% } %> - });<% if (filters.models) { %> - - this.addThing = function() { - if (self.newThing === '') { - return; - } - $http.post('/api/things', { name: self.newThing }); - self.newThing = ''; - }; - - this.deleteThing = function(thing) { - $http.delete('/api/things/' + thing._id); - };<% } if (filters.socketio) { %> - - $scope.$on('$destroy', function() { - socket.unsyncUpdates('thing'); - });<% } %> - } - - angular.module('<%= scriptAppName %>') - .controller('MainController', MainController); +function MainController($scope, $http<% if (filters.socketio) { %>, socket<% } %>) { + var self = this; + this.awesomeThings = []; + + $http.get('/api/things').then(function(response) { + self.awesomeThings = response.data;<% if (filters.socketio) { %> + socket.syncUpdates('thing', self.awesomeThings);<% } %> + });<% if (filters.models) { %> + + this.addThing = function() { + if (self.newThing === '') { + return; + } + $http.post('/api/things', { name: self.newThing }); + self.newThing = ''; + }; + + this.deleteThing = function(thing) { + $http.delete('/api/things/' + thing._id); + };<% } if (filters.socketio) { %> + + $scope.$on('$destroy', function() { + socket.unsyncUpdates('thing'); + });<% } %> +} + +angular.module('<%= scriptAppName %>') + .controller('MainController', MainController); })(); diff --git a/app/templates/client/components/auth(auth)/auth.service(js).js b/app/templates/client/components/auth(auth)/auth.service(js).js index 0310e1198..49bdb2a9e 100644 --- a/app/templates/client/components/auth(auth)/auth.service(js).js +++ b/app/templates/client/components/auth(auth)/auth.service(js).js @@ -2,197 +2,197 @@ (function() { - function AuthService($location, $http, $cookies, $q, appConfig, User) { +function AuthService($location, $http, $cookies, $q, appConfig, User) { + /** + * Return a callback or noop function + * + * @param {Function|*} cb - a 'potential' function + * @return {Function} + */ + var safeCb = function(cb) { + return (angular.isFunction(cb)) ? cb : angular.noop; + }, + + currentUser = {}, + userRoles = appConfig.userRoles || []; + + if ($cookies.get('token') && $location.path() !== '/logout') { + currentUser = User.get(); + } + + var Auth = { + /** - * Return a callback or noop function + * Authenticate user and save token * - * @param {Function|*} cb - a 'potential' function - * @return {Function} + * @param {Object} user - login info + * @param {Function} callback - optional, function(error, user) + * @return {Promise} */ - var safeCb = function(cb) { - return (angular.isFunction(cb)) ? cb : angular.noop; + login: function(user, callback) { + return $http.post('/auth/local', { + email: user.email, + password: user.password + }) + .then(function(res) { + $cookies.put('token', res.data.token); + currentUser = User.get(); + return currentUser.$promise; + }) + .then(function(user) { + safeCb(callback)(null, user); + return user; + }) + .catch(function(err) { + Auth.logout(); + safeCb(callback)(err.data); + return $q.reject(err.data); + }); }, - currentUser = {}, - userRoles = appConfig.userRoles || []; - - if ($cookies.get('token') && $location.path() !== '/logout') { - currentUser = User.get(); - } + /** + * Delete access token and user info + */ + logout: function() { + $cookies.remove('token'); + currentUser = {}; + }, - var Auth = { - - /** - * Authenticate user and save token - * - * @param {Object} user - login info - * @param {Function} callback - optional, function(error, user) - * @return {Promise} - */ - login: function(user, callback) { - return $http.post('/auth/local', { - email: user.email, - password: user.password - }) - .then(function(res) { - $cookies.put('token', res.data.token); + /** + * Create a new user + * + * @param {Object} user - user info + * @param {Function} callback - optional, function(error, user) + * @return {Promise} + */ + createUser: function(user, callback) { + return User.save(user, + function(data) { + $cookies.put('token', data.token); currentUser = User.get(); - return currentUser.$promise; - }) - .then(function(user) { - safeCb(callback)(null, user); - return user; - }) - .catch(function(err) { + return safeCb(callback)(null, user); + }, + function(err) { Auth.logout(); - safeCb(callback)(err.data); - return $q.reject(err.data); - }); - }, - - /** - * Delete access token and user info - */ - logout: function() { - $cookies.remove('token'); - currentUser = {}; - }, - - /** - * Create a new user - * - * @param {Object} user - user info - * @param {Function} callback - optional, function(error, user) - * @return {Promise} - */ - createUser: function(user, callback) { - return User.save(user, - function(data) { - $cookies.put('token', data.token); - currentUser = User.get(); - return safeCb(callback)(null, user); - }, - function(err) { - Auth.logout(); - return safeCb(callback)(err); - }).$promise; - }, - - /** - * Change password - * - * @param {String} oldPassword - * @param {String} newPassword - * @param {Function} callback - optional, function(error, user) - * @return {Promise} - */ - changePassword: function(oldPassword, newPassword, callback) { - return User.changePassword({ id: currentUser._id }, { - oldPassword: oldPassword, - newPassword: newPassword - }, function() { - return safeCb(callback)(null); - }, function(err) { return safeCb(callback)(err); }).$promise; - }, - - /** - * Gets all available info on a user - * (synchronous|asynchronous) - * - * @param {Function|*} callback - optional, funciton(user) - * @return {Object|Promise} - */ - getCurrentUser: function(callback) { - if (arguments.length === 0) { - return currentUser; - } - - var value = (currentUser.hasOwnProperty('$promise')) ? - currentUser.$promise : currentUser; - return $q.when(value) - .then(function(user) { - safeCb(callback)(user); - return user; - }, function() { - safeCb(callback)({}); - return {}; - }); - }, - - /** - * Check if a user is logged in - * (synchronous|asynchronous) - * - * @param {Function|*} callback - optional, function(is) - * @return {Bool|Promise} - */ - isLoggedIn: function(callback) { - if (arguments.length === 0) { - return currentUser.hasOwnProperty('role'); - } - - return Auth.getCurrentUser(null) - .then(function(user) { - var is = user.hasOwnProperty('role'); - safeCb(callback)(is); - return is; - }); - }, - - /** - * Check if a user has a specified role or higher - * (synchronous|asynchronous) - * - * @param {String} role - the role to check against - * @param {Function|*} callback - optional, function(has) - * @return {Bool|Promise} - */ - hasRole: function(role, callback) { - var hasRole = function(r, h) { - return userRoles.indexOf(r) >= userRoles.indexOf(h); - }; - - if (arguments.length < 2) { - return hasRole(currentUser.role, role); - } - - return Auth.getCurrentUser(null) - .then(function(user) { - var has = (user.hasOwnProperty('role')) ? - hasRole(user.role, role) : false; - safeCb(callback)(has); - return has; - }); - }, - - /** - * Check if a user is an admin - * (synchronous|asynchronous) - * - * @param {Function|*} callback - optional, function(is) - * @return {Bool|Promise} - */ - isAdmin: function() { - return Auth.hasRole - .apply(Auth, [].concat.apply(['admin'], arguments)); - }, - - /** - * Get auth token - * - * @return {String} - a token string used for authenticating - */ - getToken: function() { - return $cookies.get('token'); + }, + + /** + * Change password + * + * @param {String} oldPassword + * @param {String} newPassword + * @param {Function} callback - optional, function(error, user) + * @return {Promise} + */ + changePassword: function(oldPassword, newPassword, callback) { + return User.changePassword({ id: currentUser._id }, { + oldPassword: oldPassword, + newPassword: newPassword + }, function() { + return safeCb(callback)(null); + }, function(err) { + return safeCb(callback)(err); + }).$promise; + }, + + /** + * Gets all available info on a user + * (synchronous|asynchronous) + * + * @param {Function|*} callback - optional, funciton(user) + * @return {Object|Promise} + */ + getCurrentUser: function(callback) { + if (arguments.length === 0) { + return currentUser; } - }; - return Auth; - } + var value = (currentUser.hasOwnProperty('$promise')) ? + currentUser.$promise : currentUser; + return $q.when(value) + .then(function(user) { + safeCb(callback)(user); + return user; + }, function() { + safeCb(callback)({}); + return {}; + }); + }, + + /** + * Check if a user is logged in + * (synchronous|asynchronous) + * + * @param {Function|*} callback - optional, function(is) + * @return {Bool|Promise} + */ + isLoggedIn: function(callback) { + if (arguments.length === 0) { + return currentUser.hasOwnProperty('role'); + } + + return Auth.getCurrentUser(null) + .then(function(user) { + var is = user.hasOwnProperty('role'); + safeCb(callback)(is); + return is; + }); + }, + + /** + * Check if a user has a specified role or higher + * (synchronous|asynchronous) + * + * @param {String} role - the role to check against + * @param {Function|*} callback - optional, function(has) + * @return {Bool|Promise} + */ + hasRole: function(role, callback) { + var hasRole = function(r, h) { + return userRoles.indexOf(r) >= userRoles.indexOf(h); + }; + + if (arguments.length < 2) { + return hasRole(currentUser.role, role); + } + + return Auth.getCurrentUser(null) + .then(function(user) { + var has = (user.hasOwnProperty('role')) ? + hasRole(user.role, role) : false; + safeCb(callback)(has); + return has; + }); + }, + + /** + * Check if a user is an admin + * (synchronous|asynchronous) + * + * @param {Function|*} callback - optional, function(is) + * @return {Bool|Promise} + */ + isAdmin: function() { + return Auth.hasRole + .apply(Auth, [].concat.apply(['admin'], arguments)); + }, + + /** + * Get auth token + * + * @return {String} - a token string used for authenticating + */ + getToken: function() { + return $cookies.get('token'); + } + }; + + return Auth; +} - angular.module('<%= scriptAppName %>.auth') - .factory('Auth', AuthService); +angular.module('<%= scriptAppName %>.auth') + .factory('Auth', AuthService); })(); diff --git a/app/templates/client/components/auth(auth)/interceptor.service(js).js b/app/templates/client/components/auth(auth)/interceptor.service(js).js index 8843527b9..67c0526a3 100644 --- a/app/templates/client/components/auth(auth)/interceptor.service(js).js +++ b/app/templates/client/components/auth(auth)/interceptor.service(js).js @@ -2,34 +2,34 @@ (function() { - function authInterceptor($rootScope, $q, $cookies<% if (filters.ngroute) { %>, $location<% } if (filters.uirouter) { %>, $injector<% } %>) { - <% if (filters.uirouter) { %>var state; - <% } %>return { - // Add authorization token to headers - request: function(config) { - config.headers = config.headers || {}; - if ($cookies.get('token')) { - config.headers.Authorization = 'Bearer ' + $cookies.get('token'); - } - return config; - }, +function authInterceptor($rootScope, $q, $cookies<% if (filters.ngroute) { %>, $location<% } if (filters.uirouter) { %>, $injector<% } %>) { + <% if (filters.uirouter) { %>var state; + <% } %>return { + // Add authorization token to headers + request: function(config) { + config.headers = config.headers || {}; + if ($cookies.get('token')) { + config.headers.Authorization = 'Bearer ' + $cookies.get('token'); + } + return config; + }, - // Intercept 401s and redirect you to login - responseError: function(response) { - if (response.status === 401) { - <% if (filters.ngroute) { %>$location.path('/login');<% } if (filters.uirouter) { %>(state || (state = $injector.get('$state'))).go('login');<% } %> - // remove any stale tokens - $cookies.remove('token'); - return $q.reject(response); - } - else { - return $q.reject(response); - } + // Intercept 401s and redirect you to login + responseError: function(response) { + if (response.status === 401) { + <% if (filters.ngroute) { %>$location.path('/login');<% } if (filters.uirouter) { %>(state || (state = $injector.get('$state'))).go('login');<% } %> + // remove any stale tokens + $cookies.remove('token'); + return $q.reject(response); + } + else { + return $q.reject(response); } - }; - } + } + }; +} - angular.module('<%= scriptAppName %>.auth') - .factory('authInterceptor', authInterceptor); +angular.module('<%= scriptAppName %>.auth') + .factory('authInterceptor', authInterceptor); })(); diff --git a/app/templates/client/components/auth(auth)/router.decorator(js).js b/app/templates/client/components/auth(auth)/router.decorator(js).js index edd71d95e..4e48f401a 100644 --- a/app/templates/client/components/auth(auth)/router.decorator(js).js +++ b/app/templates/client/components/auth(auth)/router.decorator(js).js @@ -2,40 +2,40 @@ (function() { - function routerDecorator(<%= filters.uirouter ? '$stateProvider' : '$provide' %>) { - var authDecorator = function(<%= filters.uirouter ? 'state' : 'route' %>) { - var auth = <%= filters.uirouter ? 'state' : 'route' %>.authenticate; - if (auth) { - <%= filters.uirouter ? 'state' : 'route' %>.resolve = <%= filters.uirouter ? 'state' : 'route' %>.resolve || {}; - <%= filters.uirouter ? 'state' : 'route' %>.resolve.user = function(<%= filters.uirouter ? '$state' : '$location' %>, $q, Auth) { - return Auth.getCurrentUser(true) - .then(function(user) { - if ((typeof auth !== 'string' && user._id) || - (typeof auth === 'string' && Auth.hasRole(auth))) { - return user; - }<% if (filters.ngroute) { %> - $location.path((user._id) ? '/' : '/login');<% } if (filters.uirouter) { %> - $state.go((user._id) ? 'main' : 'login');<% } %> - return $q.reject('not authorized'); - }); - }; - } - };<% if (filters.ngroute) { %> +function routerDecorator(<%= filters.uirouter ? '$stateProvider' : '$provide' %>) { + var authDecorator = function(<%= filters.uirouter ? 'state' : 'route' %>) { + var auth = <%= filters.uirouter ? 'state' : 'route' %>.authenticate; + if (auth) { + <%= filters.uirouter ? 'state' : 'route' %>.resolve = <%= filters.uirouter ? 'state' : 'route' %>.resolve || {}; + <%= filters.uirouter ? 'state' : 'route' %>.resolve.user = function(<%= filters.uirouter ? '$state' : '$location' %>, $q, Auth) { + return Auth.getCurrentUser(true) + .then(function(user) { + if ((typeof auth !== 'string' && user._id) || + (typeof auth === 'string' && Auth.hasRole(auth))) { + return user; + }<% if (filters.ngroute) { %> + $location.path((user._id) ? '/' : '/login');<% } if (filters.uirouter) { %> + $state.go((user._id) ? 'main' : 'login');<% } %> + return $q.reject('not authorized'); + }); + }; + } + };<% if (filters.ngroute) { %> - $provide.decorator('$route', function($delegate) { - for (var r in $delegate.routes) { - authDecorator($delegate.routes[r]); - } - return $delegate; - });<% } if (filters.uirouter) { %> + $provide.decorator('$route', function($delegate) { + for (var r in $delegate.routes) { + authDecorator($delegate.routes[r]); + } + return $delegate; + });<% } if (filters.uirouter) { %> - $stateProvider.decorator('authenticate', function(state) { - authDecorator(state); - return state.authenticate; - });<% } %> - } + $stateProvider.decorator('authenticate', function(state) { + authDecorator(state); + return state.authenticate; + });<% } %> +} - angular.module('<%= scriptAppName %>.auth') - .config(routerDecorator); +angular.module('<%= scriptAppName %>.auth') + .config(routerDecorator); })(); diff --git a/app/templates/client/components/auth(auth)/user.service(js).js b/app/templates/client/components/auth(auth)/user.service(js).js index 965f84566..f347c72a9 100644 --- a/app/templates/client/components/auth(auth)/user.service(js).js +++ b/app/templates/client/components/auth(auth)/user.service(js).js @@ -2,27 +2,27 @@ (function() { - function UserResource($resource) { - return $resource('/api/users/:id/:controller', { - id: '@_id' +function UserResource($resource) { + return $resource('/api/users/:id/:controller', { + id: '@_id' + }, + { + changePassword: { + method: 'PUT', + params: { + controller:'password' + } }, - { - changePassword: { - method: 'PUT', - params: { - controller:'password' - } - }, - get: { - method: 'GET', - params: { - id:'me' - } + get: { + method: 'GET', + params: { + id:'me' } - }); - } + } + }); +} - angular.module('<%= scriptAppName %>.auth') - .factory('User', UserResource); +angular.module('<%= scriptAppName %>.auth') + .factory('User', UserResource); })(); From a9ab1fa0d60a6ac4cd05787af3d448b2a8942e41 Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 15 Sep 2015 22:45:10 -0400 Subject: [PATCH 0292/1357] chore(dependencies): update grunt-contrib-cssmin to `^0.14.0` --- app/templates/_package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 4d4b52a15..6eba3d7f3 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -44,7 +44,7 @@ "grunt-contrib-clean": "^0.6.0", "grunt-contrib-concat": "^0.5.1", "grunt-contrib-copy": "^0.8.0", - "grunt-contrib-cssmin": "^0.13.0", + "grunt-contrib-cssmin": "^0.14.0", "grunt-contrib-imagemin": "^0.9.4", "grunt-contrib-jshint": "~0.11.2", "grunt-contrib-uglify": "^0.9.1", From 2fab1f549806f950da53a756a9d179e181677a0f Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 16 Sep 2015 00:51:16 -0400 Subject: [PATCH 0293/1357] refactor(client:auth) simplify `authInterceptor.responseError` --- .../client/components/auth(auth)/interceptor.service(js).js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/templates/client/components/auth(auth)/interceptor.service(js).js b/app/templates/client/components/auth(auth)/interceptor.service(js).js index 67c0526a3..4191d1dde 100644 --- a/app/templates/client/components/auth(auth)/interceptor.service(js).js +++ b/app/templates/client/components/auth(auth)/interceptor.service(js).js @@ -20,11 +20,8 @@ function authInterceptor($rootScope, $q, $cookies<% if (filters.ngroute) { %>, $ <% if (filters.ngroute) { %>$location.path('/login');<% } if (filters.uirouter) { %>(state || (state = $injector.get('$state'))).go('login');<% } %> // remove any stale tokens $cookies.remove('token'); - return $q.reject(response); - } - else { - return $q.reject(response); } + return $q.reject(response); } }; } From 3c29832f515179a5f4fb54f9ed73ebc07dd34945 Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 16 Sep 2015 03:29:48 -0400 Subject: [PATCH 0294/1357] feat(app): implement util module for thin, reusable functions --- .../components/auth(auth)/auth.module(js).js | 1 + .../components/auth(auth)/auth.service(js).js | 17 ++--- .../client/components/util/util.module.js | 3 + .../client/components/util/util.service.js | 62 +++++++++++++++++++ test/test-file-creation.js | 2 + 5 files changed, 72 insertions(+), 13 deletions(-) create mode 100644 app/templates/client/components/util/util.module.js create mode 100644 app/templates/client/components/util/util.service.js diff --git a/app/templates/client/components/auth(auth)/auth.module(js).js b/app/templates/client/components/auth(auth)/auth.module(js).js index 3e096aeb3..60ce6e321 100644 --- a/app/templates/client/components/auth(auth)/auth.module(js).js +++ b/app/templates/client/components/auth(auth)/auth.module(js).js @@ -2,6 +2,7 @@ angular.module('<%= scriptAppName %>.auth', [ '<%= scriptAppName %>.constants', + '<%= scriptAppName %>.util', 'ngCookies'<% if (filters.ngroute) { %>, 'ngRoute'<% } if (filters.uirouter) { %>, 'ui.router'<% } %> diff --git a/app/templates/client/components/auth(auth)/auth.service(js).js b/app/templates/client/components/auth(auth)/auth.service(js).js index 49bdb2a9e..e8c7c16b1 100644 --- a/app/templates/client/components/auth(auth)/auth.service(js).js +++ b/app/templates/client/components/auth(auth)/auth.service(js).js @@ -2,19 +2,10 @@ (function() { -function AuthService($location, $http, $cookies, $q, appConfig, User) { - /** - * Return a callback or noop function - * - * @param {Function|*} cb - a 'potential' function - * @return {Function} - */ - var safeCb = function(cb) { - return (angular.isFunction(cb)) ? cb : angular.noop; - }, - - currentUser = {}, - userRoles = appConfig.userRoles || []; +function AuthService($location, $http, $cookies, $q, appConfig, Util, User) { + var safeCb = Util.safeCb; + var currentUser = {}; + var userRoles = appConfig.userRoles || []; if ($cookies.get('token') && $location.path() !== '/logout') { currentUser = User.get(); diff --git a/app/templates/client/components/util/util.module.js b/app/templates/client/components/util/util.module.js new file mode 100644 index 000000000..690b12456 --- /dev/null +++ b/app/templates/client/components/util/util.module.js @@ -0,0 +1,3 @@ +'use strict'; + +angular.module('<%= scriptAppName %>.util', []); diff --git a/app/templates/client/components/util/util.service.js b/app/templates/client/components/util/util.service.js new file mode 100644 index 000000000..71f0c25e5 --- /dev/null +++ b/app/templates/client/components/util/util.service.js @@ -0,0 +1,62 @@ +'use strict'; + +(function() { + +/** + * The Util service is for thin, globally reusable, utility functions + */ +function UtilService($window) { + + var Util = { + + /** + * Return a callback or noop function + * + * @param {Function|*} cb - a 'potential' function + * @return {Function} + */ + safeCb: function(cb) { + return (angular.isFunction(cb)) ? cb : angular.noop; + }, + + /** + * Parse a given url with the use of an anchor element + * + * @param {String} url - the url to parse + * @return {Object} - the parsed url, anchor element + */ + urlParse: function(url) { + var a = document.createElement('a'); + a.href = url; + return a; + }, + + /** + * Test whether or not a given url is same origin + * + * @param {String} url - url to test + * @param {String|String[]} [origins] - additional origins to test against + * @return {Boolean} - true if url is same origin + */ + isSameOrigin: function(url, origins) { + url = Util.urlParse(url); + origins = (origins && [].concat(origins)) || []; + origins = origins.map(Util.urlParse); + origins.push($window.location); + origins = origins.filter(function(o) { + return url.hostname === o.hostname && + url.port === o.port && + url.protocol === o.protocol; + }); + return (origins.length >= 1); + } + + }; + + return Util; +} + +angular.module('<%= scriptAppName %>.util') + .factory('Util', UtilService); + +})(); diff --git a/test/test-file-creation.js b/test/test-file-creation.js index ae1dc0297..5edd9ec84 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -182,6 +182,8 @@ describe('angular-fullstack generator', function () { 'client/components/navbar/navbar.' + markup, 'client/components/navbar/navbar.controller.' + script, 'client/components/navbar/navbar.directive.' + script, + 'client/components/util/util.module.' + script, + 'client/components/util/util.service.' + script, 'server/.jshintrc', 'server/.jshintrc-spec', 'server/app.js', From abcb51a7686bb138ef9d005a596e2de43b790766 Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 16 Sep 2015 03:46:36 -0400 Subject: [PATCH 0295/1357] fix(client:auth): restrict `Authorization` header to same origin --- .../client/components/auth(auth)/interceptor.service(js).js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/client/components/auth(auth)/interceptor.service(js).js b/app/templates/client/components/auth(auth)/interceptor.service(js).js index 4191d1dde..5bfb4b174 100644 --- a/app/templates/client/components/auth(auth)/interceptor.service(js).js +++ b/app/templates/client/components/auth(auth)/interceptor.service(js).js @@ -2,13 +2,13 @@ (function() { -function authInterceptor($rootScope, $q, $cookies<% if (filters.ngroute) { %>, $location<% } if (filters.uirouter) { %>, $injector<% } %>) { +function authInterceptor($rootScope, $q, $cookies<% if (filters.ngroute) { %>, $location<% } if (filters.uirouter) { %>, $injector<% } %>, Util) { <% if (filters.uirouter) { %>var state; <% } %>return { // Add authorization token to headers request: function(config) { config.headers = config.headers || {}; - if ($cookies.get('token')) { + if ($cookies.get('token') && Util.isSameOrigin(config.url)) { config.headers.Authorization = 'Bearer ' + $cookies.get('token'); } return config; From 64d0e4342b6cbcebf3f60e27afe0d7165f646821 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 9 Sep 2015 08:45:21 -0400 Subject: [PATCH 0296/1357] chore(travis): add node 4.0.0 to travis targets allow failures on node 4.0.0 for now --- .travis.yml | 5 +++++ app/templates/.travis.yml | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/.travis.yml b/.travis.yml index 82f95fde5..1ce49d7dc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,10 +2,15 @@ sudo: false language: node_js node_js: - '0.12' + - '4.0.0' env: global: - SAUCE_USERNAME=fullstack_ci - SAUCE_ACCESS_KEY=1a527ca6-4aa5-4618-86ce-0278bf158cbf +matrix: + fast_finish: true + allow_failures: + - node_js: 4.0.0 before_install: - ./scripts/sauce_connect_setup.sh - gem update --system diff --git a/app/templates/.travis.yml b/app/templates/.travis.yml index c12f57edb..95545e08d 100644 --- a/app/templates/.travis.yml +++ b/app/templates/.travis.yml @@ -1,6 +1,11 @@ language: node_js node_js: - '0.12' + - '4.0.0' +matrix: + fast_finish: true + allow_failures: + - node_js: 4.0.0 before_script: - npm install -g bower grunt-cli<% if (filters.sass) { %> - gem install sass<% } %> From cdfc423c9f079eacff8592d7c100609f3e85171a Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 15 Sep 2015 15:33:08 -0400 Subject: [PATCH 0297/1357] feat(gen): always use Babel leave in supporting code for use with eventually supporting typescript --- app/generator.js | 18 ++---- .../{account(js).js => account.js} | 0 ....controller(js).js => login.controller.js} | 0 ...ntroller(js).js => settings.controller.js} | 0 ...controller(js).js => signup.controller.js} | 0 ....controller(js).js => admin.controller.js} | 0 .../admin(auth)/{admin(js).js => admin.js} | 0 .../client/app/{app(js).js => app.js} | 0 ...n.controller(js).js => main.controller.js} | 0 ...er.spec(js).js => main.controller.spec.js} | 0 .../client/app/main/{main(js).js => main.js} | 0 .../{auth.module(js).js => auth.module.js} | 0 .../{auth.service(js).js => auth.service.js} | 0 ....service(js).js => interceptor.service.js} | 0 ...r.decorator(js).js => router.decorator.js} | 0 .../{user.service(js).js => user.service.js} | 0 ...r.directive(js).js => footer.directive.js} | 0 ...{modal.service(js).js => modal.service.js} | 0 ...ive(js).js => mongoose-error.directive.js} | 0 ...controller(js).js => navbar.controller.js} | 0 ...r.directive(js).js => navbar.directive.js} | 0 ...ler(js).js => oauth-buttons.controller.js} | 0 ...s).js => oauth-buttons.controller.spec.js} | 0 ...tive(js).js => oauth-buttons.directive.js} | 0 ...js).js => oauth-buttons.directive.spec.js} | 0 .../{socket.mock(js).js => socket.mock.js} | 0 ...ocket.service(js).js => socket.service.js} | 0 ...i-router.mock(js).js => ui-router.mock.js} | 0 test/test-file-creation.js | 61 ------------------- 29 files changed, 6 insertions(+), 73 deletions(-) rename app/templates/client/app/account(auth)/{account(js).js => account.js} (100%) rename app/templates/client/app/account(auth)/login/{login.controller(js).js => login.controller.js} (100%) rename app/templates/client/app/account(auth)/settings/{settings.controller(js).js => settings.controller.js} (100%) rename app/templates/client/app/account(auth)/signup/{signup.controller(js).js => signup.controller.js} (100%) rename app/templates/client/app/admin(auth)/{admin.controller(js).js => admin.controller.js} (100%) rename app/templates/client/app/admin(auth)/{admin(js).js => admin.js} (100%) rename app/templates/client/app/{app(js).js => app.js} (100%) rename app/templates/client/app/main/{main.controller(js).js => main.controller.js} (100%) rename app/templates/client/app/main/{main.controller.spec(js).js => main.controller.spec.js} (100%) rename app/templates/client/app/main/{main(js).js => main.js} (100%) rename app/templates/client/components/auth(auth)/{auth.module(js).js => auth.module.js} (100%) rename app/templates/client/components/auth(auth)/{auth.service(js).js => auth.service.js} (100%) rename app/templates/client/components/auth(auth)/{interceptor.service(js).js => interceptor.service.js} (100%) rename app/templates/client/components/auth(auth)/{router.decorator(js).js => router.decorator.js} (100%) rename app/templates/client/components/auth(auth)/{user.service(js).js => user.service.js} (100%) rename app/templates/client/components/footer/{footer.directive(js).js => footer.directive.js} (100%) rename app/templates/client/components/modal(uibootstrap)/{modal.service(js).js => modal.service.js} (100%) rename app/templates/client/components/mongoose-error(auth)/{mongoose-error.directive(js).js => mongoose-error.directive.js} (100%) rename app/templates/client/components/navbar/{navbar.controller(js).js => navbar.controller.js} (100%) rename app/templates/client/components/navbar/{navbar.directive(js).js => navbar.directive.js} (100%) rename app/templates/client/components/oauth-buttons(oauth)/{oauth-buttons.controller(js).js => oauth-buttons.controller.js} (100%) rename app/templates/client/components/oauth-buttons(oauth)/{oauth-buttons.controller.spec(js).js => oauth-buttons.controller.spec.js} (100%) rename app/templates/client/components/oauth-buttons(oauth)/{oauth-buttons.directive(js).js => oauth-buttons.directive.js} (100%) rename app/templates/client/components/oauth-buttons(oauth)/{oauth-buttons.directive.spec(js).js => oauth-buttons.directive.spec.js} (100%) rename app/templates/client/components/socket(socketio)/{socket.mock(js).js => socket.mock.js} (100%) rename app/templates/client/components/socket(socketio)/{socket.service(js).js => socket.service.js} (100%) rename app/templates/client/components/ui-router(uirouter)/{ui-router.mock(js).js => ui-router.mock.js} (100%) diff --git a/app/generator.js b/app/generator.js index 00fad1ad5..5478748f0 100644 --- a/app/generator.js +++ b/app/generator.js @@ -90,18 +90,13 @@ export default class Generator extends Base { this.log('# Client\n'); - this.prompt([{ + this.prompt([/*{ type: 'list', name: 'script', message: 'What would you like to write scripts with?', - choices: [ 'JavaScript', 'JavaScript + Babel'], - filter: function( val ) { - return { - 'JavaScript': 'js', - 'JavaScript + Babel': 'babel' - }[val]; - } - }, { + choices: ['Babel', 'TypeScript'], + filter: function(val) { return val.toLowerCase(); } + }, */{ type: 'list', name: 'markup', message: 'What would you like to write markup with?', @@ -134,9 +129,8 @@ export default class Generator extends Base { } }], function (answers) { - // also set 'js' to true if using babel - if(answers.script === 'babel') { this.filters.js = true; } - this.filters[answers.script] = true; + this.filters.js = true; + this.filters.babel = true; this.filters[answers.markup] = true; this.filters[answers.stylesheet] = true; this.filters[answers.router] = true; diff --git a/app/templates/client/app/account(auth)/account(js).js b/app/templates/client/app/account(auth)/account.js similarity index 100% rename from app/templates/client/app/account(auth)/account(js).js rename to app/templates/client/app/account(auth)/account.js diff --git a/app/templates/client/app/account(auth)/login/login.controller(js).js b/app/templates/client/app/account(auth)/login/login.controller.js similarity index 100% rename from app/templates/client/app/account(auth)/login/login.controller(js).js rename to app/templates/client/app/account(auth)/login/login.controller.js diff --git a/app/templates/client/app/account(auth)/settings/settings.controller(js).js b/app/templates/client/app/account(auth)/settings/settings.controller.js similarity index 100% rename from app/templates/client/app/account(auth)/settings/settings.controller(js).js rename to app/templates/client/app/account(auth)/settings/settings.controller.js diff --git a/app/templates/client/app/account(auth)/signup/signup.controller(js).js b/app/templates/client/app/account(auth)/signup/signup.controller.js similarity index 100% rename from app/templates/client/app/account(auth)/signup/signup.controller(js).js rename to app/templates/client/app/account(auth)/signup/signup.controller.js diff --git a/app/templates/client/app/admin(auth)/admin.controller(js).js b/app/templates/client/app/admin(auth)/admin.controller.js similarity index 100% rename from app/templates/client/app/admin(auth)/admin.controller(js).js rename to app/templates/client/app/admin(auth)/admin.controller.js diff --git a/app/templates/client/app/admin(auth)/admin(js).js b/app/templates/client/app/admin(auth)/admin.js similarity index 100% rename from app/templates/client/app/admin(auth)/admin(js).js rename to app/templates/client/app/admin(auth)/admin.js diff --git a/app/templates/client/app/app(js).js b/app/templates/client/app/app.js similarity index 100% rename from app/templates/client/app/app(js).js rename to app/templates/client/app/app.js diff --git a/app/templates/client/app/main/main.controller(js).js b/app/templates/client/app/main/main.controller.js similarity index 100% rename from app/templates/client/app/main/main.controller(js).js rename to app/templates/client/app/main/main.controller.js diff --git a/app/templates/client/app/main/main.controller.spec(js).js b/app/templates/client/app/main/main.controller.spec.js similarity index 100% rename from app/templates/client/app/main/main.controller.spec(js).js rename to app/templates/client/app/main/main.controller.spec.js diff --git a/app/templates/client/app/main/main(js).js b/app/templates/client/app/main/main.js similarity index 100% rename from app/templates/client/app/main/main(js).js rename to app/templates/client/app/main/main.js diff --git a/app/templates/client/components/auth(auth)/auth.module(js).js b/app/templates/client/components/auth(auth)/auth.module.js similarity index 100% rename from app/templates/client/components/auth(auth)/auth.module(js).js rename to app/templates/client/components/auth(auth)/auth.module.js diff --git a/app/templates/client/components/auth(auth)/auth.service(js).js b/app/templates/client/components/auth(auth)/auth.service.js similarity index 100% rename from app/templates/client/components/auth(auth)/auth.service(js).js rename to app/templates/client/components/auth(auth)/auth.service.js diff --git a/app/templates/client/components/auth(auth)/interceptor.service(js).js b/app/templates/client/components/auth(auth)/interceptor.service.js similarity index 100% rename from app/templates/client/components/auth(auth)/interceptor.service(js).js rename to app/templates/client/components/auth(auth)/interceptor.service.js diff --git a/app/templates/client/components/auth(auth)/router.decorator(js).js b/app/templates/client/components/auth(auth)/router.decorator.js similarity index 100% rename from app/templates/client/components/auth(auth)/router.decorator(js).js rename to app/templates/client/components/auth(auth)/router.decorator.js diff --git a/app/templates/client/components/auth(auth)/user.service(js).js b/app/templates/client/components/auth(auth)/user.service.js similarity index 100% rename from app/templates/client/components/auth(auth)/user.service(js).js rename to app/templates/client/components/auth(auth)/user.service.js diff --git a/app/templates/client/components/footer/footer.directive(js).js b/app/templates/client/components/footer/footer.directive.js similarity index 100% rename from app/templates/client/components/footer/footer.directive(js).js rename to app/templates/client/components/footer/footer.directive.js diff --git a/app/templates/client/components/modal(uibootstrap)/modal.service(js).js b/app/templates/client/components/modal(uibootstrap)/modal.service.js similarity index 100% rename from app/templates/client/components/modal(uibootstrap)/modal.service(js).js rename to app/templates/client/components/modal(uibootstrap)/modal.service.js diff --git a/app/templates/client/components/mongoose-error(auth)/mongoose-error.directive(js).js b/app/templates/client/components/mongoose-error(auth)/mongoose-error.directive.js similarity index 100% rename from app/templates/client/components/mongoose-error(auth)/mongoose-error.directive(js).js rename to app/templates/client/components/mongoose-error(auth)/mongoose-error.directive.js diff --git a/app/templates/client/components/navbar/navbar.controller(js).js b/app/templates/client/components/navbar/navbar.controller.js similarity index 100% rename from app/templates/client/components/navbar/navbar.controller(js).js rename to app/templates/client/components/navbar/navbar.controller.js diff --git a/app/templates/client/components/navbar/navbar.directive(js).js b/app/templates/client/components/navbar/navbar.directive.js similarity index 100% rename from app/templates/client/components/navbar/navbar.directive(js).js rename to app/templates/client/components/navbar/navbar.directive.js diff --git a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller(js).js b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller.js similarity index 100% rename from app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller(js).js rename to app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller.js diff --git a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller.spec(js).js b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller.spec.js similarity index 100% rename from app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller.spec(js).js rename to app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.controller.spec.js diff --git a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive(js).js b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive.js similarity index 100% rename from app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive(js).js rename to app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive.js diff --git a/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive.spec(js).js b/app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive.spec.js similarity index 100% rename from app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive.spec(js).js rename to app/templates/client/components/oauth-buttons(oauth)/oauth-buttons.directive.spec.js diff --git a/app/templates/client/components/socket(socketio)/socket.mock(js).js b/app/templates/client/components/socket(socketio)/socket.mock.js similarity index 100% rename from app/templates/client/components/socket(socketio)/socket.mock(js).js rename to app/templates/client/components/socket(socketio)/socket.mock.js diff --git a/app/templates/client/components/socket(socketio)/socket.service(js).js b/app/templates/client/components/socket(socketio)/socket.service.js similarity index 100% rename from app/templates/client/components/socket(socketio)/socket.service(js).js rename to app/templates/client/components/socket(socketio)/socket.service.js diff --git a/app/templates/client/components/ui-router(uirouter)/ui-router.mock(js).js b/app/templates/client/components/ui-router(uirouter)/ui-router.mock.js similarity index 100% rename from app/templates/client/components/ui-router(uirouter)/ui-router.mock(js).js rename to app/templates/client/components/ui-router(uirouter)/ui-router.mock.js diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 5edd9ec84..26f326dc7 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -729,66 +729,5 @@ describe('angular-fullstack generator', function () { } }); - - describe('with no preprocessors and no server options', function() { - var testOptions = { - script: 'js', - markup: 'html', - stylesheet: 'css', - router: 'ngroute', - testing: 'jasmine', - odms: [], - auth: false, - oauth: [], - socketio: false, - bootstrap: true, - uibootstrap: true - }; - - beforeEach(function(done) { - helpers.mockPrompt(gen, testOptions); - done(); - }); - - it('should run client tests successfully', function(done) { - runTest('grunt test:client', this, done); - }); - - it('should pass jscs', function(done) { - runTest('grunt jscs', this, done); - }); - - it('should pass lint', function(done) { - runTest('grunt jshint', this, done); - }); - - it('should run server tests successfully', function(done) { - runTest('grunt test:server', this, done); - }); - - it('should generate expected files', function (done) { - gen.run(function () { - assert.file(genFiles(testOptions)); - done(); - }); - }); - - it('should not generate unexpected files', function (done) { - gen.run(function () { - assertOnlyFiles(genFiles(testOptions), done); - }); - }); - - if(!process.env.SKIP_E2E) { - it('should run e2e tests successfully', function (done) { - runTest('grunt test:e2e', this, done, 240000); - }); - - //it('should run e2e tests successfully for production app', function (done) { - // runTest('grunt test:e2e:prod', this, done, 240000); - //}); - } - - }); }); }); From 1a783ba4f8653b3fa2b90b7432ad58053c52f29f Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 15 Sep 2015 16:11:10 -0400 Subject: [PATCH 0298/1357] feat(client:main): use a class for the main controller --- .../client/app/main/main.controller.js | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/app/templates/client/app/main/main.controller.js b/app/templates/client/app/main/main.controller.js index db9bbd5c3..f69ad1e8b 100644 --- a/app/templates/client/app/main/main.controller.js +++ b/app/templates/client/app/main/main.controller.js @@ -2,30 +2,32 @@ (function() { -function MainController($scope, $http<% if (filters.socketio) { %>, socket<% } %>) { - var self = this; - this.awesomeThings = []; - - $http.get('/api/things').then(function(response) { - self.awesomeThings = response.data;<% if (filters.socketio) { %> - socket.syncUpdates('thing', self.awesomeThings);<% } %> - });<% if (filters.models) { %> - - this.addThing = function() { - if (self.newThing === '') { - return; +class MainController { + + constructor($http<% if (filters.socketio) { %>, $scope, socket<% } %>) { + this.$http = $http; + this.awesomeThings = []; + + $http.get('/api/things').then(response => { + this.awesomeThings = response.data;<% if (filters.socketio) { %> + socket.syncUpdates('thing', this.awesomeThings);<% } %> + });<% if (filters.socketio) { %> + + $scope.$on('$destroy', function() { + socket.unsyncUpdates('thing'); + });<% } %> + }<% if (filters.models) { %> + + addThing() { + if (this.newThing) { + this.$http.post('/api/things', { name: this.newThing }); + this.newThing = ''; } - $http.post('/api/things', { name: self.newThing }); - self.newThing = ''; - }; + } - this.deleteThing = function(thing) { - $http.delete('/api/things/' + thing._id); - };<% } if (filters.socketio) { %> - - $scope.$on('$destroy', function() { - socket.unsyncUpdates('thing'); - });<% } %> + deleteThing(thing) { + this.$http.delete('/api/things/' + thing._id); + }<% } %> } angular.module('<%= scriptAppName %>') From 5babe1ce7ff269885fffdf5c5a407d763a0d40d9 Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 16 Sep 2015 17:18:25 -0400 Subject: [PATCH 0299/1357] feat(client:admin): implement admin components as a seperate module --- app/generator.js | 1 + app/templates/client/app/admin(auth)/admin.controller.js | 2 +- app/templates/client/app/admin(auth)/admin.module.js | 7 +++++++ .../client/app/admin(auth)/{admin.js => admin.router.js} | 4 ++-- test/test-file-creation.js | 3 ++- 5 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 app/templates/client/app/admin(auth)/admin.module.js rename app/templates/client/app/admin(auth)/{admin.js => admin.router.js} (79%) diff --git a/app/generator.js b/app/generator.js index 5478748f0..67a00bfe5 100644 --- a/app/generator.js +++ b/app/generator.js @@ -375,6 +375,7 @@ export default class Generator extends Base { if(this.filters.uirouter) angModules.push("'ui.router'"); if(this.filters.uibootstrap) angModules.push("'ui.bootstrap'"); if(this.filters.auth) { + angModules.unshift(`'${this.scriptAppName}.admin'`); angModules.unshift(`'${this.scriptAppName}.auth'`); angModules.push("'validation.match'"); } diff --git a/app/templates/client/app/admin(auth)/admin.controller.js b/app/templates/client/app/admin(auth)/admin.controller.js index 3cbfd4b7f..bcc8f0a6a 100644 --- a/app/templates/client/app/admin(auth)/admin.controller.js +++ b/app/templates/client/app/admin(auth)/admin.controller.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('<%= scriptAppName %>') +angular.module('<%= scriptAppName %>.admin') .controller('AdminCtrl', function($scope, $http, Auth, User) { // Use the User $resource to fetch all users diff --git a/app/templates/client/app/admin(auth)/admin.module.js b/app/templates/client/app/admin(auth)/admin.module.js new file mode 100644 index 000000000..da769ae91 --- /dev/null +++ b/app/templates/client/app/admin(auth)/admin.module.js @@ -0,0 +1,7 @@ +'use strict'; + +angular.module('<%= scriptAppName %>.admin', [ + '<%= scriptAppName %>.auth'<% if (filters.ngroute) { %>, + 'ngRoute'<% } if (filters.uirouter) { %>, + 'ui.router'<% } %> +]); diff --git a/app/templates/client/app/admin(auth)/admin.js b/app/templates/client/app/admin(auth)/admin.router.js similarity index 79% rename from app/templates/client/app/admin(auth)/admin.js rename to app/templates/client/app/admin(auth)/admin.router.js index 510363868..fd0366df0 100644 --- a/app/templates/client/app/admin(auth)/admin.js +++ b/app/templates/client/app/admin(auth)/admin.router.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('<%= scriptAppName %>') +angular.module('<%= scriptAppName %>.admin') <% if (filters.ngroute) { %>.config(function($routeProvider) { $routeProvider .when('/admin', { @@ -8,7 +8,7 @@ angular.module('<%= scriptAppName %>') controller: 'AdminCtrl', authenticate: 'admin' }); - });<% } %><% if (filters.uirouter) { %>.config(function($stateProvider) { + });<% } if (filters.uirouter) { %>.config(function($stateProvider) { $stateProvider .state('admin', { url: '/admin', diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 26f326dc7..ef4a3e8e4 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -267,7 +267,8 @@ describe('angular-fullstack generator', function () { 'client/app/account/signup/signup.controller.' + script, 'client/app/admin/admin.' + markup, 'client/app/admin/admin.' + stylesheet, - 'client/app/admin/admin.' + script, + 'client/app/admin/admin.module.' + script, + 'client/app/admin/admin.router.' + script, 'client/app/admin/admin.controller.' + script, 'client/components/auth/auth.module.' + script, 'client/components/auth/auth.service.' + script, From 8a76da29efd6a35819df1e24f153f2358b685f3d Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 16 Sep 2015 17:32:19 -0400 Subject: [PATCH 0300/1357] feat(client:admin): use controllerAs syntax for `AdminController` --- .../client/app/admin(auth)/admin(html).html | 4 ++-- .../client/app/admin(auth)/admin(jade).jade | 4 ++-- .../app/admin(auth)/admin.controller.js | 23 +++++++++++-------- .../client/app/admin(auth)/admin.router.js | 6 +++-- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/app/templates/client/app/admin(auth)/admin(html).html b/app/templates/client/app/admin(auth)/admin(html).html index 7688c9b47..fca41494e 100644 --- a/app/templates/client/app/admin(auth)/admin(html).html +++ b/app/templates/client/app/admin(auth)/admin(html).html @@ -3,10 +3,10 @@

The delete user and user index api routes are restricted to users with the 'admin' role.

    -
  • +
  • {{user.name}}
    {{user.email}} - +
diff --git a/app/templates/client/app/admin(auth)/admin(jade).jade b/app/templates/client/app/admin(auth)/admin(jade).jade index bcef64773..822e747d8 100644 --- a/app/templates/client/app/admin(auth)/admin(jade).jade +++ b/app/templates/client/app/admin(auth)/admin(jade).jade @@ -3,9 +3,9 @@ navbar p | The delete user and user index api routes are restricted to users with the 'admin' role. ul.list-group - li.list-group-item(ng-repeat='user in users') + li.list-group-item(ng-repeat='user in admin.users') strong {{user.name}} br span.text-muted {{user.email}} - a.trash(ng-click='delete(user)') + a.trash(ng-click='admin.delete(user)') span.glyphicon.glyphicon-trash.pull-right diff --git a/app/templates/client/app/admin(auth)/admin.controller.js b/app/templates/client/app/admin(auth)/admin.controller.js index bcc8f0a6a..c28d2adf3 100644 --- a/app/templates/client/app/admin(auth)/admin.controller.js +++ b/app/templates/client/app/admin(auth)/admin.controller.js @@ -1,13 +1,18 @@ 'use strict'; -angular.module('<%= scriptAppName %>.admin') - .controller('AdminCtrl', function($scope, $http, Auth, User) { +(function() { + +function AdminController(User) { + // Use the User $resource to fetch all users + var users = this.users = User.query(); - // Use the User $resource to fetch all users - $scope.users = User.query(); + this.delete = function(user) { + user.$remove(); + users.splice(users.indexOf(user), 1); + }; +} + +angular.module('<%= scriptAppName %>.admin') + .controller('AdminController', AdminController); - $scope.delete = function(user) { - User.remove({ id: user._id }); - $scope.users.splice(this.$index, 1); - }; - }); +})(); diff --git a/app/templates/client/app/admin(auth)/admin.router.js b/app/templates/client/app/admin(auth)/admin.router.js index fd0366df0..cc3d9e9f9 100644 --- a/app/templates/client/app/admin(auth)/admin.router.js +++ b/app/templates/client/app/admin(auth)/admin.router.js @@ -5,7 +5,8 @@ angular.module('<%= scriptAppName %>.admin') $routeProvider .when('/admin', { templateUrl: 'app/admin/admin.html', - controller: 'AdminCtrl', + controller: 'AdminController', + controllerAs: 'admin', authenticate: 'admin' }); });<% } if (filters.uirouter) { %>.config(function($stateProvider) { @@ -13,7 +14,8 @@ angular.module('<%= scriptAppName %>.admin') .state('admin', { url: '/admin', templateUrl: 'app/admin/admin.html', - controller: 'AdminCtrl', + controller: 'AdminController', + controllerAs: 'admin', authenticate: 'admin' }); });<% } %> From d93c7d5e56a3a7885c53ddfdfed70c2a04fee31c Mon Sep 17 00:00:00 2001 From: kingcody Date: Wed, 16 Sep 2015 20:18:14 -0400 Subject: [PATCH 0301/1357] refactor(karma): update file globs, jade preprocessor only when `filters.jade` --- app/templates/_package.json | 4 ++-- app/templates/karma.conf.js | 23 ++++++++--------------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 6eba3d7f3..336292463 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -49,7 +49,8 @@ "grunt-contrib-jshint": "~0.11.2", "grunt-contrib-uglify": "^0.9.1", "grunt-contrib-watch": "~0.6.1",<% if (filters.jade) { %> - "grunt-contrib-jade": "^0.15.0",<% } %><% if (filters.less) { %> + "grunt-contrib-jade": "^0.15.0", + "karma-ng-jade2js-preprocessor": "^0.2.0",<% } %><% if (filters.less) { %> "grunt-contrib-less": "^1.0.0",<% } %><% if(filters.babel) { %> "karma-babel-preprocessor": "^5.2.1",<% } %> "grunt-babel": "~5.0.0", @@ -95,7 +96,6 @@ "karma-firefox-launcher": "~0.1.6", "karma-script-launcher": "~0.1.0", "karma-html2js-preprocessor": "~0.1.0", - "karma-ng-jade2js-preprocessor": "^0.2.0", "karma-chrome-launcher": "~0.2.0", "requirejs": "~2.1.11", "karma-requirejs": "~0.2.2", diff --git a/app/templates/karma.conf.js b/app/templates/karma.conf.js index 61aa87b74..f85a28f71 100644 --- a/app/templates/karma.conf.js +++ b/app/templates/karma.conf.js @@ -22,29 +22,25 @@ module.exports = function(config) { // endbower<% if (filters.socketio) { %> 'node_modules/socket.io-client/socket.io.js',<% } %> 'client/app/app.js', - 'client/app/**/*.js', - 'client/components/**/*.js', - 'client/app/**/*.jade', - 'client/components/**/*.jade', - 'client/app/**/*.html', - 'client/components/**/*.html' + 'client/{app,components}/**/*.module.js', + 'client/{app,components}/**/*.js', + 'client/{app,components}/**/*.<%= filters.jade ? '{jade,html}' : 'html' %>' ], preprocessors: { - '**/*.jade': 'ng-jade2js', - '**/*.html': 'html2js',<% if(filters.babel) { %> + '**/*.html': 'html2js'<% if (filters.jade) { %>, + '**/*.jade': 'ng-jade2js'<% } if (filters.babel) { %>, 'client/{app,components}/**/*.js': 'babel'<% } %> }, ngHtml2JsPreprocessor: { stripPrefix: 'client/' - }, + },<% if (filters.jade) { %> ngJade2JsPreprocessor: { stripPrefix: 'client/' - }, + },<% } if (filters.babel) { %> - <% if(filters.babel) { %> babelPreprocessor: { options: { sourceMap: 'inline' @@ -55,8 +51,7 @@ module.exports = function(config) { sourceFileName: function (file) { return file.originalPath; } - }, - <% } %> + },<% } %> // list of files / patterns to exclude exclude: [], @@ -80,7 +75,6 @@ module.exports = function(config) { // enable / disable watching file and executing tests whenever any file changes autoWatch: false, - // Start these browsers, currently available: // - Chrome // - ChromeCanary @@ -91,7 +85,6 @@ module.exports = function(config) { // - IE (only Windows) browsers: ['PhantomJS'], - // Continuous Integration mode // if true, it capture browsers, run tests and exit singleRun: false From 618461ff5da5f27f36d4477d9ac7a44e6b26c516 Mon Sep 17 00:00:00 2001 From: kingcody Date: Thu, 17 Sep 2015 01:18:56 -0400 Subject: [PATCH 0302/1357] feat(client:admin): use class for AdminController --- .../client/app/admin(auth)/admin.controller.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/app/templates/client/app/admin(auth)/admin.controller.js b/app/templates/client/app/admin(auth)/admin.controller.js index c28d2adf3..698120b61 100644 --- a/app/templates/client/app/admin(auth)/admin.controller.js +++ b/app/templates/client/app/admin(auth)/admin.controller.js @@ -2,14 +2,17 @@ (function() { -function AdminController(User) { - // Use the User $resource to fetch all users - var users = this.users = User.query(); +class AdminController { - this.delete = function(user) { + constructor(User) { + // Use the User $resource to fetch all users + this.users = User.query(); + } + + delete(user) { user.$remove(); - users.splice(users.indexOf(user), 1); - }; + this.users.splice(this.users.indexOf(user), 1); + } } angular.module('<%= scriptAppName %>.admin') From 4228330ba99bdcb5914a380d4dd26397a9b61679 Mon Sep 17 00:00:00 2001 From: kingcody Date: Sat, 19 Sep 2015 01:50:18 -0400 Subject: [PATCH 0303/1357] chore(dependencies): require peer-dependant modules directly, per npm 3+ Changes: * require `chai`, `sinon`, and `phantomjs` directly --- app/templates/_package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/templates/_package.json b/app/templates/_package.json index 6eba3d7f3..682fa04d8 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -83,6 +83,8 @@ "grunt-mocha-test": "~0.12.7", "grunt-mocha-istanbul": "^3.0.1", "istanbul": "^0.3.17", + "chai": "^3.2.0", + "sinon": "^1.16.1", "chai-as-promised": "^5.1.0", "chai-things": "^0.2.0", "sinon-chai": "^2.8.0",<% if (filters.mocha) { %> @@ -100,6 +102,7 @@ "requirejs": "~2.1.11", "karma-requirejs": "~0.2.2", "karma-jade-preprocessor": "0.0.11", + "phantomjs": "^1.9.18", "karma-phantomjs-launcher": "~0.2.0", "karma": "~0.13.3", "karma-ng-html2js-preprocessor": "~0.1.2", From a8bd8a678d370035277309551e11e0870fa49b1e Mon Sep 17 00:00:00 2001 From: kingcody Date: Sun, 20 Sep 2015 21:30:39 -0400 Subject: [PATCH 0304/1357] fix(server:config): template db configs and add sequelize prod conf --- .../server/config/environment/development.js | 11 ++++-- .../server/config/environment/production.js | 36 ++++++++++++------- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/app/templates/server/config/environment/development.js b/app/templates/server/config/environment/development.js index d79b250b3..b97297e36 100644 --- a/app/templates/server/config/environment/development.js +++ b/app/templates/server/config/environment/development.js @@ -2,11 +2,14 @@ // Development specific configuration // ================================== -module.exports = { +module.exports = {<% if (filters.mongoose) { %> + // MongoDB connection options mongo: { uri: 'mongodb://localhost/<%= lodash.slugify(appname) %>-dev' - }, + },<% } if (filters.sequelize) { %> + + // Sequelize connecton opions sequelize: { uri: 'sqlite://', options: { @@ -16,7 +19,9 @@ module.exports = { timestamps: false } } - }, + },<% } %> + // Seed database on startup seedDB: true + }; diff --git a/app/templates/server/config/environment/production.js b/app/templates/server/config/environment/production.js index abdda30a3..bb2a0375c 100644 --- a/app/templates/server/config/environment/production.js +++ b/app/templates/server/config/environment/production.js @@ -4,21 +4,33 @@ // ================================= module.exports = { // Server IP - ip: process.env.OPENSHIFT_NODEJS_IP || - process.env.IP || - undefined, + ip: process.env.OPENSHIFT_NODEJS_IP || + process.env.IP || + undefined, // Server port - port: process.env.OPENSHIFT_NODEJS_PORT || - process.env.PORT || - 8080, + port: process.env.OPENSHIFT_NODEJS_PORT || + process.env.PORT || + 8080<% if (filters.mongoose) { %>, // MongoDB connection options mongo: { - uri: process.env.MONGOLAB_URI || - process.env.MONGOHQ_URL || - process.env.OPENSHIFT_MONGODB_DB_URL + - process.env.OPENSHIFT_APP_NAME || - 'mongodb://localhost/<%= lodash.slugify(appname) %>' - } + uri: process.env.MONGOLAB_URI || + process.env.MONGOHQ_URL || + process.env.OPENSHIFT_MONGODB_DB_URL + + process.env.OPENSHIFT_APP_NAME || + 'mongodb://localhost/<%= lodash.slugify(appname) %>' + }<% } if (filters.sequelize) { %>, + + sequelize: { + uri: process.env.SEQUELIZE_URI || + 'sqlite://', + options: { + logging: false, + storage: 'dist.sqlite', + define: { + timestamps: false + } + } + }<% } %> }; From 2266709c789766253fb7167d3f5c6d41a6f79122 Mon Sep 17 00:00:00 2001 From: devon townsend Date: Wed, 23 Sep 2015 13:46:59 -0700 Subject: [PATCH 0305/1357] Fix typo in readme.md --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index b63bc9562..6a5c91068 100644 --- a/readme.md +++ b/readme.md @@ -438,7 +438,7 @@ See the [contributing docs](https://github.com/DaftMonk/generator-angular-fullst This project has 2 main branches: `master` and `canary`. The `master` branch is where the current stable code lives and should be used for production setups. The `canary` branch is the main development branch, this is where PRs should be submitted to (backport fixes may be applied to `master`). -By seperating the current stable code from the cutting-edge development we hope to provide a stable and efficient workflow for users and developers alike. +By separating the current stable code from the cutting-edge development we hope to provide a stable and efficient workflow for users and developers alike. When submitting an issue, please follow the [guidelines](https://github.com/yeoman/yeoman/blob/master/contributing.md#issue-submission). Especially important is to make sure Yeoman is up-to-date, and providing the command or commands that cause the issue. From 0138cdaffe82c97ee521540d9d6df33a485171e4 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 6 Oct 2015 12:48:11 -0400 Subject: [PATCH 0306/1357] chore(npm): grunt-node-inspector ^0.2.0 -> ^0.4.1 --- app/templates/_package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 682fa04d8..1aa01b38f 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -61,7 +61,7 @@ "grunt-filerev": "^2.3.1", "grunt-usemin": "^3.0.0", "grunt-env": "~0.4.1", - "grunt-node-inspector": "^0.2.0", + "grunt-node-inspector": "^0.4.1", "grunt-nodemon": "^0.4.0", "grunt-angular-templates": "^0.5.4", "grunt-dom-munger": "^3.4.0", From 605d3151d0c05c9afa568dbbe20317b121734521 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 14 Oct 2015 12:14:01 -0400 Subject: [PATCH 0307/1357] docs(gen:readme): remove demo --- readme.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/readme.md b/readme.md index b63bc9562..f9b1b8b4f 100644 --- a/readme.md +++ b/readme.md @@ -12,8 +12,6 @@ ## Example project -Generated with defaults: http://fullstack-demo.herokuapp.com/. - Source code: https://github.com/DaftMonk/fullstack-demo ## Usage From 42a4b8f80518d42abf97c67d2a62406e07cceedb Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 14 Oct 2015 15:23:24 -0400 Subject: [PATCH 0308/1357] feat(jscs): update to ^2.1.0, rename config file to .jscsrc, use esnext option --- app/templates/{.jscs.json => .jscsrc} | 1 + app/templates/Gruntfile.js | 2 +- app/templates/_package.json | 2 +- test/test-file-creation.js | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) rename app/templates/{.jscs.json => .jscsrc} (98%) diff --git a/app/templates/.jscs.json b/app/templates/.jscsrc similarity index 98% rename from app/templates/.jscs.json rename to app/templates/.jscsrc index 99393d5f6..76b4a9aaa 100644 --- a/app/templates/.jscs.json +++ b/app/templates/.jscsrc @@ -1,4 +1,5 @@ { + "esnext": true, "maximumLineLength": { "value": 100, "allowComments": true, diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index cc3d414e0..1c3ad2bfc 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -165,7 +165,7 @@ module.exports = function (grunt) { jscs: { options: { - config: ".jscs.json" + config: ".jscsrc" }, main: { files: { diff --git a/app/templates/_package.json b/app/templates/_package.json index 4e4490510..217df92ab 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -55,7 +55,7 @@ "karma-babel-preprocessor": "^5.2.1",<% } %> "grunt-babel": "~5.0.0", "grunt-google-cdn": "~0.4.0", - "grunt-jscs": "^2.0.0", + "grunt-jscs": "^2.1.0", "grunt-newer": "^1.1.1", "grunt-ng-annotate": "^1.0.1", "grunt-ng-constant": "^1.1.0", diff --git a/test/test-file-creation.js b/test/test-file-creation.js index ef4a3e8e4..555036c94 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -212,7 +212,7 @@ describe('angular-fullstack generator', function () { '.gitattributes', '.gitignore', '.travis.yml', - '.jscs.json', + '.jscsrc', '.yo-rc.json', 'Gruntfile.js', 'package.json', From 8069d3b304d360dff2a28eb5badb0b343dfab357 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Fri, 30 Oct 2015 14:34:02 -0400 Subject: [PATCH 0309/1357] docs(gen:readme): modify supported configurations section reformat supported configurations section, add more info closes #1397 --- readme.md | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/readme.md b/readme.md index f9b1b8b4f..1ea32f406 100644 --- a/readme.md +++ b/readme.md @@ -39,19 +39,34 @@ Run `grunt` for building, `grunt serve` for preview, and `grunt serve:dist` for ## Supported Configurations +**General** + +* Build Systems: `Grunt`, `Gulp` (Coming Soon) +* Testing: + * `Jasmine` + * `Mocha + Chai + Sinon` + * Chai assertions: + * `Expect` + * `Should` + **Client** -* Scripts: `JavaScript`, `Babel` +* Scripts: `Babel`, `TypeScript` (Coming Soon) * Markup: `HTML`, `Jade` -* Stylesheets: `CSS`, `Stylus`, `Sass`, `Less`, +* Stylesheets: `CSS`, `Stylus`, `Sass`, `Less` * Angular Routers: `ngRoute`, `ui-router` +* CSS Frameworks: `Bootstrap` + * Option to include `UI Bootstrap` **Server** -* Database: `None`, `MongoDB` -* Authentication boilerplate: `Yes`, `No` -* oAuth integrations: `Facebook` `Twitter` `Google` -* Socket.io integration: `Yes`, `No` +* Scripts: `Babel` +* Database: + * `None`, + * `MongoDB`, `SQL` + * Authentication boilerplate: `Yes`, `No` + * oAuth integrations: `Facebook` `Twitter` `Google` + * Socket.io integration: `Yes`, `No` ## Injection From f4f8db4b4ab01f5ca1e4f076f863fb0fbb07c728 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Thu, 19 Nov 2015 15:18:48 -0500 Subject: [PATCH 0310/1357] fix(npm): use latest version numbers instead of "latest" closes #1440 --- app/templates/_package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 217df92ab..9304ef869 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -27,9 +27,9 @@ "express-jwt": "^3.0.0", "passport": "~0.3.0", "passport-local": "^1.0.0",<% } %><% if (filters.facebookAuth) { %> - "passport-facebook": "latest",<% } %><% if (filters.twitterAuth) { %> - "passport-twitter": "latest",<% } %><% if (filters.googleAuth) { %> - "passport-google-oauth": "latest",<% } %><% if (filters.socketio) { %> + "passport-facebook": "^2.0.0",<% } %><% if (filters.twitterAuth) { %> + "passport-twitter": "^1.0.3",<% } %><% if (filters.googleAuth) { %> + "passport-google-oauth": "~0.2.0",<% } %><% if (filters.socketio) { %> "socket.io": "^1.3.5", "socket.io-client": "^1.3.5", "socketio-jwt": "^4.2.0",<% } %> @@ -71,7 +71,7 @@ "grunt-karma": "~0.12.0", "grunt-build-control": "^0.6.0",<% if(filters.sass) { %> "grunt-contrib-sass": "^0.9.0",<% } %><% if(filters.stylus) { %> - "grunt-contrib-stylus": "latest",<% } %> + "grunt-contrib-stylus": "~0.22.0",<% } %> "jit-grunt": "^0.9.1", "time-grunt": "^1.2.1", "grunt-express-server": "^0.5.1", From 08831de1022aecbe07c24082fa51a19f49aae226 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sat, 31 Oct 2015 13:56:02 -0400 Subject: [PATCH 0311/1357] feat(): update package.json node & npm. switch travis.yml to test 4.2.2, allow failures on 5.0.0 --- .travis.yml | 5 ++--- app/templates/.travis.yml | 5 ++--- app/templates/_package.json | 3 ++- package.json | 4 ++-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1ce49d7dc..87857d767 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,7 @@ sudo: false language: node_js node_js: - - '0.12' - - '4.0.0' + - 4.2.2 env: global: - SAUCE_USERNAME=fullstack_ci @@ -10,7 +9,7 @@ env: matrix: fast_finish: true allow_failures: - - node_js: 4.0.0 + - node_js: 5.0.0 before_install: - ./scripts/sauce_connect_setup.sh - gem update --system diff --git a/app/templates/.travis.yml b/app/templates/.travis.yml index 95545e08d..c4451b445 100644 --- a/app/templates/.travis.yml +++ b/app/templates/.travis.yml @@ -1,11 +1,10 @@ language: node_js node_js: - - '0.12' - - '4.0.0' + - 4.2.2 matrix: fast_finish: true allow_failures: - - node_js: 4.0.0 + - node_js: 5.0.0 before_script: - npm install -g bower grunt-cli<% if (filters.sass) { %> - gem install sass<% } %> diff --git a/app/templates/_package.json b/app/templates/_package.json index 9304ef869..9db220316 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -111,7 +111,8 @@ "supertest": "^1.1.0" }, "engines": { - "node": ">=0.12.0" + "node": "^4.2.2", + "npm": "^2.14.7" }, "scripts": { "start": "node server", diff --git a/package.json b/package.json index caad04a6b..9bb8767ca 100644 --- a/package.json +++ b/package.json @@ -62,8 +62,8 @@ "yeoman-assert": "^2.0.0" }, "engines": { - "node": ">=0.12.0", - "npm": ">=1.2.10" + "node": "^4.2.2", + "npm": "^2.14.7" }, "license": "BSD-2-Clause" } From eaed80fc358ea23ad1159d924f10806abccfa14d Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 3 Nov 2015 15:43:34 -0500 Subject: [PATCH 0312/1357] fix(tests): use `npm run-script update-webdriver` instead of `npm run update-webdriver` --- Gruntfile.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 64e407a11..3b9964182 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -292,8 +292,8 @@ module.exports = function (grunt) { child_process.exec('bower install', {cwd: '../fixtures'}, function (error, stdout, stderr) { if(!process.env.SAUCE_USERNAME) { - grunt.log.ok('running npm run update-webdriver'); - child_process.exec('npm run update-webdriver', function() { + grunt.log.ok('running npm run-script update-webdriver'); + child_process.exec('npm run-script update-webdriver', function() { shell.cd('../../'); done(); }); From 3c1bff7daad39a0e204d8626df81149553db6d09 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Thu, 19 Nov 2015 21:09:53 -0500 Subject: [PATCH 0313/1357] chore(npm): use protractor 3.0.0 use *my* version of grunt-protractor-runner --- app/templates/_package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 9db220316..6193ef373 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -66,7 +66,7 @@ "grunt-nodemon": "^0.4.0", "grunt-angular-templates": "^0.5.4", "grunt-dom-munger": "^3.4.0", - "grunt-protractor-runner": "^2.0.0", + "grunt-protractor-runner": "https://github.com/StoutLLC/grunt-protractor-runner", "grunt-injector": "^0.6.0", "grunt-karma": "~0.12.0", "grunt-build-control": "^0.6.0",<% if(filters.sass) { %> From a0920af0c087b97842e919d3b0a4b67e205223c0 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Thu, 19 Nov 2015 21:10:10 -0500 Subject: [PATCH 0314/1357] fix(e2e): properly use some promises in e2e tests --- app/templates/e2e/account(auth)/login/login.po.js | 2 +- app/templates/e2e/account(auth)/login/login.spec(mocha).js | 3 ++- app/templates/e2e/account(auth)/logout/logout.spec(mocha).js | 3 ++- app/templates/e2e/account(auth)/signup/signup.po.js | 2 +- app/templates/e2e/account(auth)/signup/signup.spec(mocha).js | 3 ++- app/templates/e2e/main/main.spec(mocha).js | 3 ++- 6 files changed, 10 insertions(+), 6 deletions(-) diff --git a/app/templates/e2e/account(auth)/login/login.po.js b/app/templates/e2e/account(auth)/login/login.po.js index 045204754..67005af2d 100644 --- a/app/templates/e2e/account(auth)/login/login.po.js +++ b/app/templates/e2e/account(auth)/login/login.po.js @@ -20,7 +20,7 @@ var LoginPage = function() { } } - form.submit.click(); + return form.submit.click(); }; }; diff --git a/app/templates/e2e/account(auth)/login/login.spec(mocha).js b/app/templates/e2e/account(auth)/login/login.spec(mocha).js index 1fefea5d0..7316f6314 100644 --- a/app/templates/e2e/account(auth)/login/login.spec(mocha).js +++ b/app/templates/e2e/account(auth)/login/login.spec(mocha).js @@ -8,8 +8,9 @@ describe('Login View', function() { var page; var loadPage = function() { - browser.get(config.baseUrl + '/login'); + let promise = browser.get(config.baseUrl + '/login'); page = require('./login.po'); + return promise; }; var testUser = { diff --git a/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js b/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js index 0006306e0..7138149ac 100644 --- a/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js +++ b/app/templates/e2e/account(auth)/logout/logout.spec(mocha).js @@ -6,8 +6,9 @@ var UserModel = require(config.serverConfig.root + '/server/sqldb').User;<% } %> describe('Logout View', function() { var login = function(user) { - browser.get(config.baseUrl + '/login'); + let promise = browser.get(config.baseUrl + '/login'); require('../login/login.po').login(user); + return promise; }; var testUser = { diff --git a/app/templates/e2e/account(auth)/signup/signup.po.js b/app/templates/e2e/account(auth)/signup/signup.po.js index 3a812266c..39108177c 100644 --- a/app/templates/e2e/account(auth)/signup/signup.po.js +++ b/app/templates/e2e/account(auth)/signup/signup.po.js @@ -22,7 +22,7 @@ var SignupPage = function() { } } - form.submit.click(); + return form.submit.click(); }; }; diff --git a/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js b/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js index 7578d2796..a45fdb3c3 100644 --- a/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js +++ b/app/templates/e2e/account(auth)/signup/signup.spec(mocha).js @@ -9,8 +9,9 @@ describe('Signup View', function() { var loadPage = function() { browser.manage().deleteAllCookies() - browser.get(config.baseUrl + '/signup'); + let promise = browser.get(config.baseUrl + '/signup'); page = require('./signup.po'); + return promise; }; var testUser = { diff --git a/app/templates/e2e/main/main.spec(mocha).js b/app/templates/e2e/main/main.spec(mocha).js index d497443cd..798b58c41 100644 --- a/app/templates/e2e/main/main.spec(mocha).js +++ b/app/templates/e2e/main/main.spec(mocha).js @@ -6,8 +6,9 @@ describe('Main View', function() { var page; beforeEach(function() { - browser.get(config.baseUrl + '/'); + let promise = browser.get(config.baseUrl + '/'); page = require('./main.po'); + return promise; }); it('should include jumbotron with correct data', function() { From 3ae64d7f1fbeb0db4ba140e567c6670db80a57fe Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Thu, 19 Nov 2015 21:32:16 -0500 Subject: [PATCH 0315/1357] fix(jscs): exclude generated 'app.constant.js' --- app/templates/.jscsrc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/templates/.jscsrc b/app/templates/.jscsrc index 76b4a9aaa..8923ad53e 100644 --- a/app/templates/.jscsrc +++ b/app/templates/.jscsrc @@ -1,4 +1,7 @@ { + "excludeFiles": [ + "client/app/app.constant.js" + ], "esnext": true, "maximumLineLength": { "value": 100, From 898f9213744b3bd6904e3c87aa6d61ba8b7ae3a5 Mon Sep 17 00:00:00 2001 From: Varayut Lerdkanlayanawat Date: Sat, 28 Nov 2015 23:15:41 +0700 Subject: [PATCH 0316/1357] chore(npm): grunt-contrib-imagemin ^0.9.4 -> 1.0.0 update grunt-contrib-imagemin version to fix the error when using npm install with Node v4.2.2 Closes #1412 --- app/templates/_package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 217df92ab..a68e1fd6b 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -45,7 +45,7 @@ "grunt-contrib-concat": "^0.5.1", "grunt-contrib-copy": "^0.8.0", "grunt-contrib-cssmin": "^0.14.0", - "grunt-contrib-imagemin": "^0.9.4", + "grunt-contrib-imagemin": "~1.0.0", "grunt-contrib-jshint": "~0.11.2", "grunt-contrib-uglify": "^0.9.1", "grunt-contrib-watch": "~0.6.1",<% if (filters.jade) { %> From 586f3ee6e84cb4d737e26e42cf89be85ee04cd42 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Thu, 10 Sep 2015 21:40:03 -0400 Subject: [PATCH 0317/1357] chore(gen): remove prerelease note --- app/generator.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/app/generator.js b/app/generator.js index 67a00bfe5..64db0c1a5 100644 --- a/app/generator.js +++ b/app/generator.js @@ -38,13 +38,6 @@ export default class Generator extends Base { }, info: function () { - this.log(chalk.red(` -################################################################ -# NOTE: You are using a pre-release version of -# generator-angular-fullstack. For a more stable version, run -# \`npm install -g generator-angular-fullstack@^2.0.0\` -################################################################`)); - this.log('You\'re using the Angular Full-Stack Generator, version ' + this.rootGeneratorVersion()); this.log(this.yoWelcome); this.log('Out of the box I create an AngularJS app with an Express server.\n'); }, From 426810707772525d4056a4990cbac19f50c7b3e3 Mon Sep 17 00:00:00 2001 From: kingcody Date: Tue, 8 Sep 2015 21:47:57 -0400 Subject: [PATCH 0318/1357] chore(gen): remove pre-`3.0.0` release code and docs [ci skip] --- Gruntfile.js | 1 - contributing.md | 10 ++-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 64e407a11..675c166bb 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -40,7 +40,6 @@ module.exports = function (grunt) { }, release: { options: { - bump: false, // remove after 3.0.0 release commitMessage: '<%= version %>', tagName: '<%= version %>', file: 'package.json', diff --git a/contributing.md b/contributing.md index 037a6b78f..bfcd7bb98 100644 --- a/contributing.md +++ b/contributing.md @@ -74,15 +74,9 @@ A detailed explanation can be found in this [document][commit-message-format]. # Releasing *(for contributors with push access)* -The `grunt release` task will do most of the work for you, see [`grunt-release`](https://github.com/geddski/grunt-release) for semver usage. +The `grunt release` task will do most of the work for you, see [`grunt-release`](https://github.com/geddski/grunt-release#using-grunt-release) for valid release targets. -* Manually bump `package.json` version. - -*note: this step will be removed once `3.0.0` is released* - -* Run the release task `grunt release`. - -*note: once `3.0.0` is released you will need to use a valid `grunt-release` target, see [here](https://github.com/geddski/grunt-release#using-grunt-release)* +* Run the release task `grunt release:RELEASE_TARGET`. * Push and publish the `angular-fullstack-deps` submodule. ```bash From 33cb0496d952b5cdcb8f7059644633e8dc6d999c Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 2 Dec 2015 10:45:20 -0500 Subject: [PATCH 0319/1357] docs(changelog): 3.0.0 --- CHANGELOG.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b47eb6f1..20e4aed18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,25 @@ + +# [3.0.0](https://github.com/DaftMonk/generator-angular-fullstack/compare/2.1.1...3.0.0) (2015-12-06) + +# 3.0.0 + +### New Features + + * **Sequelize** - You can now choose between MongoDB + Mongoose or SQLite3 + Sequelize + * **Babel** - We now include Babel transpiler support, with plans to add TypeScript in the future + * **Lusca** - Lusca Security Middleware is included by default + * **Angular Modules** - A few components of the front-end have been broken out into their own Angular modules, such as `auth`, `admin`, and a new `util` module + * **Modern Angular Best-Practices** - We have moved a lot of the code to take advantage of the `controllerAs` syntax, as well as ES6/ES7 Classes + * Mongoose Bluebird Promises + +### Breaking Changes + + * **Node >= 4.2.2** - We now support versions of Node 4.2.2 and up. Since this is a generator for scaffolding out a new project, it makes sense to move support to the 4.2.2 Long Term Support (LTS) version of Node, since it is the most supported release by Node. It is likely that the generator will work with earlier versions of Node, but it is not recommended. + * **~~CoffeeScript~~, ~~Vanilla JS~~** - Removed CoffeeScript and vanilla JS support. CoffeeScript has served its purpose and been replaced by much better transpilers. Vanilla JS doesn't provide a lot of the features that enable good, modern code. We now only support Babel 5.8.x, and plan to add TypeScript support in the future. + * Removed some backwards-compatibility support code + +To see the full list of changes, click the '3.0.0' title to view the GitHub compare between 3.0.0 and 2.1.1 + ## [2.1.1](https://github.com/DaftMonk/generator-angular-fullstack/compare/2.1.0...2.1.1) (2015-07-29) From 40d1d55a895773664e60b63b97deee794015f560 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Tue, 1 Dec 2015 12:10:45 -0500 Subject: [PATCH 0320/1357] chore(npm): bump some out-of-date gen and template dependencies --- app/templates/_package.json | 16 ++++++++-------- package.json | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/templates/_package.json b/app/templates/_package.json index 8c3af0cd8..335ad9df4 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -21,7 +21,7 @@ "bluebird": "^2.9.34", "connect-mongo": "^0.8.1",<% } %><% if (filters.sequelize) { %> "sequelize": "^3.5.1", - "sqlite3": "~3.1.0", + "sqlite3": "~3.1.1", "express-sequelize-session": "0.4.0",<% } %><% if (filters.auth) { %> "jsonwebtoken": "^5.0.0", "express-jwt": "^3.0.0", @@ -41,13 +41,13 @@ "grunt": "~0.4.5", "grunt-wiredep": "^2.0.0", "grunt-concurrent": "^2.0.1", - "grunt-contrib-clean": "^0.6.0", + "grunt-contrib-clean": "~0.7.0", "grunt-contrib-concat": "^0.5.1", "grunt-contrib-copy": "^0.8.0", - "grunt-contrib-cssmin": "^0.14.0", + "grunt-contrib-cssmin": "~0.14.0", "grunt-contrib-imagemin": "~1.0.0", "grunt-contrib-jshint": "~0.11.2", - "grunt-contrib-uglify": "^0.9.1", + "grunt-contrib-uglify": "~0.11.0", "grunt-contrib-watch": "~0.6.1",<% if (filters.jade) { %> "grunt-contrib-jade": "^0.15.0", "karma-ng-jade2js-preprocessor": "^0.2.0",<% } %><% if (filters.less) { %> @@ -75,15 +75,15 @@ "jit-grunt": "^0.9.1", "time-grunt": "^1.2.1", "grunt-express-server": "^0.5.1", - "grunt-postcss": "^0.6.0", + "grunt-postcss": "~0.7.1", "grunt-open": "~0.2.3", "open": "~0.0.4", - "jshint-stylish": "~2.0.1", + "jshint-stylish": "~2.1.0", "connect-livereload": "^0.5.3", "mocha": "^2.2.5", "grunt-mocha-test": "~0.12.7", "grunt-mocha-istanbul": "^3.0.1", - "istanbul": "^0.3.17", + "istanbul": "~0.4.1", "chai": "^3.2.0", "sinon": "^1.16.1", "chai-as-promised": "^5.1.0", @@ -105,7 +105,7 @@ "phantomjs": "^1.9.18", "karma-phantomjs-launcher": "~0.2.0", "karma": "~0.13.3", - "karma-ng-html2js-preprocessor": "~0.1.2", + "karma-ng-html2js-preprocessor": "~0.2.0", "karma-spec-reporter": "~0.0.20", "proxyquire": "^1.0.1", "supertest": "^1.1.0" diff --git a/package.json b/package.json index caad04a6b..3453adaad 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "babel-core": "^5.8.23", "chalk": "^1.1.0", "generator-ng-component": "~0.1.1", - "glob": "^5.0.14", + "glob": "^6.0.1", "lodash": "^3.10.1", "underscore.string": "^3.1.1", "yeoman-generator": "~0.20.3", @@ -47,10 +47,10 @@ "chai": "^3.2.0", "grunt": "~0.4.1", "grunt-build-control": "^0.6.0", - "grunt-contrib-clean": "^0.6.0", + "grunt-contrib-clean": "^0.7.0", "grunt-contrib-jshint": "^0.11.2", "grunt-conventional-changelog": "^4.1.0", - "grunt-david": "~0.5.0", + "grunt-david": "~0.7.0", "grunt-env": "^0.4.1", "grunt-mocha-test": "^0.12.7", "grunt-release": "^0.13.0", From 519fd36309cd5bfcd831d14e7af9da0149fab903 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 14 Oct 2015 14:49:23 -0400 Subject: [PATCH 0321/1357] feat(): add optional es7.classProperties transformer to Babel --- app/templates/Gruntfile.js | 5 ++++- app/templates/karma.conf.js | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 1c3ad2bfc..aa62e5c13 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -589,7 +589,10 @@ module.exports = function (grunt) { // Compiles ES6 to JavaScript using Babel babel: { options: { - sourceMap: true + sourceMap: true, + optional: [ + 'es7.classProperties' + ] },<% if(filters.babel) { %> client: { files: [{ diff --git a/app/templates/karma.conf.js b/app/templates/karma.conf.js index f85a28f71..771749d4b 100644 --- a/app/templates/karma.conf.js +++ b/app/templates/karma.conf.js @@ -43,7 +43,10 @@ module.exports = function(config) { babelPreprocessor: { options: { - sourceMap: 'inline' + sourceMap: 'inline', + optional: [ + 'es7.classProperties' + ] }, filename: function (file) { return file.originalPath.replace(/\.js$/, '.es5.js'); From 326c69b57c665b0e0e1e6cfe28d59a1eb6de1df6 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 14 Oct 2015 18:13:20 -0400 Subject: [PATCH 0322/1357] refactor(client:account): use controller as and classes --- .../client/app/account(auth)/account.js | 18 +++-- .../app/account(auth)/login/login(html).html | 12 +-- .../app/account(auth)/login/login(jade).jade | 10 +-- .../account(auth)/login/login.controller.js | 50 +++++++----- .../settings/settings(html).html | 18 ++--- .../settings/settings(jade).jade | 18 ++--- .../settings/settings.controller.js | 44 ++++++----- .../account(auth)/signup/signup(html).html | 42 +++++----- .../account(auth)/signup/signup(jade).jade | 43 +++++----- .../account(auth)/signup/signup.controller.js | 78 ++++++++++--------- .../e2e/account(auth)/login/login.po.js | 4 +- .../e2e/account(auth)/signup/signup.po.js | 8 +- 12 files changed, 188 insertions(+), 157 deletions(-) diff --git a/app/templates/client/app/account(auth)/account.js b/app/templates/client/app/account(auth)/account.js index d60fd72fe..4266116fa 100644 --- a/app/templates/client/app/account(auth)/account.js +++ b/app/templates/client/app/account(auth)/account.js @@ -5,7 +5,8 @@ angular.module('<%= scriptAppName %>') $routeProvider .when('/login', { templateUrl: 'app/account/login/login.html', - controller: 'LoginCtrl' + controller: 'LoginController', + controllerAs: 'vm' }) .when('/logout', { name: 'logout', @@ -21,11 +22,13 @@ angular.module('<%= scriptAppName %>') }) .when('/signup', { templateUrl: 'app/account/signup/signup.html', - controller: 'SignupCtrl' + controller: 'SignupController', + controllerAs: 'vm' }) .when('/settings', { templateUrl: 'app/account/settings/settings.html', - controller: 'SettingsCtrl', + controller: 'SettingsController', + controllerAs: 'vm', authenticate: true }); }) @@ -40,7 +43,8 @@ angular.module('<%= scriptAppName %>') .state('login', { url: '/login', templateUrl: 'app/account/login/login.html', - controller: 'LoginCtrl' + controller: 'LoginController', + controllerAs: 'vm' }) .state('logout', { url: '/logout?referrer', @@ -57,12 +61,14 @@ angular.module('<%= scriptAppName %>') .state('signup', { url: '/signup', templateUrl: 'app/account/signup/signup.html', - controller: 'SignupCtrl' + controller: 'SignupController', + controllerAs: 'vm' }) .state('settings', { url: '/settings', templateUrl: 'app/account/settings/settings.html', - controller: 'SettingsCtrl', + controller: 'SettingsController', + controllerAs: 'vm', authenticate: true }); }) diff --git a/app/templates/client/app/account(auth)/login/login(html).html b/app/templates/client/app/account(auth)/login/login(html).html index ab1346ba6..a01d29342 100644 --- a/app/templates/client/app/account(auth)/login/login(html).html +++ b/app/templates/client/app/account(auth)/login/login(html).html @@ -8,29 +8,29 @@

Login

Admin account is admin@example.com / admin

-
+
- +
- +
-

+

Please enter your email and password.

-

+

Please enter a valid email.

-

{{ errors.other }}

+

{{ vm.errors.other }}

diff --git a/app/templates/client/app/account(auth)/login/login(jade).jade b/app/templates/client/app/account(auth)/login/login(jade).jade index 2352e8fad..04936ec48 100644 --- a/app/templates/client/app/account(auth)/login/login(jade).jade +++ b/app/templates/client/app/account(auth)/login/login(jade).jade @@ -17,18 +17,18 @@ navbar code admin .col-sm-12 - form.form(name='form', ng-submit='login(form)', novalidate='') + form.form(name='form', ng-submit='vm.login(form)', novalidate='') .form-group label Email - input.form-control(type='email', name='email', ng-model='user.email') + input.form-control(type='email', name='email', ng-model='vm.user.email') .form-group label Password - input.form-control(type='password', name='password', ng-model='user.password') + input.form-control(type='password', name='password', ng-model='vm.user.password') .form-group.has-error - p.help-block(ng-show='form.email.$error.required && form.password.$error.required && submitted') + p.help-block(ng-show='form.email.$error.required && form.password.$error.required && vm.submitted') | Please enter your email and password. - p.help-block {{ errors.other }} + p.help-block {{ vm.errors.other }} div button.btn.btn-inverse.btn-lg.btn-login(type='submit') diff --git a/app/templates/client/app/account(auth)/login/login.controller.js b/app/templates/client/app/account(auth)/login/login.controller.js index 6e9d5fd7b..d98200fed 100644 --- a/app/templates/client/app/account(auth)/login/login.controller.js +++ b/app/templates/client/app/account(auth)/login/login.controller.js @@ -1,26 +1,34 @@ 'use strict'; -angular.module('<%= scriptAppName %>') - .controller('LoginCtrl', function($scope, Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %>) { - $scope.user = {}; - $scope.errors = {}; +class LoginController { + user = {}; + errors = {}; + submitted = false; + + constructor(Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %>) { + this.Auth = Auth;<% if (filters.ngroute) { %> + this.$location = $location;<% } if (filters.uirouter) { %> + this.$state = $state;<% } %> + } - $scope.login = function(form) { - $scope.submitted = true; + login(form) { + this.submitted = true; - if (form.$valid) { - Auth.login({ - email: $scope.user.email, - password: $scope.user.password - }) - .then(function() { - // Logged in, redirect to home - <% if (filters.ngroute) { %>$location.path('/');<% } %><% if (filters.uirouter) { %>$state.go('main');<% } %> - }) - .catch(function(err) { - $scope.errors.other = err.message; - }); - } - }; + if (form.$valid) { + this.Auth.login({ + email: this.user.email, + password: this.user.password + }) + .then(() => { + // Logged in, redirect to home + <% if (filters.ngroute) { %>this.$location.path('/');<% } %><% if (filters.uirouter) { %>this.$state.go('main');<% } %> + }) + .catch(err => { + this.errors.other = err.message; + }); + } + } +} - }); +angular.module('<%= scriptAppName %>') + .controller('LoginController', LoginController); diff --git a/app/templates/client/app/account(auth)/settings/settings(html).html b/app/templates/client/app/account(auth)/settings/settings(html).html index 92ee40aa4..d1d979a3c 100644 --- a/app/templates/client/app/account(auth)/settings/settings(html).html +++ b/app/templates/client/app/account(auth)/settings/settings(html).html @@ -6,26 +6,26 @@

Change Password

- +
-

- {{ errors.other }} + {{ vm.errors.other }}

-

+ ng-show="(form.newPassword.$error.minlength || form.newPassword.$error.required) && (form.newPassword.$dirty || vm.submitted)"> Password must be at least 3 characters.

@@ -33,18 +33,18 @@

Change Password

-

+ ng-show="form.confirmPassword.$error.match && vm.submitted"> Passwords must match.

-

{{ message }}

+

{{ vm.message }}

diff --git a/app/templates/client/app/account(auth)/settings/settings(jade).jade b/app/templates/client/app/account(auth)/settings/settings(jade).jade index 701215380..8fe47801e 100644 --- a/app/templates/client/app/account(auth)/settings/settings(jade).jade +++ b/app/templates/client/app/account(auth)/settings/settings(jade).jade @@ -4,33 +4,33 @@ navbar .col-sm-12 h1 Change Password .col-sm-12 - form.form(name='form', ng-submit='changePassword(form)', novalidate='') + form.form(name='form', ng-submit='vm.changePassword(form)', novalidate='') .form-group label Current Password input.form-control(type='password' name='password' - ng-model='user.oldPassword' + ng-model='vm.user.oldPassword' mongoose-error='') p.help-block(ng-show='form.password.$error.mongoose') - | {{ errors.other }} + | {{ vm.errors.other }} .form-group label New Password input.form-control(type='password' name='newPassword' - ng-model='user.newPassword' + ng-model='vm.user.newPassword' ng-minlength='3', required='') - p.help-block(ng-show='(form.newPassword.$error.minlength || form.newPassword.$error.required) && (form.newPassword.$dirty || submitted)') + p.help-block(ng-show='(form.newPassword.$error.minlength || form.newPassword.$error.required) && (form.newPassword.$dirty || vm.submitted)') | Password must be at least 3 characters. .form-group label Confirm New Password input.form-control(type='password' name='confirmPassword' - ng-model='user.confirmPassword' - match="user.newPassword" + ng-model='vm.user.confirmPassword' + match="vm.user.newPassword" ng-minlength='3', required='') - p.help-block(ng-show='form.confirmPassword.$error.match && submitted') + p.help-block(ng-show='fvm.orm.confirmPassword.$error.match && vm.submitted') | Passwords must match. - p.help-block {{ message }} + p.help-block {{ vm.message }} button.btn.btn-lg.btn-primary(type='submit') Save changes diff --git a/app/templates/client/app/account(auth)/settings/settings.controller.js b/app/templates/client/app/account(auth)/settings/settings.controller.js index eeb1219cf..58c89e0ff 100644 --- a/app/templates/client/app/account(auth)/settings/settings.controller.js +++ b/app/templates/client/app/account(auth)/settings/settings.controller.js @@ -1,21 +1,29 @@ 'use strict'; -angular.module('<%= scriptAppName %>') - .controller('SettingsCtrl', function($scope, User, Auth) { - $scope.errors = {}; +class SettingsController { + errors = {}; + submitted = false; + + constructor(Auth) { + this.Auth = Auth; + } + + changePassword(form) { + this.submitted = true; - $scope.changePassword = function(form) { - $scope.submitted = true; - if (form.$valid) { - Auth.changePassword($scope.user.oldPassword, $scope.user.newPassword) - .then(function() { - $scope.message = 'Password successfully changed.'; - }) - .catch(function() { - form.password.$setValidity('mongoose', false); - $scope.errors.other = 'Incorrect password'; - $scope.message = ''; - }); - } - }; - }); + if (form.$valid) { + this.Auth.changePassword(this.user.oldPassword, this.user.newPassword) + .then(() => { + this.message = 'Password successfully changed.'; + }) + .catch(() => { + form.password.$setValidity('mongoose', false); + this.errors.other = 'Incorrect password'; + this.message = ''; + }); + } + } +} + +angular.module('<%= scriptAppName %>') + .controller('SettingsController', SettingsController); diff --git a/app/templates/client/app/account(auth)/signup/signup(html).html b/app/templates/client/app/account(auth)/signup/signup(html).html index 84f4451e0..a23fe43a6 100644 --- a/app/templates/client/app/account(auth)/signup/signup(html).html +++ b/app/templates/client/app/account(auth)/signup/signup(html).html @@ -6,62 +6,62 @@

Sign up

-
+ -
+
- -

+

A name is required

-
+
- -

+

Doesn't look like a valid email.

-

+

What's your email address?

- {{ errors.email }} + {{ vm.errors.email }}

-
+
-

+ ng-show="(form.password.$error.minlength || form.password.$error.required) && vm.submitted"> Password must be at least 3 characters.

- {{ errors.password }} + {{ vm.errors.password }}

-
+
-

+ ng-show="form.confirmPassword.$error.match && vm.submitted"> Passwords must match.

diff --git a/app/templates/client/app/account(auth)/signup/signup(jade).jade b/app/templates/client/app/account(auth)/signup/signup(jade).jade index 139dd2941..1d9d547ff 100644 --- a/app/templates/client/app/account(auth)/signup/signup(jade).jade +++ b/app/templates/client/app/account(auth)/signup/signup(jade).jade @@ -4,47 +4,48 @@ navbar .col-sm-12 h1 Sign up .col-sm-12 - form.form(name='form', ng-submit='register(form)', novalidate='') - .form-group(ng-class='{ "has-success": form.name.$valid && submitted,\ - "has-error": form.name.$invalid && submitted }') + form.form(name='form', ng-submit='vm.register(form)', novalidate='') + .form-group(ng-class='{ "has-success": form.name.$valid && vm.submitted,\ + "has-error": form.name.$invalid && vm.submitted }') label Name - input.form-control(type='text', name='name', ng-model='user.name', required='') - p.help-block(ng-show='form.name.$error.required && submitted') + input.form-control(type='text', name='name', ng-model='vm.user.name', required='') + p.help-block(ng-show='form.name.$error.required && vm.submitted') | A name is required - .form-group(ng-class='{ "has-success": form.email.$valid && submitted,\ - "has-error": form.email.$invalid && submitted }') + .form-group(ng-class='{ "has-success": form.email.$valid && vm.submitted,\ + "has-error": form.email.$invalid && vm.submitted }') label Email - input.form-control(type='email', name='email', ng-model='user.email', required='', mongoose-error='') - p.help-block(ng-show='form.email.$error.email && submitted') + input.form-control(type='email', name='email', ng-model='vm.user.email', required='', mongoose-error='') + p.help-block(ng-show='form.email.$error.email && vm.submitted') | Doesn't look like a valid email. - p.help-block(ng-show='form.email.$error.required && submitted') + p.help-block(ng-show='form.email.$error.required && vm.submitted') | What's your email address? p.help-block(ng-show='form.email.$error.mongoose') - | {{ errors.email }} + | {{ vm.errors.email }} - .form-group(ng-class='{ "has-success": form.password.$valid && submitted,\ - "has-error": form.password.$invalid && submitted }') + .form-group(ng-class='{ "has-success": form.password.$valid && vm.submitted,\ + "has-error": form.password.$invalid && vm.submitted }') label Password input.form-control(type='password' name='password' - ng-model='user.password' + ng-model='vm.user.password' mongoose-error='' ng-minlength='3', required='') - p.help-block(ng-show='(form.password.$error.minlength || form.password.$error.required) && submitted') + + p.help-block(ng-show='(form.password.$error.minlength || form.password.$error.required) && vm.submitted') | Password must be at least 3 characters. p.help-block(ng-show='form.password.$error.mongoose') - | {{ errors.password }} + | {{ vm.errors.password }} - .form-group(ng-class='{ "has-success": form.confirmPassword.$valid && submitted,\ - "has-error": form.confirmPassword.$invalid && submitted }') + .form-group(ng-class='{ "has-success": form.confirmPassword.$valid && vm.submitted,\ + "has-error": form.confirmPassword.$invalid && vm.submitted }') label Confirm Password input.form-control(type='password' name='confirmPassword' - ng-model='user.confirmPassword' - match="user.password" + ng-model='vm.user.confirmPassword' + match="vm.user.password" ng-minlength='3', required='') - p.help-block(ng-show='form.confirmPassword.$error.match && submitted') + p.help-block(ng-show='form.confirmPassword.$error.match && vm.submitted') | Passwords must match. div diff --git a/app/templates/client/app/account(auth)/signup/signup.controller.js b/app/templates/client/app/account(auth)/signup/signup.controller.js index 405461a1f..3937ab4ac 100644 --- a/app/templates/client/app/account(auth)/signup/signup.controller.js +++ b/app/templates/client/app/account(auth)/signup/signup.controller.js @@ -1,42 +1,50 @@ 'use strict'; -angular.module('<%= scriptAppName %>') - .controller('SignupCtrl', function($scope, Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %>) { - $scope.user = {}; - $scope.errors = {}; +class SignupController { + user = {}; + errors = {}; + submitted = false; + + constructor(Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %>) { + this.Auth = Auth;<% if (filters.ngroute) { %> + this.$location = $location;<% } if (filters.uirouter) { %> + this.$state = $state;<% } %> + } - $scope.register = function(form) { - $scope.submitted = true; + register(form) { + this.submitted = true; - if (form.$valid) { - Auth.createUser({ - name: $scope.user.name, - email: $scope.user.email, - password: $scope.user.password - }) - .then(function() { - // Account created, redirect to home - <% if (filters.ngroute) { %>$location.path('/');<% } %><% if (filters.uirouter) { %>$state.go('main');<% } %> - }) - .catch(function(err) { - err = err.data; - $scope.errors = {}; + if (form.$valid) { + this.Auth.createUser({ + name: this.user.name, + email: this.user.email, + password: this.user.password + }) + .then(() => { + // Account created, redirect to home + <% if (filters.ngroute) { %>this.$location.path('/');<% } %><% if (filters.uirouter) { %>this.$state.go('main');<% } %> + }) + .catch(err => { + err = err.data; + this.errors = {}; <% if (filters.mongooseModels) { %> - // Update validity of form fields that match the mongoose errors - angular.forEach(err.errors, function(error, field) { + // Update validity of form fields that match the mongoose errors + angular.forEach(err.errors, (error, field) => { + form[field].$setValidity('mongoose', false); + this.errors[field] = error.message; + });<% } +if (filters.sequelizeModels) { %> + // Update validity of form fields that match the sequelize errors + if (err.name) { + angular.forEach(err.fields, field => { form[field].$setValidity('mongoose', false); - $scope.errors[field] = error.message; - });<% } - if (filters.sequelizeModels) { %> - // Update validity of form fields that match the sequelize errors - if (err.name) { - angular.forEach(err.fields, function(field) { - form[field].$setValidity('mongoose', false); - $scope.errors[field] = err.message; - }); - }<% } %> - }); - } - }; + this.errors[field] = err.message; + }); + }<% } %> + }); + } + } +} - }); +angular.module('<%= scriptAppName %>') + .controller('SignupController', SignupController); diff --git a/app/templates/e2e/account(auth)/login/login.po.js b/app/templates/e2e/account(auth)/login/login.po.js index 67005af2d..a9829c4cb 100644 --- a/app/templates/e2e/account(auth)/login/login.po.js +++ b/app/templates/e2e/account(auth)/login/login.po.js @@ -7,8 +7,8 @@ var LoginPage = function() { var form = this.form = element(by.css('.form')); - form.email = form.element(by.model('user.email')); - form.password = form.element(by.model('user.password')); + form.email = form.element(by.model('vm.user.email')); + form.password = form.element(by.model('vm.user.password')); form.submit = form.element(by.css('.btn-login'));<% if (filters.oauth) { %> form.oauthButtons = require('../../components/oauth-buttons/oauth-buttons.po').oauthButtons;<% } %> diff --git a/app/templates/e2e/account(auth)/signup/signup.po.js b/app/templates/e2e/account(auth)/signup/signup.po.js index 39108177c..aee1f4194 100644 --- a/app/templates/e2e/account(auth)/signup/signup.po.js +++ b/app/templates/e2e/account(auth)/signup/signup.po.js @@ -7,10 +7,10 @@ var SignupPage = function() { var form = this.form = element(by.css('.form')); - form.name = form.element(by.model('user.name')); - form.email = form.element(by.model('user.email')); - form.password = form.element(by.model('user.password')); - form.confirmPassword = form.element(by.model('user.confirmPassword')); + form.name = form.element(by.model('vm.user.name')); + form.email = form.element(by.model('vm.user.email')); + form.password = form.element(by.model('vm.user.password')); + form.confirmPassword = form.element(by.model('vm.user.confirmPassword')); form.submit = form.element(by.css('.btn-register'));<% if (filters.oauth) { %> form.oauthButtons = require('../../components/oauth-buttons/oauth-buttons.po').oauthButtons;<% } %> From f016415d047075ec70313df5d3a4b0ab3a77cb8c Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 14 Oct 2015 16:27:44 -0400 Subject: [PATCH 0323/1357] fix(jshint): add non-standard comments for JSHint, use them around class properties AFAIK we won't need this if we move to ESLint --- app/templates/client/.jshintrc | 3 +++ .../client/app/account(auth)/login/login.controller.js | 2 ++ .../client/app/account(auth)/settings/settings.controller.js | 2 ++ .../client/app/account(auth)/signup/signup.controller.js | 2 ++ 4 files changed, 9 insertions(+) diff --git a/app/templates/client/.jshintrc b/app/templates/client/.jshintrc index 07b9d3793..9d0d57476 100644 --- a/app/templates/client/.jshintrc +++ b/app/templates/client/.jshintrc @@ -16,6 +16,9 @@ "strict": true, "trailing": true, "smarttabs": true, + "ignoreDelimiters": [ + { "start": "start-non-standard", "end": "end-non-standard" } + ], "globals": { "jQuery": true, "angular": true, diff --git a/app/templates/client/app/account(auth)/login/login.controller.js b/app/templates/client/app/account(auth)/login/login.controller.js index d98200fed..2363aab8f 100644 --- a/app/templates/client/app/account(auth)/login/login.controller.js +++ b/app/templates/client/app/account(auth)/login/login.controller.js @@ -1,9 +1,11 @@ 'use strict'; class LoginController { + //start-non-standard user = {}; errors = {}; submitted = false; + //end-non-standard constructor(Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %>) { this.Auth = Auth;<% if (filters.ngroute) { %> diff --git a/app/templates/client/app/account(auth)/settings/settings.controller.js b/app/templates/client/app/account(auth)/settings/settings.controller.js index 58c89e0ff..379ccc506 100644 --- a/app/templates/client/app/account(auth)/settings/settings.controller.js +++ b/app/templates/client/app/account(auth)/settings/settings.controller.js @@ -1,8 +1,10 @@ 'use strict'; class SettingsController { + //start-non-standard errors = {}; submitted = false; + //end-non-standard constructor(Auth) { this.Auth = Auth; diff --git a/app/templates/client/app/account(auth)/signup/signup.controller.js b/app/templates/client/app/account(auth)/signup/signup.controller.js index 3937ab4ac..a6f83fb58 100644 --- a/app/templates/client/app/account(auth)/signup/signup.controller.js +++ b/app/templates/client/app/account(auth)/signup/signup.controller.js @@ -1,9 +1,11 @@ 'use strict'; class SignupController { + //start-non-standard user = {}; errors = {}; submitted = false; + //end-non-standard constructor(Auth<% if (filters.ngroute) { %>, $location<% } %><% if (filters.uirouter) { %>, $state<% } %>) { this.Auth = Auth;<% if (filters.ngroute) { %> From 02773df73ed1babce54e66d196e47b9574a84dc8 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Mon, 19 Oct 2015 15:29:58 -0400 Subject: [PATCH 0324/1357] refactor(navbar): controller as, ES7 class --- .../components/navbar/navbar(html).html | 20 +++++------ .../components/navbar/navbar(jade).jade | 22 ++++++------ .../components/navbar/navbar.controller.js | 36 +++++++++++-------- .../components/navbar/navbar.directive.js | 13 ++++--- 4 files changed, 49 insertions(+), 42 deletions(-) diff --git a/app/templates/client/components/navbar/navbar(html).html b/app/templates/client/components/navbar/navbar(html).html index eda46b07a..06bcff0c6 100644 --- a/app/templates/client/components/navbar/navbar(html).html +++ b/app/templates/client/components/navbar/navbar(html).html @@ -1,7 +1,7 @@ -