Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(gen): unify testing framework #585

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
language: node_js
node_js:
- '0.10'
- '0.11'
- '0.11.13'
env:
global:
- SAUCE_USERNAME=fullstack_ci
Expand Down
133 changes: 94 additions & 39 deletions app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 () {
Expand All @@ -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;
Expand Down Expand Up @@ -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',
Expand All @@ -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;
}
Expand All @@ -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));
},

Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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');
Expand Down Expand Up @@ -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() {
Expand Down
18 changes: 11 additions & 7 deletions app/templates/_package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand All @@ -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",
Expand All @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<% } %>
5 changes: 3 additions & 2 deletions app/templates/client/app/main/main.controller.spec(js).js
Original file line number Diff line number Diff line change
Expand Up @@ -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);<% } %>
});
});
73 changes: 73 additions & 0 deletions app/templates/e2e/account(auth)/login/login.spec(mocha).js
Original file line number Diff line number Diff line change
@@ -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: '[email protected]',
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.');
});

});

});
});
Loading