From e09fb76c3380c36e8378880703e9e5b95659ed6b Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 24 Apr 2016 00:02:15 -0400 Subject: [PATCH 01/53] feat(gen): also build test dir (just like generators dir) --- .gitignore | 8 ++--- gulpfile.js | 16 +++++++-- package.json | 1 + src/{ => generators}/app/USAGE | 0 src/{ => generators}/app/index.js | 0 src/{ => generators}/controller/index.js | 0 src/{ => generators}/decorator/index.js | 0 src/{ => generators}/directive/index.js | 0 src/{ => generators}/endpoint/index.js | 0 src/{ => generators}/factory/index.js | 0 src/{ => generators}/filter/index.js | 0 src/{ => generators}/generator-base.js | 0 src/{ => generators}/heroku/USAGE | 0 src/{ => generators}/heroku/index.js | 0 .../heroku/templates/Procfile | 0 src/{ => generators}/insight-init.js | 0 src/{ => generators}/openshift/USAGE | 0 src/{ => generators}/openshift/index.js | 0 .../openshift/templates/hot_deploy | 0 src/{ => generators}/provider/index.js | 0 src/{ => generators}/route/index.js | 0 src/{ => generators}/service/index.js | 0 src/{ => generators}/util.js | 0 src/test/fixtures/.bowerrc | 3 ++ src/test/fixtures/.yo-rc.json | 36 +++++++++++++++++++ {test => src/test}/test-file-creation.js | 0 26 files changed, 57 insertions(+), 7 deletions(-) rename src/{ => generators}/app/USAGE (100%) rename src/{ => generators}/app/index.js (100%) rename src/{ => generators}/controller/index.js (100%) rename src/{ => generators}/decorator/index.js (100%) rename src/{ => generators}/directive/index.js (100%) rename src/{ => generators}/endpoint/index.js (100%) rename src/{ => generators}/factory/index.js (100%) rename src/{ => generators}/filter/index.js (100%) rename src/{ => generators}/generator-base.js (100%) rename src/{ => generators}/heroku/USAGE (100%) rename src/{ => generators}/heroku/index.js (100%) rename src/{ => generators}/heroku/templates/Procfile (100%) rename src/{ => generators}/insight-init.js (100%) rename src/{ => generators}/openshift/USAGE (100%) rename src/{ => generators}/openshift/index.js (100%) rename src/{ => generators}/openshift/templates/hot_deploy (100%) rename src/{ => generators}/provider/index.js (100%) rename src/{ => generators}/route/index.js (100%) rename src/{ => generators}/service/index.js (100%) rename src/{ => generators}/util.js (100%) create mode 100644 src/test/fixtures/.bowerrc create mode 100644 src/test/fixtures/.yo-rc.json rename {test => src/test}/test-file-creation.js (100%) diff --git a/.gitignore b/.gitignore index f9b1763a8..230257f1f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,8 @@ node_modules bower_components -test/temp +/generators/* +/test/* demo .idea .DS_Store -release.txt -test/fixtures/bower.json -test/fixtures/package.json -generators \ No newline at end of file +release.txt \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 7aeb1de2c..2fa763455 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -6,15 +6,22 @@ var gulp = require('gulp'); var babel = require('gulp-babel'); var del = require('del'); var runSequence = require('run-sequence'); +var merge = require('merge-stream'); gulp.task('clean', () => { return del(['generators/**/*']); }); gulp.task('babel', () => { - return gulp.src(['src/**/*.js']) + let generators = gulp.src(['src/generators/**/*.js']) .pipe(babel()) .pipe(gulp.dest('generators')); + + let test = gulp.src(['src/test/**/*.js']) + .pipe(babel()) + .pipe(gulp.dest('test')); + + return merge(generators); }); gulp.task('watch', () => { @@ -22,8 +29,13 @@ gulp.task('watch', () => { }); gulp.task('copy', () => { - return gulp.src(['src/**/*', '!src/**/*.js']) + let nonJsGen = gulp.src(['src/generators/**/*', '!src/generators/**/*.js'], {dot: true}) .pipe(gulp.dest('generators')); + + let nonJsTest = gulp.src(['src/test/**/*', '!src/test/**/*.js'], {dot: true}) + .pipe(gulp.dest('test')); + + return merge(nonJsGen, nonJsTest); }); gulp.task('build', cb => { diff --git a/package.json b/package.json index 7cc2759bf..a6f769767 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "grunt-release": "^0.13.0", "gulp": "^3.9.1", "jit-grunt": "~0.10.0", + "merge-stream": "^1.0.0", "mocha": "^2.2.5", "q": "^1.0.1", "recursive-readdir": "^2.0.0", diff --git a/src/app/USAGE b/src/generators/app/USAGE similarity index 100% rename from src/app/USAGE rename to src/generators/app/USAGE diff --git a/src/app/index.js b/src/generators/app/index.js similarity index 100% rename from src/app/index.js rename to src/generators/app/index.js diff --git a/src/controller/index.js b/src/generators/controller/index.js similarity index 100% rename from src/controller/index.js rename to src/generators/controller/index.js diff --git a/src/decorator/index.js b/src/generators/decorator/index.js similarity index 100% rename from src/decorator/index.js rename to src/generators/decorator/index.js diff --git a/src/directive/index.js b/src/generators/directive/index.js similarity index 100% rename from src/directive/index.js rename to src/generators/directive/index.js diff --git a/src/endpoint/index.js b/src/generators/endpoint/index.js similarity index 100% rename from src/endpoint/index.js rename to src/generators/endpoint/index.js diff --git a/src/factory/index.js b/src/generators/factory/index.js similarity index 100% rename from src/factory/index.js rename to src/generators/factory/index.js diff --git a/src/filter/index.js b/src/generators/filter/index.js similarity index 100% rename from src/filter/index.js rename to src/generators/filter/index.js diff --git a/src/generator-base.js b/src/generators/generator-base.js similarity index 100% rename from src/generator-base.js rename to src/generators/generator-base.js diff --git a/src/heroku/USAGE b/src/generators/heroku/USAGE similarity index 100% rename from src/heroku/USAGE rename to src/generators/heroku/USAGE diff --git a/src/heroku/index.js b/src/generators/heroku/index.js similarity index 100% rename from src/heroku/index.js rename to src/generators/heroku/index.js diff --git a/src/heroku/templates/Procfile b/src/generators/heroku/templates/Procfile similarity index 100% rename from src/heroku/templates/Procfile rename to src/generators/heroku/templates/Procfile diff --git a/src/insight-init.js b/src/generators/insight-init.js similarity index 100% rename from src/insight-init.js rename to src/generators/insight-init.js diff --git a/src/openshift/USAGE b/src/generators/openshift/USAGE similarity index 100% rename from src/openshift/USAGE rename to src/generators/openshift/USAGE diff --git a/src/openshift/index.js b/src/generators/openshift/index.js similarity index 100% rename from src/openshift/index.js rename to src/generators/openshift/index.js diff --git a/src/openshift/templates/hot_deploy b/src/generators/openshift/templates/hot_deploy similarity index 100% rename from src/openshift/templates/hot_deploy rename to src/generators/openshift/templates/hot_deploy diff --git a/src/provider/index.js b/src/generators/provider/index.js similarity index 100% rename from src/provider/index.js rename to src/generators/provider/index.js diff --git a/src/route/index.js b/src/generators/route/index.js similarity index 100% rename from src/route/index.js rename to src/generators/route/index.js diff --git a/src/service/index.js b/src/generators/service/index.js similarity index 100% rename from src/service/index.js rename to src/generators/service/index.js diff --git a/src/util.js b/src/generators/util.js similarity index 100% rename from src/util.js rename to src/generators/util.js diff --git a/src/test/fixtures/.bowerrc b/src/test/fixtures/.bowerrc new file mode 100644 index 000000000..69fad3580 --- /dev/null +++ b/src/test/fixtures/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory": "bower_components" +} diff --git a/src/test/fixtures/.yo-rc.json b/src/test/fixtures/.yo-rc.json new file mode 100644 index 000000000..716e42b6c --- /dev/null +++ b/src/test/fixtures/.yo-rc.json @@ -0,0 +1,36 @@ +{ + "generator-angular-fullstack": { + "endpointDirectory": "server/api/", + "insertRoutes": true, + "registerRoutesFile": "server/routes.js", + "routesNeedle": "// Insert routes below", + "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": { + "babel": true, + "html": true, + "less": true, + "uirouter": true, + "bootstrap": false, + "uibootstrap": false, + "socketio": true, + "auth": true, + "models": true, + "mongooseModels": true, + "mongoose": true, + "oauth": true, + "googleAuth": true, + "grunt": true, + "mocha": true, + "jasmine": false, + "should": true, + "expect": false + } + } +} diff --git a/test/test-file-creation.js b/src/test/test-file-creation.js similarity index 100% rename from test/test-file-creation.js rename to src/test/test-file-creation.js From f852113cb88f959412d60e4a437d5647c1baa669 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 24 Apr 2016 01:20:09 -0400 Subject: [PATCH 02/53] fix(gen:gulp:watch): use plumber when watching --- gulpfile.js | 7 +++++++ package.json | 2 ++ 2 files changed, 9 insertions(+) diff --git a/gulpfile.js b/gulpfile.js index 2fa763455..e10855420 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -4,6 +4,8 @@ var path = require('path'); var Promise = require('bluebird'); var gulp = require('gulp'); var babel = require('gulp-babel'); +var plumber = require('gulp-plumber'); +var gulpIf = require('gulp-if'); var del = require('del'); var runSequence = require('run-sequence'); var merge = require('merge-stream'); @@ -12,12 +14,16 @@ gulp.task('clean', () => { return del(['generators/**/*']); }); +var watching = false; + gulp.task('babel', () => { let generators = gulp.src(['src/generators/**/*.js']) + .pipe(gulpIf(watching, plumber())) .pipe(babel()) .pipe(gulp.dest('generators')); let test = gulp.src(['src/test/**/*.js']) + .pipe(gulpIf(watching, plumber())) .pipe(babel()) .pipe(gulp.dest('test')); @@ -25,6 +31,7 @@ gulp.task('babel', () => { }); gulp.task('watch', () => { + watching = true; return gulp.watch('src/**/*.js', ['babel']); }); diff --git a/package.json b/package.json index a6f769767..c35fe4c42 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,8 @@ "grunt-mocha-test": "^0.12.7", "grunt-release": "^0.13.0", "gulp": "^3.9.1", + "gulp-if": "^2.0.0", + "gulp-plumber": "^1.1.0", "jit-grunt": "~0.10.0", "merge-stream": "^1.0.0", "mocha": "^2.2.5", From 6398160cfcdb16b62af8c17782656833ac96b5b5 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 24 Apr 2016 01:22:59 -0400 Subject: [PATCH 03/53] refactor(gen:test): promisify `fs`, use the promises --- src/test/test-file-creation.js | 70 ++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/src/test/test-file-creation.js b/src/test/test-file-creation.js index 5c4c29e5d..4d0d97882 100644 --- a/src/test/test-file-creation.js +++ b/src/test/test-file-creation.js @@ -1,7 +1,9 @@ /*global describe, beforeEach, it */ 'use strict'; var path = require('path'); +var Promise = require('bluebird'); var fs = require('fs'); +Promise.promisifyAll(fs); var exec = require('child_process').exec; var helpers = require('yeoman-test'); var assert = require('yeoman-assert'); @@ -9,8 +11,18 @@ var chai = require('chai'); var expect = chai.expect; var recursiveReadDir = require('recursive-readdir'); +/**************** + * FileSystem Utils + ****************/ + +function copyAsync(src, dest) { + return fs.readFileAsync(src) + .then(data => fs.writeFileAsync(data, dest)); +} + describe('angular-fullstack generator', function () { - var gen, defaultOptions = { + var gen; + var defaultOptions = { buildtool: 'grunt', script: 'js', transpiler: 'babel', @@ -21,13 +33,12 @@ describe('angular-fullstack generator', function () { chai: 'expect', bootstrap: true, uibootstrap: true, - odms: [ 'mongoose' ], + odms: ['mongoose'], auth: true, oauth: [], socketio: true - }, dependenciesInstalled = false; - - function copySync(s, d) { fs.writeFileSync(d, fs.readFileSync(s)); } + }; + var dependenciesInstalled = false; function generatorTest(generatorType, name, mockPrompt, callback) { gen.run(function () { @@ -411,9 +422,11 @@ describe('angular-fullstack generator', function () { beforeEach(function() { this.timeout(20000); - fs.mkdirSync(__dirname + '/temp/client'); - fs.symlinkSync(__dirname + '/fixtures/node_modules', __dirname + '/temp/node_modules'); - fs.symlinkSync(__dirname +'/fixtures/bower_components', __dirname +'/temp/client/bower_components'); + return Promise.all([ + fs.mkdirAsync(__dirname + '/temp/client'), + fs.symlinkAsync(__dirname + '/fixtures/node_modules', __dirname + '/temp/node_modules'), + fs.symlinkAsync(__dirname +'/fixtures/bower_components', __dirname +'/temp/client/bower_components') + ]); }); describe('with default options', function() { @@ -482,26 +495,27 @@ describe('angular-fullstack generator', function () { it('should use existing config if available', function(done) { this.timeout(60000); - copySync(__dirname + '/fixtures/.yo-rc.json', __dirname + '/temp/.yo-rc.json'); - var gen = helpers.createGenerator('angular-fullstack:app', [ - '../../generators/app', - '../../generators/endpoint', - [ - helpers.createDummyGenerator(), - 'ng-component:app' - ] - ], [], { - skipInstall: true - }); - helpers.mockPrompt(gen, { - skipConfig: true - }); - gen.run(function () { - assert.file([ - 'client/app/main/main.less', - 'server/auth/google/passport.js' - ]); - done(); + return copyAsync(__dirname + '/fixtures/.yo-rc.json', __dirname + '/temp/.yo-rc.json').then(() => { + var gen = helpers.createGenerator('angular-fullstack:app', [ + '../../generators/app', + '../../generators/endpoint', + [ + helpers.createDummyGenerator(), + 'ng-component:app' + ] + ], [], { + skipInstall: true + }); + helpers.mockPrompt(gen, { + skipConfig: true + }); + gen.run(function () { + assert.file([ + 'client/app/main/main.less', + 'server/auth/google/passport.js' + ]); + done(); + }); }); }); From 8f5c120fd9e4ca182fbff8e9d2c7df76ff262fa0 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 24 Apr 2016 01:38:03 -0400 Subject: [PATCH 04/53] fix(gen:test): fix copyAsync --- src/test/test-file-creation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/test-file-creation.js b/src/test/test-file-creation.js index 4d0d97882..200e49852 100644 --- a/src/test/test-file-creation.js +++ b/src/test/test-file-creation.js @@ -17,7 +17,7 @@ var recursiveReadDir = require('recursive-readdir'); function copyAsync(src, dest) { return fs.readFileAsync(src) - .then(data => fs.writeFileAsync(data, dest)); + .then(data => fs.writeFileAsync(dest, data)); } describe('angular-fullstack generator', function () { From 27806c564e3fd64859e5bb779b45f8f1cd9191e8 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 24 Apr 2016 04:28:17 -0400 Subject: [PATCH 05/53] refactor(gen:gulp): use lazypipe --- gulpfile.js | 15 +++++++++------ package.json | 1 + 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index e10855420..f6d5e244a 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -7,24 +7,27 @@ var babel = require('gulp-babel'); var plumber = require('gulp-plumber'); var gulpIf = require('gulp-if'); var del = require('del'); +var lazypipe = require('lazypipe'); var runSequence = require('run-sequence'); var merge = require('merge-stream'); +var watching = false; + +const transpile = lazypipe() + .pipe(() => gulpIf(watching, plumber())) + .pipe(babel); + gulp.task('clean', () => { return del(['generators/**/*']); }); -var watching = false; - gulp.task('babel', () => { let generators = gulp.src(['src/generators/**/*.js']) - .pipe(gulpIf(watching, plumber())) - .pipe(babel()) + .pipe(transpile()) .pipe(gulp.dest('generators')); let test = gulp.src(['src/test/**/*.js']) - .pipe(gulpIf(watching, plumber())) - .pipe(babel()) + .pipe(transpile()) .pipe(gulp.dest('test')); return merge(generators); diff --git a/package.json b/package.json index c35fe4c42..28d95ad7d 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "gulp-if": "^2.0.0", "gulp-plumber": "^1.1.0", "jit-grunt": "~0.10.0", + "lazypipe": "^1.0.1", "merge-stream": "^1.0.0", "mocha": "^2.2.5", "q": "^1.0.1", From 3748953ba08d2821a16df522b01ed4d6ff15b8bf Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 24 Apr 2016 04:28:54 -0400 Subject: [PATCH 06/53] fix(gen:gulp:babel): return the two merged streams --- gulpfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gulpfile.js b/gulpfile.js index f6d5e244a..a625a1f0a 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -30,7 +30,7 @@ gulp.task('babel', () => { .pipe(transpile()) .pipe(gulp.dest('test')); - return merge(generators); + return merge(generators, test); }); gulp.task('watch', () => { From ead201a24b993e8e017a9d4988c1c6705fdc41de Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 24 Apr 2016 04:29:20 -0400 Subject: [PATCH 07/53] feat(gen:gulp): add mocha --- gulpfile.js | 15 +++++++++++++++ package.json | 2 ++ 2 files changed, 17 insertions(+) diff --git a/gulpfile.js b/gulpfile.js index a625a1f0a..257025cf3 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -4,6 +4,7 @@ var path = require('path'); var Promise = require('bluebird'); var gulp = require('gulp'); var babel = require('gulp-babel'); +var gulpMocha = require('gulp-mocha'); var plumber = require('gulp-plumber'); var gulpIf = require('gulp-if'); var del = require('del'); @@ -13,6 +14,15 @@ var merge = require('merge-stream'); var watching = false; +const mocha = lazypipe() + .pipe(gulpMocha, { + reporter: 'spec', + timeout: 120000, + globals: { + should: require('should') + } + }); + const transpile = lazypipe() .pipe(() => gulpIf(watching, plumber())) .pipe(babel); @@ -103,3 +113,8 @@ gulp.task('updateFixtures:test', () => { gulp.task('updateFixtures:deps', () => { return updateFixtures('deps'); }); + +gulp.task('test', () => { + return gulp.src('test/*.test.js') + .pipe(mocha()) +}); diff --git a/package.json b/package.json index 28d95ad7d..f961d8549 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "grunt-release": "^0.13.0", "gulp": "^3.9.1", "gulp-if": "^2.0.0", + "gulp-mocha": "^2.2.0", "gulp-plumber": "^1.1.0", "jit-grunt": "~0.10.0", "lazypipe": "^1.0.1", @@ -77,6 +78,7 @@ "recursive-readdir": "^2.0.0", "run-sequence": "^1.1.5", "shelljs": "^0.6.0", + "should": "^8.3.1", "yeoman-assert": "^2.0.0", "yeoman-test": "^1.1.0" }, From 316e93f2897216b8fbc50fd3b920292087b1601c Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Mon, 25 Apr 2016 11:25:57 -0400 Subject: [PATCH 08/53] feat(gen:tests): step 1 of new test structure --- src/test/get-expected-files.js | 237 ++++++++++++++++++ src/test/main.test.js | 96 +++++++ ...test-file-creation.js => main.test.off.js} | 37 ++- 3 files changed, 348 insertions(+), 22 deletions(-) create mode 100644 src/test/get-expected-files.js create mode 100644 src/test/main.test.js rename src/test/{test-file-creation.js => main.test.off.js} (96%) diff --git a/src/test/get-expected-files.js b/src/test/get-expected-files.js new file mode 100644 index 000000000..6a435b3dd --- /dev/null +++ b/src/test/get-expected-files.js @@ -0,0 +1,237 @@ +/** + * Generate an array of files to expect from a set of options + * + * @param {Object} options - generator options + * @return {Array} - array of files + * + */ +export function app(options) { + var mapping = { + stylesheet: { + sass: 'scss', + stylus: 'styl', + less: 'less', + css: 'css' + }, + markup: { + jade: 'jade', + html: 'html' + }, + script: { + js: 'js', + ts: 'ts' + } + }, + 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', + 'server/auth/' + type + '/passport.js', + ]; + }; + + + var script = mapping.script[options.transpiler === 'ts' ? 'ts' : 'js'], + markup = mapping.markup[options.markup], + stylesheet = mapping.stylesheet[options.stylesheet], + models = options.models ? options.models : options.odms[0]; + + /* Core Files */ + files = files.concat([ + 'client/.htaccess', + '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/footer/footer.' + stylesheet, + 'client/components/footer/footer.' + markup, + 'client/components/footer/footer.directive.' + script, + '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', + 'server/index.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.integration.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/config/environment/shared.js', + 'server/views/404.' + markup, + 'e2e/main/main.po.js', + 'e2e/main/main.spec.js', + 'e2e/components/navbar/navbar.po.js', + '.babelrc', + '.bowerrc', + '.buildignore', + '.editorconfig', + '.gitattributes', + '.gitignore', + '.travis.yml', + '.jscsrc', + '.yo-rc.json', + 'Gruntfile.js', + 'package.json', + 'bower.json', + 'karma.conf.js', + 'mocha.conf.js', + 'protractor.conf.js', + 'README.md' + ]); + + /* TypeScript */ + if (options.transpiler === 'ts') { + files = files.concat([ + 'tsconfig.client.test.json', + 'tsconfig.client.json', + 'tsd.json', + 'tsd_test.json', + 'client/tslint.json' + ]); + } else { + files = files.concat([ + 'client/.jshintrc' + ]); + } + + /* Ui-Router */ + if (options.router === 'uirouter') { + files = files.concat([ + 'client/components/ui-router/ui-router.mock.' + script + ]); + } + + /* Ui-Bootstrap */ + if (options.uibootstrap) { + files = files.concat([ + 'client/components/modal/modal.' + markup, + 'client/components/modal/modal.' + stylesheet, + 'client/components/modal/modal.service.' + script + ]); + } + + /* Models - Mongoose or Sequelize */ + if (models) { + files = files.concat([ + 'server/api/thing/thing.model.js', + 'server/api/thing/thing.events.js', + 'server/config/seed.js' + ]); + } + + /* Sequelize */ + if (options.odms.indexOf('sequelize') !== -1) { + files = files.concat([ + 'server/sqldb/index.js' + ]); + } + + /* Authentication */ + if (options.auth) { + files = files.concat([ + 'client/app/account/account.' + script, + 'client/app/account/login/login.' + markup, + '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.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, + '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', + 'server/api/user/index.spec.js', + 'server/api/user/user.controller.js', + 'server/api/user/user.integration.js', + 'server/api/user/user.model.js', + 'server/api/user/user.model.spec.js', + 'server/api/user/user.events.js', + 'server/auth/index.js', + 'server/auth/auth.service.js', + 'server/auth/local/index.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' + ]); + } + + if (options.oauth && options.oauth.length) { + /* OAuth (see oauthFiles function above) */ + options.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 */ + if (options.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; +} + +export function endpoint(name, options) { + return [ + `server/api/${name}/index.js`, + `server/api/${name}/index.spec.js`, + `server/api/${name}/bar.controller.js`, + `server/api/${name}/bar.events.js`, + `server/api/${name}/bar.integration.js`, + `server/api/${name}/bar.model.js`, + `server/api/${name}/bar.socket.js` + ]; +} diff --git a/src/test/main.test.js b/src/test/main.test.js new file mode 100644 index 000000000..deed2c25b --- /dev/null +++ b/src/test/main.test.js @@ -0,0 +1,96 @@ +'use strict'; +import path from 'path'; +import fs from 'fs'; +import Promise from 'bluebird'; +Promise.promisifyAll(fs); +import {exec} from 'child_process'; +import helpers from 'yeoman-test'; +import assert from 'yeoman-assert'; +import * as getExpectedFiles from './get-expected-files'; + +const defaultOptions = { + buildtool: 'grunt', + script: 'js', + transpiler: 'babel', + markup: 'html', + stylesheet: 'sass', + router: 'uirouter', + testing: 'mocha', + chai: 'expect', + bootstrap: true, + uibootstrap: true, + odms: ['mongoose'], + auth: true, + oauth: [], + socketio: true +}; +// var DEBUG = true; +var DEBUG = false; + +function runCmd(cmd, done) { + exec(cmd, {}, function(err, stdout, stderr) { + if(err) { + console.error(stdout); + throw new Error(`Error running command: ${cmd}`); + done(err); + } else { + if(DEBUG) console.log(stdout); + done(); + } + }); +} + +describe('angular-fullstack:app', function() { + beforeEach(function() { + this.gen = helpers + .run(require.resolve('../generators/app')) + .inTmpDir(function(dir) { + var done = this.async(); + if(DEBUG) console.log(`TEMP DIR: ${dir}`); + + return Promise.all([ + fs.mkdirAsync(dir + '/client').then(() => { + return fs.symlinkAsync(__dirname + '/fixtures/bower_components', dir + '/client/bower_components'); + }), + fs.symlinkAsync(__dirname + '/fixtures/node_modules', dir + '/node_modules') + ]).then(done); + }) + .withGenerators([ + require.resolve('../generators/endpoint'), + // [helpers.createDummyGenerator(), 'ng-component:app'] + ]) + .withOptions({ + skipInstall: true, + force: true + }) + // .withArguments(['upperCaseBug']) + .withPrompts(defaultOptions); + }); + + describe('default settings', function() { + beforeEach(function(done) { + this.gen.on('end', done); + }); + + it('generates the proper files', function(done) { + assert.file(getExpectedFiles.app(defaultOptions)); + done(); + }); + + it('passes JSCS', function(done) { + runCmd('grunt jscs', done); + }); + + it('passes JSHint', function(done) { + runCmd('grunt jshint', done); + }); + + it('passes client tests', function(done) { + runCmd('grunt test:client', done); + }); + + it('passes client tests', function(done) { + runCmd('grunt test:server', done); + }); + }); +}); \ No newline at end of file diff --git a/src/test/test-file-creation.js b/src/test/main.test.off.js similarity index 96% rename from src/test/test-file-creation.js rename to src/test/main.test.off.js index 200e49852..6f706cc70 100644 --- a/src/test/test-file-creation.js +++ b/src/test/main.test.off.js @@ -64,12 +64,13 @@ describe('angular-fullstack generator', function () { * @param {Array} skip - array of paths to skip/ignore (optional) * */ - function assertOnlyFiles(expectedFiles, done, topLevelPath, skip) { - topLevelPath = topLevelPath || './'; - skip = skip || ['node_modules', 'client/bower_components']; - + function assertOnlyFiles( + expectedFiles, + done, + topLevelPath='./', + skip=['node_modules', 'client/bower_components']) { recursiveReadDir(topLevelPath, skip, function(err, actualFiles) { - if (err) { return done(err); } + if (err) return done(err); var files = actualFiles.concat(); expectedFiles.forEach(function(file, i) { @@ -101,9 +102,9 @@ describe('angular-fullstack generator', function () { * */ 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; + var args = Array.prototype.slice.call(arguments); + var endpoint = (args[3] && typeof args[3] === 'string') ? args.splice(3, 1)[0] : null; + var timeout = (args[3] && typeof args[3] === 'number') ? args.splice(3, 1)[0] : null; self.timeout(timeout || 60000); @@ -370,31 +371,24 @@ describe('angular-fullstack generator', function () { ] ]; - helpers.testDirectory(path.join(__dirname, 'temp'), function (err) { - if (err) { - return done(err); - } + helpers.testDirectory(path.join(__dirname, 'temp'), err => { + if(err) return done(err); gen = helpers.createGenerator('angular-fullstack:app', deps, [], { skipInstall: true }); gen.conflicter.force = true; done(); - }.bind(this)); + }); }); describe('making sure test fixtures are present', function() { - it('should have package.json in fixtures', function() { - assert.file([ - path.join(__dirname, 'fixtures', 'package.json') - ]); + assert.file([path.join(__dirname, 'fixtures', 'package.json')]); }); it('should have bower.json in fixtures', function() { - assert.file([ - path.join(__dirname, 'fixtures', 'bower.json') - ]); + assert.file([path.join(__dirname, 'fixtures', 'bower.json')]); }); it('should have all npm packages in fixtures/node_modules', function() { @@ -419,7 +413,6 @@ describe('angular-fullstack generator', function () { }); describe('running app', function() { - beforeEach(function() { this.timeout(20000); return Promise.all([ @@ -438,7 +431,7 @@ describe('angular-fullstack generator', function () { runTest('grunt test:client', this, done); }); - it('should pass jscs', function(done) { + it.only('should pass jscs', function(done) { runTest('grunt jscs', this, done); }); From 7c8795371cfa2a7c6afdf5f7f1bc93d393972feb Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Mon, 25 Apr 2016 13:00:25 -0400 Subject: [PATCH 09/53] chore(package): update test command to use `gulp test` instead of grunt --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f961d8549..1827ba07e 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "url": "git://github.com/angular-fullstack/generator-angular-fullstack.git" }, "scripts": { - "test": "gulp build && grunt test", + "test": "gulp build && gulp test", "prepublish": "gulp build" }, "dependencies": { From 04a787884ad05d0cc1facf662725bcdbdd294e8b Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Mon, 25 Apr 2016 13:51:57 -0400 Subject: [PATCH 10/53] feat(gen:gulp): add installFixtures task --- gulpfile.js | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/gulpfile.js b/gulpfile.js index 257025cf3..e4529953e 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -11,6 +11,10 @@ var del = require('del'); var lazypipe = require('lazypipe'); var runSequence = require('run-sequence'); var merge = require('merge-stream'); +const exec = require('child_process').exec; +const _ = require('lodash'); +const gutil = require('gulp-util'); +const shell = require('shelljs'); var watching = false; @@ -114,6 +118,47 @@ gulp.task('updateFixtures:deps', () => { return updateFixtures('deps'); }); +function execAsync(cmd, opt) { + return new Promise((resolve, reject) => { + exec(cmd, opt, (err, stdout, stderr) => { + if(err) { + console.log(`stderr: ${stderr}`); + return reject(err); + } + + return resolve(stdout); + }) + }); +} + +gulp.task('installFixtures', function() { + gutil.log('installing npm & bower dependencies for generated app'); + let progress = setInterval(() => { + process.stdout.write('.'); + }, 1 * 1000); + shell.cd('test/fixtures'); + + return Promise.all([ + execAsync('npm install --quiet', {cwd: '../fixtures'}), + execAsync('bower install', {cwd: '../fixtures'}) + ]).then(() => { + process.stdout.write('\n'); + if(!process.env.SAUCE_USERNAME) { + gutil.log('running npm run-script update-webdriver'); + return execAsync('npm run-script update-webdriver').then(() => { + clearInterval(progress); + process.stdout.write('\n'); + shell.cd('../../'); + }); + } else { + clearInterval(progress); + process.stdout.write('\n'); + shell.cd('../../'); + return Promise.resolve(); + } + }); +}); + gulp.task('test', () => { return gulp.src('test/*.test.js') .pipe(mocha()) From 62577eafb4c4f8c5c8e45e464aa89db1f6f126ce Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Mon, 25 Apr 2016 13:52:51 -0400 Subject: [PATCH 11/53] style(gen:gulp): use const for imports, add semicolon --- gulpfile.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index e4529953e..8310337f7 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,19 +1,19 @@ 'use strict'; -var fs = require('fs'); -var path = require('path'); -var Promise = require('bluebird'); -var gulp = require('gulp'); -var babel = require('gulp-babel'); -var gulpMocha = require('gulp-mocha'); -var plumber = require('gulp-plumber'); -var gulpIf = require('gulp-if'); -var del = require('del'); -var lazypipe = require('lazypipe'); -var runSequence = require('run-sequence'); -var merge = require('merge-stream'); +const fs = require('fs'); +const path = require('path'); const exec = require('child_process').exec; const _ = require('lodash'); +const Promise = require('bluebird'); +const gulp = require('gulp'); const gutil = require('gulp-util'); +const babel = require('gulp-babel'); +const gulpMocha = require('gulp-mocha'); +const plumber = require('gulp-plumber'); +const gulpIf = require('gulp-if'); +const del = require('del'); +const lazypipe = require('lazypipe'); +const runSequence = require('run-sequence'); +const merge = require('merge-stream'); const shell = require('shelljs'); var watching = false; @@ -161,5 +161,5 @@ gulp.task('installFixtures', function() { gulp.task('test', () => { return gulp.src('test/*.test.js') - .pipe(mocha()) + .pipe(mocha()); }); From 9b9c781fbd97048eb42b31b2e8e852cc2f8b74a2 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Mon, 25 Apr 2016 13:53:16 -0400 Subject: [PATCH 12/53] chore(package): add gulp-util --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 1827ba07e..f373d4df7 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "gulp-if": "^2.0.0", "gulp-mocha": "^2.2.0", "gulp-plumber": "^1.1.0", + "gulp-util": "^3.0.7", "jit-grunt": "~0.10.0", "lazypipe": "^1.0.1", "merge-stream": "^1.0.0", From 5a21831029bf107665b8111239dc755f72e2a5a8 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Mon, 25 Apr 2016 13:53:43 -0400 Subject: [PATCH 13/53] chore(package): add updateFixtures:deps & installFixtures to `test` script --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f373d4df7..524ab175b 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "url": "git://github.com/angular-fullstack/generator-angular-fullstack.git" }, "scripts": { - "test": "gulp build && gulp test", + "test": "gulp updateFixtures:test && gulp installFixtures && gulp build && gulp test", "prepublish": "gulp build" }, "dependencies": { From 57477392d315faa8b9db1e2915c206f3c3e97e50 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Mon, 25 Apr 2016 16:40:09 -0400 Subject: [PATCH 14/53] fix(gen:gulp:watch): for some reason gulp-if isn't working inside lazypipe --- gulpfile.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gulpfile.js b/gulpfile.js index 8310337f7..3b47197d6 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -28,7 +28,6 @@ const mocha = lazypipe() }); const transpile = lazypipe() - .pipe(() => gulpIf(watching, plumber())) .pipe(babel); gulp.task('clean', () => { @@ -37,10 +36,12 @@ gulp.task('clean', () => { gulp.task('babel', () => { let generators = gulp.src(['src/generators/**/*.js']) + .pipe(gulpIf(watching, plumber())) .pipe(transpile()) .pipe(gulp.dest('generators')); let test = gulp.src(['src/test/**/*.js']) + .pipe(gulpIf(watching, plumber())) .pipe(transpile()) .pipe(gulp.dest('test')); From 0787039881bec29280b9fafeadbf8fe14fb95058 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Mon, 25 Apr 2016 16:41:16 -0400 Subject: [PATCH 15/53] fix(gen:endpoint): typo --- src/generators/endpoint/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/generators/endpoint/index.js b/src/generators/endpoint/index.js index 675e61c07..4c05c8e97 100644 --- a/src/generators/endpoint/index.js +++ b/src/generators/endpoint/index.js @@ -22,7 +22,7 @@ export class Generator extends Base { }); this.option('endpointDirectory', { - desc: 'Parent directory for enpoints', + desc: 'Parent directory for endpoints', type: String }); } From d51295a84b0149496d904a775954f65ec1a6945f Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Mon, 25 Apr 2016 16:42:10 -0400 Subject: [PATCH 16/53] docs(gen:tests): add some JSDoc to `runCmd` --- src/test/main.test.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/test/main.test.js b/src/test/main.test.js index deed2c25b..802d2c6b1 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -27,6 +27,16 @@ const defaultOptions = { // var DEBUG = true; var DEBUG = false; +/** + * @callback doneCallback + * @param {null|Error} err + */ + +/** + * Run the given command in a child process + * @param {string} cmd - command to run + * @param {doneCallback} done + */ function runCmd(cmd, done) { exec(cmd, {}, function(err, stdout, stderr) { if(err) { From 36d79c2f98bfddce0f3f85077e6a9fc39491614b Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Mon, 25 Apr 2016 16:43:47 -0400 Subject: [PATCH 17/53] feat(gen:tests): a bunch of test progress --- src/test/main.test.js | 177 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 163 insertions(+), 14 deletions(-) diff --git a/src/test/main.test.js b/src/test/main.test.js index 802d2c6b1..64f80e796 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -1,12 +1,14 @@ 'use strict'; import path from 'path'; import fs from 'fs'; +import _ from 'lodash'; import Promise from 'bluebird'; Promise.promisifyAll(fs); import {exec} from 'child_process'; import helpers from 'yeoman-test'; import assert from 'yeoman-assert'; import * as getExpectedFiles from './get-expected-files'; +import recursiveReadDir from 'recursive-readdir'; const defaultOptions = { buildtool: 'grunt', @@ -26,6 +28,12 @@ const defaultOptions = { }; // var DEBUG = true; var DEBUG = false; +const TEST_DIR = __dirname; + +function copyAsync(src, dest) { + return fs.readFileAsync(src) + .then(data => fs.writeFileAsync(dest, data)); +} /** * @callback doneCallback @@ -50,14 +58,36 @@ function runCmd(cmd, done) { }); } -describe('angular-fullstack:app', function() { - beforeEach(function() { - this.gen = helpers +function assertOnlyFiles(expectedFiles, topLevelPath='./', skip=['node_modules', 'bower_components']) { + return new Promise((resolve, reject) => { + recursiveReadDir(topLevelPath, skip, function(err, actualFiles) { + if(err) return reject(err); + + actualFiles = _.map(actualFiles.concat(), file => path.normalize(file.replace(path.normalize(`${topLevelPath}/`), ''))); + expectedFiles = _.map(expectedFiles, file => path.normalize(file)); + + let extras = _.pullAll(actualFiles, expectedFiles); + + if(extras.length !== 0) { + return reject(extras); + } + resolve(); + }); + }); +} + +function runGen(prompts) { + return new Promise((resolve, reject) => { + let dir; + helpers .run(require.resolve('../generators/app')) - .inTmpDir(function(dir) { + .inTmpDir(function(_dir) { + // this will create a new temporary directory for each new generator run var done = this.async(); - if(DEBUG) console.log(`TEMP DIR: ${dir}`); + if(DEBUG) console.log(`TEMP DIR: ${_dir}`); + dir = _dir; + // symlink our dependency directories return Promise.all([ fs.mkdirAsync(dir + '/client').then(() => { return fs.symlinkAsync(__dirname + '/fixtures/bower_components', dir + '/client/bower_components'); @@ -70,21 +100,62 @@ describe('angular-fullstack:app', function() { // [helpers.createDummyGenerator(), 'ng-component:app'] ]) .withOptions({ - skipInstall: true, - force: true + skipInstall: true }) // .withArguments(['upperCaseBug']) - .withPrompts(defaultOptions); + .withPrompts(prompts) + .on('error', reject) + .on('end', () => resolve(dir)); + }); +} + +function runEndpointGen(name, opt={}) { + let prompts = opt.prompts || {}; + let options = opt.options || {}; + let config = opt.config; + + return new Promise((resolve, reject) => { + let gen = helpers + .run(require.resolve('../generators/endpoint'), {tmpdir: false}) + .withOptions(options) + .withArguments([name]) + .withPrompts(prompts); + + if(config) { + gen + .withLocalConfig(config); + } + + gen + .on('error', reject) + .on('end', () => resolve()) + }); +} + +function getConfig(dir) { + return fs.readFileAsync(path.join(dir, '.yo-rc.json'), 'utf8').then(data => { + return JSON.parse(data); + }); +} + +describe('angular-fullstack:app', function() { + beforeEach(function() { + this.gen = runGen(defaultOptions); }); describe('default settings', function() { - beforeEach(function(done) { - this.gen.on('end', done); + var dir; + + beforeEach(function() { + return this.gen.then(_dir => { + dir = _dir; + }); }); - it('generates the proper files', function(done) { - assert.file(getExpectedFiles.app(defaultOptions)); - done(); + it('generates the proper files', function() { + const expectedFiles = getExpectedFiles.app(defaultOptions); + assert.file(expectedFiles); + return assertOnlyFiles(expectedFiles, path.normalize(dir)).should.eventually.be.fulfilled; }); it('passes JSCS', function(done) { @@ -99,8 +170,86 @@ describe('angular-fullstack:app', function() { runCmd('grunt test:client', done); }); - it('passes client tests', function(done) { + it('passes server tests', function(done) { runCmd('grunt test:server', done); }); + + describe('with a generated endpont', function() { + beforeEach(function() { + getConfig(dir).then(config => { + return runEndpointGen('foo', {config: config['generator-angular-fullstack']}); + }); + }); + + it('should pass jscs'); //'foo' + + it('should pass lint'); + + it('should run server tests successfully', function(done) { + runCmd('grunt test:server', done); + }); + }); + + describe.only('with a generated capitalized endpont', function() { + beforeEach(function() { + getConfig(dir).then(config => { + return runEndpointGen('Foo', {config: config['generator-angular-fullstack']}); + }); + }); + + it('should pass jscs'); + + it('should pass lint'); + + it('should run server tests successfully', function(done) { + runCmd('grunt test:server', done); + }); + }); + + it('should pass lint with generated path name endpoint'); //'foo/bar' + + it('should run server tests successfully with generated path name endpoint'); + + it('should generate expected files with path name endpoint'); + // [ + // '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' + // ] + + it('should use existing config if available'); + // this.timeout(60000); + // return copyAsync(__dirname + '/fixtures/.yo-rc.json', __dirname + '/temp/.yo-rc.json').then(() => { + // var gen = helpers.createGenerator('angular-fullstack:app', [ + // '../../generators/app', + // '../../generators/endpoint', + // [ + // helpers.createDummyGenerator(), + // 'ng-component:app' + // ] + // ], [], { + // skipInstall: true + // }); + // helpers.mockPrompt(gen, { + // skipConfig: true + // }); + // gen.run(function () { + // assert.file([ + // 'client/app/main/main.less', + // 'server/auth/google/passport.js' + // ]); + // done(); + // }); + // }); + + if(!process.env.SKIP_E2E) { + it('should run e2e tests successfully'); //'grunt test:e2e' + + it('should run e2e tests successfully for production app'); //'grunt test:e2e:prod' + } }); }); \ No newline at end of file From 3310a1cebf417394b6b702ac87be04b374e73631 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Mon, 25 Apr 2016 16:50:00 -0400 Subject: [PATCH 18/53] fix(gen:test): remove my `.only` --- src/test/main.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/main.test.js b/src/test/main.test.js index 64f80e796..62eeed2b0 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -190,7 +190,7 @@ describe('angular-fullstack:app', function() { }); }); - describe.only('with a generated capitalized endpont', function() { + describe('with a generated capitalized endpont', function() { beforeEach(function() { getConfig(dir).then(config => { return runEndpointGen('Foo', {config: config['generator-angular-fullstack']}); From 1c91686baa0c24eade8fb8b34361417c7ff2c94e Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 27 Apr 2016 01:51:01 -0400 Subject: [PATCH 19/53] refactor(gen:test): move DEBUG var to mocha.conf.js --- gulpfile.js | 5 ++++- mocha.conf.js | 3 +++ src/test/main.test.js | 2 -- 3 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 mocha.conf.js diff --git a/gulpfile.js b/gulpfile.js index 3b47197d6..6ffef6e65 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -24,7 +24,10 @@ const mocha = lazypipe() timeout: 120000, globals: { should: require('should') - } + }, + require: [ + './mocha.conf' + ] }); const transpile = lazypipe() diff --git a/mocha.conf.js b/mocha.conf.js new file mode 100644 index 000000000..8fbbb39e6 --- /dev/null +++ b/mocha.conf.js @@ -0,0 +1,3 @@ +'use strict'; + +global.DEBUG = !!process.env.DEBUG; diff --git a/src/test/main.test.js b/src/test/main.test.js index 62eeed2b0..1f5f8a70e 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -26,8 +26,6 @@ const defaultOptions = { oauth: [], socketio: true }; -// var DEBUG = true; -var DEBUG = false; const TEST_DIR = __dirname; function copyAsync(src, dest) { From fdd5b68899f22057829066363c2c047333875f58 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 27 Apr 2016 02:04:55 -0400 Subject: [PATCH 20/53] refactor(gen:test): pull 4 helper functions out into a separate module --- src/test/main.test.js | 60 ++++---------------------------------- src/test/test-helpers.js | 63 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 54 deletions(-) create mode 100644 src/test/test-helpers.js diff --git a/src/test/main.test.js b/src/test/main.test.js index 1f5f8a70e..8f7a0836f 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -4,11 +4,15 @@ import fs from 'fs'; import _ from 'lodash'; import Promise from 'bluebird'; Promise.promisifyAll(fs); -import {exec} from 'child_process'; import helpers from 'yeoman-test'; import assert from 'yeoman-assert'; import * as getExpectedFiles from './get-expected-files'; -import recursiveReadDir from 'recursive-readdir'; +import { + copyAsync, + runCmd, + assertOnlyFiles, + getConfig +} from './test-helpers'; const defaultOptions = { buildtool: 'grunt', @@ -28,52 +32,6 @@ const defaultOptions = { }; const TEST_DIR = __dirname; -function copyAsync(src, dest) { - return fs.readFileAsync(src) - .then(data => fs.writeFileAsync(dest, data)); -} - -/** - * @callback doneCallback - * @param {null|Error} err - */ - -/** - * Run the given command in a child process - * @param {string} cmd - command to run - * @param {doneCallback} done - */ -function runCmd(cmd, done) { - exec(cmd, {}, function(err, stdout, stderr) { - if(err) { - console.error(stdout); - throw new Error(`Error running command: ${cmd}`); - done(err); - } else { - if(DEBUG) console.log(stdout); - done(); - } - }); -} - -function assertOnlyFiles(expectedFiles, topLevelPath='./', skip=['node_modules', 'bower_components']) { - return new Promise((resolve, reject) => { - recursiveReadDir(topLevelPath, skip, function(err, actualFiles) { - if(err) return reject(err); - - actualFiles = _.map(actualFiles.concat(), file => path.normalize(file.replace(path.normalize(`${topLevelPath}/`), ''))); - expectedFiles = _.map(expectedFiles, file => path.normalize(file)); - - let extras = _.pullAll(actualFiles, expectedFiles); - - if(extras.length !== 0) { - return reject(extras); - } - resolve(); - }); - }); -} - function runGen(prompts) { return new Promise((resolve, reject) => { let dir; @@ -130,12 +88,6 @@ function runEndpointGen(name, opt={}) { }); } -function getConfig(dir) { - return fs.readFileAsync(path.join(dir, '.yo-rc.json'), 'utf8').then(data => { - return JSON.parse(data); - }); -} - describe('angular-fullstack:app', function() { beforeEach(function() { this.gen = runGen(defaultOptions); diff --git a/src/test/test-helpers.js b/src/test/test-helpers.js new file mode 100644 index 000000000..7ddf890cb --- /dev/null +++ b/src/test/test-helpers.js @@ -0,0 +1,63 @@ +'use strict'; +import path from 'path'; +import fs from 'fs'; +import _ from 'lodash'; +import Promise from 'bluebird'; +Promise.promisifyAll(fs); +import {exec} from 'child_process'; +import helpers from 'yeoman-test'; +import assert from 'yeoman-assert'; +import * as getExpectedFiles from './get-expected-files'; +import recursiveReadDir from 'recursive-readdir'; + +export function copyAsync(src, dest) { + return fs.readFileAsync(src) + .then(data => fs.writeFileAsync(dest, data)); +} + +/** + * @callback doneCallback + * @param {null|Error} err + */ + +/** + * Run the given command in a child process + * @param {string} cmd - command to run + * @param {doneCallback} done + */ +export function runCmd(cmd, done) { + exec(cmd, {}, function(err, stdout, stderr) { + if(err) { + console.error(stdout); + throw new Error(`Error running command: ${cmd}`); + done(err); + } else { + if(DEBUG) console.log(stdout); + done(); + } + }); +} + +export function assertOnlyFiles(expectedFiles, topLevelPath='./', skip=['node_modules', 'bower_components']) { + return new Promise((resolve, reject) => { + recursiveReadDir(topLevelPath, skip, function(err, actualFiles) { + if(err) return reject(err); + + actualFiles = _.map(actualFiles.concat(), file => path.normalize(file.replace(path.normalize(`${topLevelPath}/`), ''))); + expectedFiles = _.map(expectedFiles, file => path.normalize(file)); + + let extras = _.pullAll(actualFiles, expectedFiles); + + if(extras.length !== 0) { + return reject(extras); + } + resolve(); + }); + }); +} + +export function getConfig(dir) { + return fs.readFileAsync(path.join(dir, '.yo-rc.json'), 'utf8').then(data => { + return JSON.parse(data); + }); +} From 0b363756b62263396c45165741ef1ef88b0d5bba Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 27 Apr 2016 02:20:15 -0400 Subject: [PATCH 21/53] feat(gen:test): add endpoint path name test --- src/test/main.test.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/test/main.test.js b/src/test/main.test.js index 8f7a0836f..84756b05c 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -156,9 +156,21 @@ describe('angular-fullstack:app', function() { }); }); - it('should pass lint with generated path name endpoint'); //'foo/bar' + describe('with a generated path name endpont', function() { + beforeEach(function() { + getConfig(dir).then(config => { + return runEndpointGen('foo/bar', {config: config['generator-angular-fullstack']}); + }); + }); + + it('should pass jscs'); - it('should run server tests successfully with generated path name endpoint'); + it('should pass lint'); + + it('should run server tests successfully', function(done) { + runCmd('grunt test:server', done); + }); + }); it('should generate expected files with path name endpoint'); // [ From babb03fa5b38dd345ae58bc330aee5842d784c2a Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Wed, 27 Apr 2016 02:25:41 -0400 Subject: [PATCH 22/53] fix(gen:test): fix `getConfig` path --- src/test/main.test.js | 6 +++--- src/test/test-helpers.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/main.test.js b/src/test/main.test.js index 84756b05c..49823798c 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -126,7 +126,7 @@ describe('angular-fullstack:app', function() { describe('with a generated endpont', function() { beforeEach(function() { - getConfig(dir).then(config => { + getConfig(path.join(dir, '.yo-rc.json')).then(config => { return runEndpointGen('foo', {config: config['generator-angular-fullstack']}); }); }); @@ -142,7 +142,7 @@ describe('angular-fullstack:app', function() { describe('with a generated capitalized endpont', function() { beforeEach(function() { - getConfig(dir).then(config => { + getConfig(path.join(dir, '.yo-rc.json')).then(config => { return runEndpointGen('Foo', {config: config['generator-angular-fullstack']}); }); }); @@ -158,7 +158,7 @@ describe('angular-fullstack:app', function() { describe('with a generated path name endpont', function() { beforeEach(function() { - getConfig(dir).then(config => { + getConfig(path.join(dir, '.yo-rc.json')).then(config => { return runEndpointGen('foo/bar', {config: config['generator-angular-fullstack']}); }); }); diff --git a/src/test/test-helpers.js b/src/test/test-helpers.js index 7ddf890cb..7a45e4b25 100644 --- a/src/test/test-helpers.js +++ b/src/test/test-helpers.js @@ -56,8 +56,8 @@ export function assertOnlyFiles(expectedFiles, topLevelPath='./', skip=['node_mo }); } -export function getConfig(dir) { - return fs.readFileAsync(path.join(dir, '.yo-rc.json'), 'utf8').then(data => { +export function getConfig(path) { + return fs.readFileAsync(path, 'utf8').then(data => { return JSON.parse(data); }); } From 2a1d702860dda8540c043ee90271eebb68c1ed79 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Thu, 28 Apr 2016 02:56:19 -0400 Subject: [PATCH 23/53] refactor(gen:test): runCmd returns a Promise instead of taking a callback --- src/test/main.test.js | 28 ++++++++++++++-------------- src/test/test-helpers.js | 23 ++++++++++++----------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/test/main.test.js b/src/test/main.test.js index 49823798c..d6bc3eac6 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -108,20 +108,20 @@ describe('angular-fullstack:app', function() { return assertOnlyFiles(expectedFiles, path.normalize(dir)).should.eventually.be.fulfilled; }); - it('passes JSCS', function(done) { - runCmd('grunt jscs', done); + it('passes JSCS', function() { + return runCmd('grunt jscs').should.be.fulfilled(); }); - it('passes JSHint', function(done) { - runCmd('grunt jshint', done); + it('passes JSHint', function() { + return runCmd('grunt jshint').should.be.fulfilled(); }); - it('passes client tests', function(done) { - runCmd('grunt test:client', done); + it('passes client tests', function() { + return runCmd('grunt test:client').should.be.fulfilled(); }); - it('passes server tests', function(done) { - runCmd('grunt test:server', done); + it('passes server tests', function() { + return runCmd('grunt test:server').should.be.fulfilled(); }); describe('with a generated endpont', function() { @@ -135,8 +135,8 @@ describe('angular-fullstack:app', function() { it('should pass lint'); - it('should run server tests successfully', function(done) { - runCmd('grunt test:server', done); + it('should run server tests successfully', function() { + return runCmd('grunt test:server').should.be.fulfilled(); }); }); @@ -151,8 +151,8 @@ describe('angular-fullstack:app', function() { it('should pass lint'); - it('should run server tests successfully', function(done) { - runCmd('grunt test:server', done); + it('should run server tests successfully', function() { + return runCmd('grunt test:server').should.be.fulfilled(); }); }); @@ -167,8 +167,8 @@ describe('angular-fullstack:app', function() { it('should pass lint'); - it('should run server tests successfully', function(done) { - runCmd('grunt test:server', done); + it('should run server tests successfully', function() { + return runCmd('grunt test:server').should.be.fulfilled(); }); }); diff --git a/src/test/test-helpers.js b/src/test/test-helpers.js index 7a45e4b25..9745c2cfe 100644 --- a/src/test/test-helpers.js +++ b/src/test/test-helpers.js @@ -23,18 +23,19 @@ export function copyAsync(src, dest) { /** * Run the given command in a child process * @param {string} cmd - command to run - * @param {doneCallback} done + * @returns {Promise} */ -export function runCmd(cmd, done) { - exec(cmd, {}, function(err, stdout, stderr) { - if(err) { - console.error(stdout); - throw new Error(`Error running command: ${cmd}`); - done(err); - } else { - if(DEBUG) console.log(stdout); - done(); - } +export function runCmd(cmd) { + return new Promise((resolve, reject) => { + exec(cmd, {}, function(err, stdout, stderr) { + if(err) { + console.error(stdout); + return reject(err); + } else { + if(DEBUG) console.log(`${cmd} stdout: ${stdout}`); + return resolve(); + } + }); }); } From 887476fc5988c4781730c5f9a69a9c0fad17e752 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Thu, 28 Apr 2016 02:58:09 -0400 Subject: [PATCH 24/53] feat(gen:test): add endpoint-specific tests --- package.json | 1 + src/test/endpoint.test.js | 192 +++++++++++++++++++++++++++++++++ src/test/get-expected-files.js | 17 +-- 3 files changed, 202 insertions(+), 8 deletions(-) create mode 100644 src/test/endpoint.test.js diff --git a/package.json b/package.json index 524ab175b..0e6ebf82e 100644 --- a/package.json +++ b/package.json @@ -74,6 +74,7 @@ "jit-grunt": "~0.10.0", "lazypipe": "^1.0.1", "merge-stream": "^1.0.0", + "minimatch": "^3.0.0", "mocha": "^2.2.5", "q": "^1.0.1", "recursive-readdir": "^2.0.0", diff --git a/src/test/endpoint.test.js b/src/test/endpoint.test.js new file mode 100644 index 000000000..7c925c93e --- /dev/null +++ b/src/test/endpoint.test.js @@ -0,0 +1,192 @@ +'use strict'; +import path from 'path'; +import fs from 'fs'; +import _ from 'lodash'; +import Promise from 'bluebird'; +Promise.promisifyAll(fs); +import helpers from 'yeoman-test'; +import assert from 'yeoman-assert'; +import minimatch from 'minimatch'; +import * as getExpectedFiles from './get-expected-files'; +import { + copyAsync, + runCmd, + assertOnlyFiles, + getConfig +} from './test-helpers'; + +const TEST_DIR = __dirname; + +const defaultOptions = { + buildtool: 'grunt', + script: 'js', + transpiler: 'babel', + markup: 'html', + stylesheet: 'sass', + router: 'uirouter', + testing: 'mocha', + chai: 'expect', + bootstrap: true, + uibootstrap: true, + odms: ['mongoose'], + auth: true, + oauth: [], + socketio: true +}; +function runGen(prompts) { + return new Promise((resolve, reject) => { + let dir; + helpers + .run(require.resolve('../generators/app')) + .inTmpDir(function(_dir) { + // this will create a new temporary directory for each new generator run + var done = this.async(); + if(DEBUG) console.log(`TEMP DIR: ${_dir}`); + dir = _dir; + + // symlink our dependency directories + return Promise.all([ + fs.mkdirAsync(dir + '/client').then(() => { + return fs.symlinkAsync(__dirname + '/fixtures/bower_components', dir + '/client/bower_components'); + }), + fs.symlinkAsync(__dirname + '/fixtures/node_modules', dir + '/node_modules') + ]).then(done); + }) + .withGenerators([ + require.resolve('../generators/endpoint'), + // [helpers.createDummyGenerator(), 'ng-component:app'] + ]) + .withOptions({ + skipInstall: true + }) + .withPrompts(prompts) + .on('error', reject) + .on('end', () => resolve(dir)); + }); +} + +function runEndpointGen(name, opt={}) { + let prompts = opt.prompts || {}; + let options = opt.options || {}; + let config = opt.config; + + return new Promise((resolve, reject) => { + let dir; + let gen = helpers + .run(require.resolve('../generators/endpoint')) + .inTmpDir(function(_dir) { + // this will create a new temporary directory for each new generator run + var done = this.async(); + if(DEBUG) console.log(`TEMP DIR: ${_dir}`); + dir = _dir; + + // symlink our dependency directories + return Promise.all([ + fs.mkdirAsync(dir + '/client').then(() => { + return fs.symlinkAsync(__dirname + '/fixtures/bower_components', dir + '/client/bower_components'); + }), + fs.symlinkAsync(__dirname + '/fixtures/node_modules', dir + '/node_modules') + ]).then(done); + }) + .withOptions(options) + .withArguments([name]) + .withPrompts(prompts); + + if(config) { + gen + .withLocalConfig(config); + } + + gen + .on('error', reject) + .on('end', () => resolve(dir)) + }); +} + +let jshintCmd = path.join(TEST_DIR, '/fixtures/node_modules/.bin/jshint'); +function jshint(_path, opt={}) { + let {exclude, config} = opt; + let cmd = `${jshintCmd} ${path.normalize(_path)}`; + if(exclude) cmd += ` --exclude ${exclude}`; + if(config) cmd += ` --config ${config}`; + return runCmd(cmd); +} + +var config; +var genDir; + +before(function() { + return Promise.all([ + runGen(defaultOptions).then(_dir => { + genDir = _dir; + }), + getConfig(path.join(TEST_DIR, 'fixtures/.yo-rc.json')).then(_config => { + _config['generator-angular-fullstack'].insertRoutes = false; + _config['generator-angular-fullstack'].pluralizeRoutes = false; + _config['generator-angular-fullstack'].insertSockets = false; + _config['generator-angular-fullstack'].insertModels = false; + config = _config; + }) + ]); +}); + +describe('angular-fullstack:endpoint', function() { + describe(`with a generated endpont 'foo'`, function() { + var dir; + beforeEach(function() { + return runEndpointGen('foo', {config: config['generator-angular-fullstack']}).then(_dir => { + dir = _dir; + + return Promise.all([ + copyAsync(path.join(genDir, '/server/.jshintrc'), './server/.jshintrc'), + copyAsync(path.join(genDir, '/server/.jshintrc-spec'), './server/.jshintrc-spec') + ]); + }); + }); + + it('should generate the expected files', function() { + assert.file(getExpectedFiles.endpoint('foo')); + }); + + it('should pass jscs'); + + it('should pass lint', function() { + let endpointDir = path.join(dir, 'server/api/foo/'); + let regFiles = fs.readdirAsync(endpointDir) + .then(files => files.filter(file => minimatch(file, '**/!(*.spec|*.mock|*.integration).js', {dot: true}))) + .map(file => jshint(`./server/api/foo/${file}`)); + + let specFiles = fs.readdirAsync(endpointDir) + .then(files => files.filter(file => minimatch(file, '**/+(*.spec|*.mock|*.integration).js', {dot: true}))) + .map(file => jshint(`./server/api/food/${file}`, {config: 'server/.jshintrc-spec'})); + + return Promise.all([regFiles, specFiles]).should.be.fulfilled(); + }); + }); + + describe('with a generated capitalized endpont', function() { + var dir; + beforeEach(function() { + return runEndpointGen('foo', {config: config['generator-angular-fullstack']}).then(_dir => { + dir = _dir; + }); + }); + + it('should pass jscs'); + + it('should pass lint'); + }); + + describe('with a generated path name endpont', function() { + var dir; + beforeEach(function() { + return runEndpointGen('foo', {config: config['generator-angular-fullstack']}).then(_dir => { + dir = _dir; + }); + }); + + it('should pass jscs'); + + it('should pass lint'); + }); +}); \ No newline at end of file diff --git a/src/test/get-expected-files.js b/src/test/get-expected-files.js index 6a435b3dd..c3ac9a338 100644 --- a/src/test/get-expected-files.js +++ b/src/test/get-expected-files.js @@ -224,14 +224,15 @@ export function app(options) { return files; } -export function endpoint(name, options) { +export function endpoint(name, path) { + if(!path) path = name; return [ - `server/api/${name}/index.js`, - `server/api/${name}/index.spec.js`, - `server/api/${name}/bar.controller.js`, - `server/api/${name}/bar.events.js`, - `server/api/${name}/bar.integration.js`, - `server/api/${name}/bar.model.js`, - `server/api/${name}/bar.socket.js` + `server/api/${path}/index.js`, + `server/api/${path}/index.spec.js`, + `server/api/${path}/${name}.controller.js`, + `server/api/${path}/${name}.events.js`, + `server/api/${path}/${name}.integration.js`, + `server/api/${path}/${name}.model.js`, + `server/api/${path}/${name}.socket.js` ]; } From cfa3152319a19355bff10fd1f59cf32bee7835d4 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Thu, 28 Apr 2016 13:36:24 -0400 Subject: [PATCH 25/53] test(gen:main): remove pending endpoint lint tasks --- src/test/main.test.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/test/main.test.js b/src/test/main.test.js index d6bc3eac6..c334174ce 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -131,10 +131,6 @@ describe('angular-fullstack:app', function() { }); }); - it('should pass jscs'); //'foo' - - it('should pass lint'); - it('should run server tests successfully', function() { return runCmd('grunt test:server').should.be.fulfilled(); }); @@ -147,10 +143,6 @@ describe('angular-fullstack:app', function() { }); }); - it('should pass jscs'); - - it('should pass lint'); - it('should run server tests successfully', function() { return runCmd('grunt test:server').should.be.fulfilled(); }); @@ -163,10 +155,6 @@ describe('angular-fullstack:app', function() { }); }); - it('should pass jscs'); - - it('should pass lint'); - it('should run server tests successfully', function() { return runCmd('grunt test:server').should.be.fulfilled(); }); From 17d9985d6afef905aa2edccc2c69923d70d778bd Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Thu, 28 Apr 2016 13:53:10 -0400 Subject: [PATCH 26/53] fix(gen:test:endpoint): `jshint` function also checks that the file exists --- src/test/endpoint.test.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/test/endpoint.test.js b/src/test/endpoint.test.js index 7c925c93e..2950448ab 100644 --- a/src/test/endpoint.test.js +++ b/src/test/endpoint.test.js @@ -105,11 +105,14 @@ function runEndpointGen(name, opt={}) { let jshintCmd = path.join(TEST_DIR, '/fixtures/node_modules/.bin/jshint'); function jshint(_path, opt={}) { - let {exclude, config} = opt; - let cmd = `${jshintCmd} ${path.normalize(_path)}`; - if(exclude) cmd += ` --exclude ${exclude}`; - if(config) cmd += ` --config ${config}`; - return runCmd(cmd); + _path = path.normalize(_path); + return fs.accessAsync(_path, fs.R_OK).then(err => { + let {config} = opt; + let cmd = `${jshintCmd} ${path.normalize(_path)}`; + if(config) cmd += ` --config ${config}`; + return runCmd(cmd); + }); +} } var config; From 61eb160ffe7ac2d8c2877dfc52511b8619d975c7 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Thu, 28 Apr 2016 13:54:16 -0400 Subject: [PATCH 27/53] refactor(test:endpoint): break out jshint suite into helper function --- src/test/endpoint.test.js | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/test/endpoint.test.js b/src/test/endpoint.test.js index 2950448ab..8bb10bb30 100644 --- a/src/test/endpoint.test.js +++ b/src/test/endpoint.test.js @@ -113,6 +113,20 @@ function jshint(_path, opt={}) { return runCmd(cmd); }); } + +function jshintDir(dir, name, folder) { + if(!folder) folder = name; + let endpointDir = path.join(dir, 'server/api', folder); + + let regFiles = fs.readdirAsync(endpointDir) + .then(files => files.filter(file => minimatch(file, '**/!(*.spec|*.mock|*.integration).js', {dot: true}))) + .map(file => jshint(path.join('./server/api/', folder, file))); + + let specFiles = fs.readdirAsync(endpointDir) + .then(files => files.filter(file => minimatch(file, '**/+(*.spec|*.mock|*.integration).js', {dot: true}))) + .map(file => jshint(path.join('./server/api/', folder, file), {config: 'server/.jshintrc-spec'})); + + return Promise.all([regFiles, specFiles]); } var config; @@ -154,16 +168,7 @@ describe('angular-fullstack:endpoint', function() { it('should pass jscs'); it('should pass lint', function() { - let endpointDir = path.join(dir, 'server/api/foo/'); - let regFiles = fs.readdirAsync(endpointDir) - .then(files => files.filter(file => minimatch(file, '**/!(*.spec|*.mock|*.integration).js', {dot: true}))) - .map(file => jshint(`./server/api/foo/${file}`)); - - let specFiles = fs.readdirAsync(endpointDir) - .then(files => files.filter(file => minimatch(file, '**/+(*.spec|*.mock|*.integration).js', {dot: true}))) - .map(file => jshint(`./server/api/food/${file}`, {config: 'server/.jshintrc-spec'})); - - return Promise.all([regFiles, specFiles]).should.be.fulfilled(); + return jshintDir(dir, 'foo').should.be.fulfilled(); }); }); From 20cfbe62bebabcbcdee00b2917a8d8e71651b15a Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Thu, 28 Apr 2016 18:52:23 -0400 Subject: [PATCH 28/53] test(gen:endpoint): add other 2 lint tests, file assert stubs --- src/test/endpoint.test.js | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/test/endpoint.test.js b/src/test/endpoint.test.js index 8bb10bb30..ed06d1575 100644 --- a/src/test/endpoint.test.js +++ b/src/test/endpoint.test.js @@ -175,26 +175,44 @@ describe('angular-fullstack:endpoint', function() { describe('with a generated capitalized endpont', function() { var dir; beforeEach(function() { - return runEndpointGen('foo', {config: config['generator-angular-fullstack']}).then(_dir => { + return runEndpointGen('Foo', {config: config['generator-angular-fullstack']}).then(_dir => { dir = _dir; + + return Promise.all([ + copyAsync(path.join(genDir, '/server/.jshintrc'), './server/.jshintrc'), + copyAsync(path.join(genDir, '/server/.jshintrc-spec'), './server/.jshintrc-spec') + ]); }); }); + it('should generate the expected files'); + it('should pass jscs'); - it('should pass lint'); + it('should pass lint', function() { + return jshintDir(dir, 'Foo').should.be.fulfilled(); + }); }); describe('with a generated path name endpont', function() { var dir; beforeEach(function() { - return runEndpointGen('foo', {config: config['generator-angular-fullstack']}).then(_dir => { + return runEndpointGen('foo/bar', {config: config['generator-angular-fullstack']}).then(_dir => { dir = _dir; + + return Promise.all([ + copyAsync(path.join(genDir, '/server/.jshintrc'), './server/.jshintrc'), + copyAsync(path.join(genDir, '/server/.jshintrc-spec'), './server/.jshintrc-spec') + ]); }); }); + it('should generate the expected files'); + it('should pass jscs'); - it('should pass lint'); + it('should pass lint', function() { + return jshintDir(dir, 'foo', 'foo/bar').should.be.fulfilled(); + }); }); }); \ No newline at end of file From 07d78eb971b8271d75c393b1437630dbc775d5da Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Fri, 29 Apr 2016 19:32:13 -0400 Subject: [PATCH 29/53] refactor(gen:test:endpoint): refactor `jshint` into more generic `testFile`, add jscsCmd --- src/test/endpoint.test.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/test/endpoint.test.js b/src/test/endpoint.test.js index ed06d1575..f57589f26 100644 --- a/src/test/endpoint.test.js +++ b/src/test/endpoint.test.js @@ -99,18 +99,16 @@ function runEndpointGen(name, opt={}) { gen .on('error', reject) - .on('end', () => resolve(dir)) + .on('end', () => resolve(dir)); }); } let jshintCmd = path.join(TEST_DIR, '/fixtures/node_modules/.bin/jshint'); -function jshint(_path, opt={}) { +let jscsCmd = path.join(TEST_DIR, '/fixtures/node_modules/gulp-jscs/node_modules/.bin/jscs'); +function testFile(command, _path) { _path = path.normalize(_path); - return fs.accessAsync(_path, fs.R_OK).then(err => { - let {config} = opt; - let cmd = `${jshintCmd} ${path.normalize(_path)}`; - if(config) cmd += ` --config ${config}`; - return runCmd(cmd); + return fs.accessAsync(_path, fs.R_OK).then(() => { + return runCmd(`${command} ${_path}`); }); } @@ -120,11 +118,11 @@ function jshintDir(dir, name, folder) { let regFiles = fs.readdirAsync(endpointDir) .then(files => files.filter(file => minimatch(file, '**/!(*.spec|*.mock|*.integration).js', {dot: true}))) - .map(file => jshint(path.join('./server/api/', folder, file))); + .map(file => testFile(jshintCmd, path.join('./server/api/', folder, file))); let specFiles = fs.readdirAsync(endpointDir) .then(files => files.filter(file => minimatch(file, '**/+(*.spec|*.mock|*.integration).js', {dot: true}))) - .map(file => jshint(path.join('./server/api/', folder, file), {config: 'server/.jshintrc-spec'})); + .map(file => testFile(`${jshintCmd} --config server/.jshintrc-spec`, path.join('./server/api/', folder, file))); return Promise.all([regFiles, specFiles]); } From f145af27d306a6db3962df6dcd59b2ed7fc656b6 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Fri, 29 Apr 2016 19:33:38 -0400 Subject: [PATCH 30/53] test(gen:endpoint): jshint other 2 endpoints --- src/test/endpoint.test.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/test/endpoint.test.js b/src/test/endpoint.test.js index f57589f26..31078f1dc 100644 --- a/src/test/endpoint.test.js +++ b/src/test/endpoint.test.js @@ -183,7 +183,9 @@ describe('angular-fullstack:endpoint', function() { }); }); - it('should generate the expected files'); + it('should generate the expected files', function() { + assert.file(getExpectedFiles.endpoint('Foo')); + }); it('should pass jscs'); @@ -205,7 +207,9 @@ describe('angular-fullstack:endpoint', function() { }); }); - it('should generate the expected files'); + it('should generate the expected files', function() { + assert.file(getExpectedFiles.endpoint('bar', 'foo/bar')); + }); it('should pass jscs'); From 5389c143c634627206043c6512e1ec6437f4df7f Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Fri, 29 Apr 2016 19:50:16 -0400 Subject: [PATCH 31/53] test(gen:endpoint): add jscs endpoint tests --- src/test/endpoint.test.js | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/test/endpoint.test.js b/src/test/endpoint.test.js index 31078f1dc..e0d074a98 100644 --- a/src/test/endpoint.test.js +++ b/src/test/endpoint.test.js @@ -126,6 +126,13 @@ function jshintDir(dir, name, folder) { return Promise.all([regFiles, specFiles]); } +function jscsDir(dir, name, folder) { + if(!folder) folder = name; + let endpointDir = path.join(dir, 'server/api', folder); + + return fs.readdirAsync(endpointDir) + .map(file => testFile(jscsCmd, path.join('./server/api/', folder, file)));; +} var config; var genDir; @@ -154,7 +161,8 @@ describe('angular-fullstack:endpoint', function() { return Promise.all([ copyAsync(path.join(genDir, '/server/.jshintrc'), './server/.jshintrc'), - copyAsync(path.join(genDir, '/server/.jshintrc-spec'), './server/.jshintrc-spec') + copyAsync(path.join(genDir, '/server/.jshintrc-spec'), './server/.jshintrc-spec'), + copyAsync(path.join(genDir, '/.jscsrc'), './.jscsrc') ]); }); }); @@ -163,7 +171,9 @@ describe('angular-fullstack:endpoint', function() { assert.file(getExpectedFiles.endpoint('foo')); }); - it('should pass jscs'); + it('should pass jscs', function() { + return jscsDir(dir, 'foo').should.be.fulfilled(); + }); it('should pass lint', function() { return jshintDir(dir, 'foo').should.be.fulfilled(); @@ -178,7 +188,8 @@ describe('angular-fullstack:endpoint', function() { return Promise.all([ copyAsync(path.join(genDir, '/server/.jshintrc'), './server/.jshintrc'), - copyAsync(path.join(genDir, '/server/.jshintrc-spec'), './server/.jshintrc-spec') + copyAsync(path.join(genDir, '/server/.jshintrc-spec'), './server/.jshintrc-spec'), + copyAsync(path.join(genDir, '/.jscsrc'), './.jscsrc') ]); }); }); @@ -187,7 +198,9 @@ describe('angular-fullstack:endpoint', function() { assert.file(getExpectedFiles.endpoint('Foo')); }); - it('should pass jscs'); + it('should pass jscs', function() { + return jscsDir(dir, 'Foo').should.be.fulfilled(); + }); it('should pass lint', function() { return jshintDir(dir, 'Foo').should.be.fulfilled(); @@ -202,7 +215,8 @@ describe('angular-fullstack:endpoint', function() { return Promise.all([ copyAsync(path.join(genDir, '/server/.jshintrc'), './server/.jshintrc'), - copyAsync(path.join(genDir, '/server/.jshintrc-spec'), './server/.jshintrc-spec') + copyAsync(path.join(genDir, '/server/.jshintrc-spec'), './server/.jshintrc-spec'), + copyAsync(path.join(genDir, '/.jscsrc'), './.jscsrc') ]); }); }); @@ -211,7 +225,9 @@ describe('angular-fullstack:endpoint', function() { assert.file(getExpectedFiles.endpoint('bar', 'foo/bar')); }); - it('should pass jscs'); + it('should pass jscs', function() { + return jscsDir(dir, 'foo', 'foo/bar').should.be.fulfilled(); + }); it('should pass lint', function() { return jshintDir(dir, 'foo', 'foo/bar').should.be.fulfilled(); From 93d7cb6e2c0fbb495d5309fc30b51d102917e533 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sat, 30 Apr 2016 03:37:16 -0400 Subject: [PATCH 32/53] test(gen:endpont): use jscs programmatically --- package.json | 1 + src/test/endpoint.test.js | 27 ++++++++++++++++++++++++--- templates/app/.jscsrc | 1 - 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 0e6ebf82e..168f15fed 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "gulp-plumber": "^1.1.0", "gulp-util": "^3.0.7", "jit-grunt": "~0.10.0", + "jscs": "^3.0.3", "lazypipe": "^1.0.1", "merge-stream": "^1.0.0", "minimatch": "^3.0.0", diff --git a/src/test/endpoint.test.js b/src/test/endpoint.test.js index e0d074a98..e52ae077f 100644 --- a/src/test/endpoint.test.js +++ b/src/test/endpoint.test.js @@ -7,6 +7,9 @@ Promise.promisifyAll(fs); import helpers from 'yeoman-test'; import assert from 'yeoman-assert'; import minimatch from 'minimatch'; +import Checker from 'jscs'; +const jscs = new Checker(); +jscs.registerDefaultRules(); import * as getExpectedFiles from './get-expected-files'; import { copyAsync, @@ -104,7 +107,6 @@ function runEndpointGen(name, opt={}) { } let jshintCmd = path.join(TEST_DIR, '/fixtures/node_modules/.bin/jshint'); -let jscsCmd = path.join(TEST_DIR, '/fixtures/node_modules/gulp-jscs/node_modules/.bin/jscs'); function testFile(command, _path) { _path = path.normalize(_path); return fs.accessAsync(_path, fs.R_OK).then(() => { @@ -130,8 +132,23 @@ function jscsDir(dir, name, folder) { if(!folder) folder = name; let endpointDir = path.join(dir, 'server/api', folder); - return fs.readdirAsync(endpointDir) - .map(file => testFile(jscsCmd, path.join('./server/api/', folder, file)));; + return fs.readdirAsync(endpointDir).then(files => { + return Promise.map(files, file => { + return fs.readFileAsync(path.join('server/api', folder, file), 'utf8').then(data => { + let results = jscs.checkString(data) + let errors = results.getErrorList(); + if(errors.length === 0) { + return Promise.resolve(); + } else { + errors.forEach(error => { + var colorizeOutput = true; + console.log(results.explainError(error, colorizeOutput) + '\n'); + }); + return Promise.reject(); + } + }); + }); + }); } var config; @@ -141,6 +158,10 @@ before(function() { return Promise.all([ runGen(defaultOptions).then(_dir => { genDir = _dir; + + return fs.readFileAsync(path.join(genDir, '.jscsrc'), 'utf8').then(data => { + jscs.configure(JSON.parse(data)); + }); }), getConfig(path.join(TEST_DIR, 'fixtures/.yo-rc.json')).then(_config => { _config['generator-angular-fullstack'].insertRoutes = false; diff --git a/templates/app/.jscsrc b/templates/app/.jscsrc index 8923ad53e..e05f83c6c 100644 --- a/templates/app/.jscsrc +++ b/templates/app/.jscsrc @@ -2,7 +2,6 @@ "excludeFiles": [ "client/app/app.constant.js" ], - "esnext": true, "maximumLineLength": { "value": 100, "allowComments": true, From c70d35a79ddfb3d0a022c4df337f60fc448a138d Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sat, 30 Apr 2016 04:06:12 -0400 Subject: [PATCH 33/53] test(gen): add pre-test (check fixtures) --- gulpfile.js | 2 +- src/test/pre.test.js | 46 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 src/test/pre.test.js diff --git a/gulpfile.js b/gulpfile.js index 6ffef6e65..b08c3968e 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -164,6 +164,6 @@ gulp.task('installFixtures', function() { }); gulp.task('test', () => { - return gulp.src('test/*.test.js') + return gulp.src(['test/pre.test.js', 'test/*.test.js']) .pipe(mocha()); }); diff --git a/src/test/pre.test.js b/src/test/pre.test.js new file mode 100644 index 000000000..d877cfb95 --- /dev/null +++ b/src/test/pre.test.js @@ -0,0 +1,46 @@ +'use strict'; +import path from 'path'; +import fs from 'fs'; +import _ from 'lodash'; +import Promise from 'bluebird'; +Promise.promisifyAll(fs); +import helpers from 'yeoman-test'; +import assert from 'yeoman-assert'; +import minimatch from 'minimatch'; +import * as getExpectedFiles from './get-expected-files'; +import { + copyAsync, + runCmd, + assertOnlyFiles, + getConfig +} from './test-helpers'; + +describe('test fixtures', function() { + it('should have package.json in fixtures', function() { + assert.file([path.join(__dirname, 'fixtures', 'package.json')]); + }); + + it('should have bower.json in fixtures', function() { + assert.file([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); + }); + assert.file(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); + }); + assert.file(deps); + }); +}); \ No newline at end of file From 0445fcc5a0a50f7e0048d2ad7c993cafb84db1b9 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sat, 30 Apr 2016 17:12:23 -0400 Subject: [PATCH 34/53] test(gen:main): test using existing config --- src/test/fixtures/.yo-rc.json | 47 +++++++++++++++++++---- src/test/main.test.js | 72 +++++++++++++++++++++++++++-------- test/fixtures/.yo-rc.json | 47 +++++++++++++++++++---- 3 files changed, 137 insertions(+), 29 deletions(-) diff --git a/src/test/fixtures/.yo-rc.json b/src/test/fixtures/.yo-rc.json index 716e42b6c..3f652f692 100644 --- a/src/test/fixtures/.yo-rc.json +++ b/src/test/fixtures/.yo-rc.json @@ -13,24 +13,57 @@ "registerModelsFile": "server/sqldb/index.js", "modelsNeedle": "// Insert models below", "filters": { + "js": true, "babel": true, + "flow": false, "html": true, - "less": true, + "sass": true, "uirouter": true, - "bootstrap": false, - "uibootstrap": false, + "bootstrap": true, + "uibootstrap": true, "socketio": true, "auth": true, "models": true, "mongooseModels": true, "mongoose": true, - "oauth": true, - "googleAuth": true, "grunt": true, "mocha": true, "jasmine": false, - "should": true, - "expect": false + "expect": true } + }, + "generator-ng-component": { + "routeDirectory": "client/app/", + "directiveDirectory": "client/app/", + "componentDirectory": "app/components/", + "filterDirectory": "client/app/", + "serviceDirectory": "client/app/", + "basePath": "client", + "moduleName": "", + "modulePrompt": true, + "filters": [ + "uirouter", + "mocha", + "expect", + "should", + "uirouter", + "es6" + ], + "extensions": [ + "babel", + "js", + "html", + "scss" + ], + "directiveSimpleTemplates": "", + "directiveComplexTemplates": "", + "filterTemplates": "", + "serviceTemplates": "", + "factoryTemplates": "", + "controllerTemplates": "", + "componentTemplates": "", + "decoratorTemplates": "", + "providerTemplates": "", + "routeTemplates": "" } } diff --git a/src/test/main.test.js b/src/test/main.test.js index c334174ce..8459e6fab 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -16,7 +16,6 @@ import { const defaultOptions = { buildtool: 'grunt', - script: 'js', transpiler: 'babel', markup: 'html', stylesheet: 'sass', @@ -32,10 +31,12 @@ const defaultOptions = { }; const TEST_DIR = __dirname; -function runGen(prompts) { +function runGen(prompts, opts={}) { + let options = opts.options || {skipInstall: true}; + return new Promise((resolve, reject) => { let dir; - helpers + let gen = helpers .run(require.resolve('../generators/app')) .inTmpDir(function(_dir) { // this will create a new temporary directory for each new generator run @@ -43,23 +44,30 @@ function runGen(prompts) { if(DEBUG) console.log(`TEMP DIR: ${_dir}`); dir = _dir; - // symlink our dependency directories - return Promise.all([ + let promises = [ fs.mkdirAsync(dir + '/client').then(() => { return fs.symlinkAsync(__dirname + '/fixtures/bower_components', dir + '/client/bower_components'); }), fs.symlinkAsync(__dirname + '/fixtures/node_modules', dir + '/node_modules') - ]).then(done); + ]; + + if(opts.copyConfigFile) { + promises.push(copyAsync(path.join(TEST_DIR, 'fixtures/.yo-rc.json'), path.join(dir, '.yo-rc.json'))); + } + + // symlink our dependency directories + return Promise.all(promises).then(done); }) .withGenerators([ require.resolve('../generators/endpoint'), // [helpers.createDummyGenerator(), 'ng-component:app'] ]) - .withOptions({ - skipInstall: true - }) // .withArguments(['upperCaseBug']) - .withPrompts(prompts) + .withOptions(options); + + if(prompts) gen.withPrompts(prompts); + + gen .on('error', reject) .on('end', () => resolve(dir)); }); @@ -89,15 +97,11 @@ function runEndpointGen(name, opt={}) { } describe('angular-fullstack:app', function() { - beforeEach(function() { - this.gen = runGen(defaultOptions); - }); - describe('default settings', function() { var dir; beforeEach(function() { - return this.gen.then(_dir => { + return runGen(defaultOptions).then(_dir => { dir = _dir; }); }); @@ -202,4 +206,42 @@ describe('angular-fullstack:app', function() { it('should run e2e tests successfully for production app'); //'grunt test:e2e:prod' } }); + + describe('default settings using existing `.yo-rc.json`', function() { + var dir; + + beforeEach(function() { + return runGen(null, { + copyConfigFile: true, + options: { + skipInstall: true, + skipConfig: true + } + }).then(_dir => { + dir = _dir; + }); + }); + + it('generates the proper files', function() { + const expectedFiles = getExpectedFiles.app(defaultOptions); + assert.file(expectedFiles); + return assertOnlyFiles(expectedFiles, path.normalize(dir)).should.be.fulfilled(); + }); + + it('passes JSCS', function() { + return runCmd('grunt jscs').should.be.fulfilled(); + }); + + it('passes JSHint', function() { + return runCmd('grunt jshint').should.be.fulfilled(); + }); + + it('passes client tests', function() { + return runCmd('grunt test:client').should.be.fulfilled(); + }); + + it('passes server tests', function() { + return runCmd('grunt test:server').should.be.fulfilled(); + }); + }); }); \ No newline at end of file diff --git a/test/fixtures/.yo-rc.json b/test/fixtures/.yo-rc.json index 716e42b6c..3f652f692 100644 --- a/test/fixtures/.yo-rc.json +++ b/test/fixtures/.yo-rc.json @@ -13,24 +13,57 @@ "registerModelsFile": "server/sqldb/index.js", "modelsNeedle": "// Insert models below", "filters": { + "js": true, "babel": true, + "flow": false, "html": true, - "less": true, + "sass": true, "uirouter": true, - "bootstrap": false, - "uibootstrap": false, + "bootstrap": true, + "uibootstrap": true, "socketio": true, "auth": true, "models": true, "mongooseModels": true, "mongoose": true, - "oauth": true, - "googleAuth": true, "grunt": true, "mocha": true, "jasmine": false, - "should": true, - "expect": false + "expect": true } + }, + "generator-ng-component": { + "routeDirectory": "client/app/", + "directiveDirectory": "client/app/", + "componentDirectory": "app/components/", + "filterDirectory": "client/app/", + "serviceDirectory": "client/app/", + "basePath": "client", + "moduleName": "", + "modulePrompt": true, + "filters": [ + "uirouter", + "mocha", + "expect", + "should", + "uirouter", + "es6" + ], + "extensions": [ + "babel", + "js", + "html", + "scss" + ], + "directiveSimpleTemplates": "", + "directiveComplexTemplates": "", + "filterTemplates": "", + "serviceTemplates": "", + "factoryTemplates": "", + "controllerTemplates": "", + "componentTemplates": "", + "decoratorTemplates": "", + "providerTemplates": "", + "routeTemplates": "" } } From a1f2c6df0dc6dd30634ecff07979b4ef66235fbb Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sat, 30 Apr 2016 18:31:13 -0400 Subject: [PATCH 35/53] test(gen:pre): add .bowerrc & .yo-rc.json checks --- src/test/pre.test.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/test/pre.test.js b/src/test/pre.test.js index d877cfb95..d08a90e59 100644 --- a/src/test/pre.test.js +++ b/src/test/pre.test.js @@ -17,11 +17,15 @@ import { describe('test fixtures', function() { it('should have package.json in fixtures', function() { - assert.file([path.join(__dirname, 'fixtures', 'package.json')]); + assert.file([path.join(__dirname, 'fixtures/package.json')]); }); - it('should have bower.json in fixtures', function() { - assert.file([path.join(__dirname, 'fixtures', 'bower.json')]); + it('should have .bowerrc & bower.json in fixtures', function() { + assert.file([path.join(__dirname, 'fixtures/bower.json'), path.join(__dirname, 'fixtures/.bowerrc')]); + }); + + it('should have .yo-rc.json in fixtures', function() { + assert.file([path.join(__dirname, 'fixtures/.yo-rc.json')]); }); it('should have all npm packages in fixtures/node_modules', function() { From df20c8ec95fc54524b15c268d059da5630766524 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sat, 30 Apr 2016 18:32:03 -0400 Subject: [PATCH 36/53] test(gen:main): various fixes/etc --- src/test/main.test.js | 44 +++++-------------------------------------- 1 file changed, 5 insertions(+), 39 deletions(-) diff --git a/src/test/main.test.js b/src/test/main.test.js index 8459e6fab..794f6e085 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -109,7 +109,7 @@ describe('angular-fullstack:app', function() { it('generates the proper files', function() { const expectedFiles = getExpectedFiles.app(defaultOptions); assert.file(expectedFiles); - return assertOnlyFiles(expectedFiles, path.normalize(dir)).should.eventually.be.fulfilled; + return assertOnlyFiles(expectedFiles, path.normalize(dir)).should.be.fulfilled(); }); it('passes JSCS', function() { @@ -128,7 +128,7 @@ describe('angular-fullstack:app', function() { return runCmd('grunt test:server').should.be.fulfilled(); }); - describe('with a generated endpont', function() { + describe('with a generated endpoint', function() { beforeEach(function() { getConfig(path.join(dir, '.yo-rc.json')).then(config => { return runEndpointGen('foo', {config: config['generator-angular-fullstack']}); @@ -140,7 +140,7 @@ describe('angular-fullstack:app', function() { }); }); - describe('with a generated capitalized endpont', function() { + describe('with a generated capitalized endpoint', function() { beforeEach(function() { getConfig(path.join(dir, '.yo-rc.json')).then(config => { return runEndpointGen('Foo', {config: config['generator-angular-fullstack']}); @@ -152,7 +152,7 @@ describe('angular-fullstack:app', function() { }); }); - describe('with a generated path name endpont', function() { + describe('with a generated path name endpoint', function() { beforeEach(function() { getConfig(path.join(dir, '.yo-rc.json')).then(config => { return runEndpointGen('foo/bar', {config: config['generator-angular-fullstack']}); @@ -164,41 +164,7 @@ describe('angular-fullstack:app', function() { }); }); - it('should generate expected files with path name endpoint'); - // [ - // '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' - // ] - - it('should use existing config if available'); - // this.timeout(60000); - // return copyAsync(__dirname + '/fixtures/.yo-rc.json', __dirname + '/temp/.yo-rc.json').then(() => { - // var gen = helpers.createGenerator('angular-fullstack:app', [ - // '../../generators/app', - // '../../generators/endpoint', - // [ - // helpers.createDummyGenerator(), - // 'ng-component:app' - // ] - // ], [], { - // skipInstall: true - // }); - // helpers.mockPrompt(gen, { - // skipConfig: true - // }); - // gen.run(function () { - // assert.file([ - // 'client/app/main/main.less', - // 'server/auth/google/passport.js' - // ]); - // done(); - // }); - // }); + it('should run server tests successfully with generated snake-case endpoint'); //'foo-bar' if(!process.env.SKIP_E2E) { it('should run e2e tests successfully'); //'grunt test:e2e' From a24643a446e29eb30bdedc415281cbdf95982b49 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sat, 30 Apr 2016 18:32:43 -0400 Subject: [PATCH 37/53] test(gen:main): add 'with TypeScript, Jade, Jasmine, LESS, & OAuth' suite --- src/test/main.test.js | 66 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/test/main.test.js b/src/test/main.test.js index 794f6e085..3efac0104 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -210,4 +210,70 @@ describe('angular-fullstack:app', function() { return runCmd('grunt test:server').should.be.fulfilled(); }); }); + + describe('with TypeScript, Jade, Jasmine, LESS, & OAuth', function() { + var dir; + var testOptions = { + buildtool: 'grunt', + transpiler: 'ts', + markup: 'jade', + stylesheet: 'less', + router: 'uirouter', + testing: 'jasmine', + odms: ['mongoose'], + auth: true, + oauth: ['twitterAuth', 'facebookAuth', 'googleAuth'], + socketio: true, + bootstrap: true, + uibootstrap: true + }; + + beforeEach(function() { + return runGen(testOptions).then(_dir => { + dir = _dir; + }); + }); + + it('should generate the proper files', function() { + const expectedFiles = getExpectedFiles.app(testOptions); + assert.file(expectedFiles); + return assertOnlyFiles(expectedFiles, path.normalize(dir)).should.be.fulfilled(); + }); + + it('passes JSCS', function() { + return runCmd('grunt jscs').should.be.fulfilled(); + }); + + it('passes lint', function() { + return runCmd('grunt tslint').should.be.fulfilled(); + }); + + it('should run client tests successfully', function() { + return runCmd('grunt test:client').should.be.fulfilled(); + }); + + it('should run server tests successfully', function() { + return runCmd('grunt test:server').should.be.fulfilled(); + }); + + describe('with a generated endpoint', function() { + beforeEach(function() { + getConfig(path.join(dir, '.yo-rc.json')).then(config => { + return runEndpointGen('foo', {config: config['generator-angular-fullstack']}); + }); + }); + + it('should run server tests successfully', function() { + return runCmd('grunt test:server').should.be.fulfilled(); + }); + }); + + if(!process.env.SKIP_E2E) { + it('should run e2e tests successfully'); + + //it('should run e2e tests successfully for production app', function (done) { + // runTest('grunt test:e2e:prod', this, done, 240000); + //}); + } + }); }); \ No newline at end of file From a75b1d4881b21d132b965f972d917f8816a9a5aa Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sat, 30 Apr 2016 22:30:53 -0400 Subject: [PATCH 38/53] fix(client:navbar.controller): refactor EJS, exclude constructor if empty --- .../client/components/navbar/navbar.controller.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/templates/app/client/components/navbar/navbar.controller.js b/templates/app/client/components/navbar/navbar.controller.js index 958355f9f..12ae0b351 100644 --- a/templates/app/client/components/navbar/navbar.controller.js +++ b/templates/app/client/components/navbar/navbar.controller.js @@ -9,13 +9,19 @@ class NavbarController { isCollapsed = true; //end-non-standard + <%_ if(filters.ngroute || filters.auth) { _%> - constructor(<% if(!filters.uirouter) { %>$location<% } if(!filters.uirouter && filters.auth) { %>, <% } if (filters.auth) { %>Auth<% } %>) {<% if(!filters.uirouter) { %> - this.$location = $location;<% } %> - <% if (filters.auth) { %>this.isLoggedIn = Auth.isLoggedIn; + constructor(<% if(!filters.uirouter) { %>$location<% } if(!filters.uirouter && filters.auth) { %>, <% } if (filters.auth) { %>Auth<% } %>) { + <%_ if(!filters.uirouter) { _%> + this.$location = $location; + <%_ } _%> + <%_ if (filters.auth) { _%> + this.isLoggedIn = Auth.isLoggedIn; this.isAdmin = Auth.isAdmin; this.getCurrentUser = Auth.getCurrentUser; - <% } %>}<% if(!filters.uirouter) { %> + <%_ } _%> + }<% } %> + <%_ if(!filters.uirouter) { _%> isActive(route) { return route === this.$location.path(); From 4b4db99d73985bba4db20e7664b12fafe09ccaf1 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 1 May 2016 03:35:31 -0400 Subject: [PATCH 39/53] fix(e2e:main): fix yeoman.png regex allow for revved image name, fixes e2e tests on a prod environment --- templates/app/e2e/main/main.spec(jasmine).js | 2 +- templates/app/e2e/main/main.spec(mocha).js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/app/e2e/main/main.spec(jasmine).js b/templates/app/e2e/main/main.spec(jasmine).js index 57284495a..3d56cb5d3 100644 --- a/templates/app/e2e/main/main.spec(jasmine).js +++ b/templates/app/e2e/main/main.spec(jasmine).js @@ -12,7 +12,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(/yeoman.png$/); + expect(page.imgEl.getAttribute('src')).toMatch(/yeoman(\.[a-zA-Z0-9]*)?\.png$/); expect(page.imgEl.getAttribute('alt')).toBe('I\'m Yeoman'); }); }); diff --git a/templates/app/e2e/main/main.spec(mocha).js b/templates/app/e2e/main/main.spec(mocha).js index 798b58c41..12b0781db 100644 --- a/templates/app/e2e/main/main.spec(mocha).js +++ b/templates/app/e2e/main/main.spec(mocha).js @@ -13,7 +13,7 @@ describe('Main View', function() { it('should include jumbotron with correct data', function() { <%= expect() %>page.h1El.getText()<%= to() %>.eventually.equal('\'Allo, \'Allo!'); - <%= expect() %>page.imgEl.getAttribute('src')<%= to() %>.eventually.match(/yeoman.png$/); + <%= expect() %>page.imgEl.getAttribute('src')<%= to() %>.eventually.match(/yeoman(\.[a-zA-Z0-9]*)?\.png$/); <%= expect() %>page.imgEl.getAttribute('alt')<%= to() %>.eventually.equal('I\'m Yeoman'); }); }); From d21082d9b25c801cb68aad8de9722539e7fae8b0 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 1 May 2016 04:25:33 -0400 Subject: [PATCH 40/53] style(grunt): less whitespace please --- templates/app/Gruntfile(grunt).js | 96 +++++++++++++------------------ 1 file changed, 39 insertions(+), 57 deletions(-) diff --git a/templates/app/Gruntfile(grunt).js b/templates/app/Gruntfile(grunt).js index a39fd5d18..0d137d551 100644 --- a/templates/app/Gruntfile(grunt).js +++ b/templates/app/Gruntfile(grunt).js @@ -1,7 +1,7 @@ // Generated on <%= (new Date).toISOString().split('T')[0] %> using <%= rootGeneratorName() %> <%= rootGeneratorVersion() %> 'use strict'; -module.exports = function (grunt) { +module.exports = function(grunt) { var localConfig; try { localConfig = require('./server/config/local.env'); @@ -26,7 +26,6 @@ module.exports = function (grunt) { // Define the configuration for all the tasks grunt.initConfig({ - // Project settings pkg: grunt.file.readJSON('package.json'), yeoman: { @@ -87,7 +86,7 @@ module.exports = function (grunt) { jsTest: { files: ['<%%= yeoman.client %>/{app,components}/**/*.{spec,mock}.<%= scriptExt %>'], tasks: [<% if(filters.babel) { %>'newer:jshint:all'<% } if(filters.ts) { %>'newer:tslint:all', 'newer:ts:client_test',<% } %>, 'wiredep:test', 'karma'] - },<% if (filters.stylus) { %> + },<% if(filters.stylus) { %> injectStylus: { files: ['<%%= yeoman.client %>/{app,components}/**/*.styl'], tasks: ['injector:stylus'] @@ -95,7 +94,7 @@ module.exports = function (grunt) { stylus: { files: ['<%%= yeoman.client %>/{app,components}/**/*.styl'], tasks: ['stylus', 'postcss'] - },<% } if (filters.sass) { %> + },<% } if(filters.sass) { %> injectSass: { files: ['<%%= yeoman.client %>/{app,components}/**/*.{scss,sass}'], tasks: ['injector:sass'] @@ -103,7 +102,7 @@ module.exports = function (grunt) { sass: { files: ['<%%= yeoman.client %>/{app,components}/**/*.{scss,sass}'], tasks: ['sass', 'postcss'] - },<% } if (filters.less) { %> + },<% } if(filters.less) { %> injectLess: { files: ['<%%= yeoman.client %>/{app,components}/**/*.less'], tasks: ['injector:less'] @@ -111,7 +110,7 @@ module.exports = function (grunt) { less: { files: ['<%%= yeoman.client %>/{app,components}/**/*.less'], tasks: ['less', 'postcss'] - },<% } if (filters.jade) { %> + },<% } if(filters.jade) { %> jade: { files: ['<%%= yeoman.client %>/{app,components}/**/*.jade'], tasks: ['jade'] @@ -240,14 +239,14 @@ module.exports = function (grunt) { env: { PORT: process.env.PORT || 9000 }, - callback: function (nodemon) { - nodemon.on('log', function (event) { + callback: function(nodemon) { + nodemon.on('log', function(event) { console.log(event.colour); }); // opens browser on initial server start - nodemon.on('config:update', function () { - setTimeout(function () { + nodemon.on('config:update', function() { + setTimeout(function() { require('open')('http://localhost:8080/debug?port=5858'); }, 500); }); @@ -469,9 +468,9 @@ 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) { %> + pre: [<% if(filters.stylus) { %> + 'injector:stylus',<% } if(filters.less) { %> + 'injector:less',<% } if(filters.sass) { %> 'injector:sass',<% } %> 'ngconstant'<% if(filters.ts) { %>, 'copy:constant'<% } %> @@ -596,7 +595,7 @@ module.exports = function (grunt) { NODE_ENV: 'production' }, all: localConfig - },<% if (filters.jade) { %> + },<% if(filters.jade) { %> // Compiles Jade to html jade: { @@ -688,7 +687,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: { @@ -700,7 +699,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: { @@ -742,7 +741,7 @@ module.exports = function (grunt) { ] ] } - },<% if (filters.stylus) { %> + },<% if(filters.stylus) { %> // Inject component styl into app.styl stylus: { @@ -762,7 +761,7 @@ module.exports = function (grunt) { '!<%%= yeoman.client %>/app/app.styl' ] } - },<% } if (filters.sass) { %> + },<% } if(filters.sass) { %> // Inject component scss into app.scss sass: { @@ -782,7 +781,7 @@ module.exports = function (grunt) { '!<%%= yeoman.client %>/app/app.{scss,sass}' ] } - },<% } if (filters.less) { %> + },<% } if(filters.less) { %> // Inject component less into app.less less: { @@ -826,12 +825,12 @@ module.exports = function (grunt) { }); // Used for delaying livereload until after server has restarted - grunt.registerTask('wait', function () { + grunt.registerTask('wait', function() { grunt.log.ok('Waiting for server reload...'); var done = this.async(); - setTimeout(function () { + setTimeout(function() { grunt.log.writeln('Done waiting!'); done(); }, 1500); @@ -841,12 +840,12 @@ module.exports = function (grunt) { this.async(); }); - grunt.registerTask('serve', function (target) { - if (target === 'dist') { + grunt.registerTask('serve', function(target) { + if(target === 'dist') { return grunt.task.run(['build', 'env:all', 'env:prod', 'express:prod', 'wait', 'open', 'express-keepalive']); } - if (target === 'debug') { + if(target === 'debug') { return grunt.task.run([ 'clean:server', 'env:all', @@ -876,22 +875,20 @@ module.exports = function (grunt) { ]); }); - grunt.registerTask('server', function () { + grunt.registerTask('server', function() { grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.'); grunt.task.run(['serve']); }); grunt.registerTask('test', function(target, option) { - if (target === 'server') { + if(target === 'server') { return grunt.task.run([ 'env:all', 'env:test', 'mochaTest:unit', 'mochaTest:integration' ]); - } - - else if (target === 'client') { + } else if(target === 'client') { return grunt.task.run([ 'clean:server', 'env:all', @@ -905,11 +902,8 @@ module.exports = function (grunt) { 'wiredep:test', 'karma' ]); - } - - else if (target === 'e2e') { - - if (option === 'prod') { + } else if(target === 'e2e') { + if(option === 'prod') { return grunt.task.run([ 'build', 'env:all', @@ -917,9 +911,7 @@ module.exports = function (grunt) { 'express:prod', 'protractor' ]); - } - - else { + } else { return grunt.task.run([ 'clean:server', 'env:all', @@ -937,33 +929,24 @@ module.exports = function (grunt) { 'protractor' ]); } - } - - else if (target === 'coverage') { - - if (option === 'unit') { + } else if(target === 'coverage') { + if(option === 'unit') { return grunt.task.run([ 'env:all', 'env:test', 'mocha_istanbul:unit' ]); - } - - else if (option === 'integration') { + } else if(option === 'integration') { return grunt.task.run([ 'env:all', 'env:test', 'mocha_istanbul:integration' ]); - } - - else if (option === 'check') { + } else if(option === 'check') { return grunt.task.run([ 'istanbul_check_coverage' ]); - } - - else { + } else { return grunt.task.run([ 'env:all', 'env:test', @@ -971,13 +954,12 @@ module.exports = function (grunt) { 'istanbul_check_coverage' ]); } - + } else { + grunt.task.run([ + 'test:server', + 'test:client' + ]); } - - else grunt.task.run([ - 'test:server', - 'test:client' - ]); }); grunt.registerTask('build', [ From 9d5e9451183914220aa9a77d17358acd0c8932b1 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 1 May 2016 04:31:06 -0400 Subject: [PATCH 41/53] test(gen:main): add snake-case endpoint test --- src/test/main.test.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/test/main.test.js b/src/test/main.test.js index 3efac0104..96b00036f 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -164,7 +164,17 @@ describe('angular-fullstack:app', function() { }); }); - it('should run server tests successfully with generated snake-case endpoint'); //'foo-bar' + describe('with a generated snake-case endpoint', function() { + beforeEach(function() { + getConfig(path.join(dir, '.yo-rc.json')).then(config => { + return runEndpointGen('foo-bar', {config: config['generator-angular-fullstack']}); + }); + }); + + it('should run server tests successfully', function() { + return runCmd('grunt test:server').should.be.fulfilled(); + }); + }); if(!process.env.SKIP_E2E) { it('should run e2e tests successfully'); //'grunt test:e2e' From 43ce8eef1f470943ea6362df7184bad88b1fd5b5 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 1 May 2016 04:31:57 -0400 Subject: [PATCH 42/53] test(gen:main): add e2e tests --- src/test/main.test.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/test/main.test.js b/src/test/main.test.js index 96b00036f..e83a98aa8 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -177,9 +177,13 @@ describe('angular-fullstack:app', function() { }); if(!process.env.SKIP_E2E) { - it('should run e2e tests successfully'); //'grunt test:e2e' + it('should run e2e tests successfully', function() { + return runCmd('grunt test:e2e').should.be.fulfilled(); + }); - it('should run e2e tests successfully for production app'); //'grunt test:e2e:prod' + it('should run e2e tests successfully for production app', function() { + return runCmd('grunt test:e2e:prod').should.be.fulfilled(); + }); } }); @@ -279,7 +283,15 @@ describe('angular-fullstack:app', function() { }); if(!process.env.SKIP_E2E) { - it('should run e2e tests successfully'); + it('should run e2e tests successfully', function() { + return runCmd('grunt test:e2e:prod').should.be.fulfilled(); + }); + + it('should run e2e tests successfully for production app', function() { + return runCmd('grunt test:e2e:prod').should.be.fulfilled(); + }); + } + }); //it('should run e2e tests successfully for production app', function (done) { // runTest('grunt test:e2e:prod', this, done, 240000); From 8827e939f472be719d1c286ec933ea88867f81e6 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 1 May 2016 04:33:02 -0400 Subject: [PATCH 43/53] test(gen:main): add the 2 other test suites (sql, no server) --- src/test/main.test.js | 137 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 134 insertions(+), 3 deletions(-) diff --git a/src/test/main.test.js b/src/test/main.test.js index e83a98aa8..b6cdea51c 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -293,9 +293,140 @@ describe('angular-fullstack:app', function() { } }); - //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 dir; + var testOptions = { + buildtool: 'grunt', + transpiler: 'babel', + markup: 'jade', + stylesheet: 'css', + router: 'uirouter', + testing: 'jasmine', + odms: ['sequelize'], + auth: true, + oauth: ['twitterAuth', 'facebookAuth', 'googleAuth'], + socketio: true, + bootstrap: true, + uibootstrap: true + }; + + beforeEach(function() { + return runGen(testOptions).then(_dir => { + dir = _dir; + }); + }); + + it('should generate the proper files', function() { + const expectedFiles = getExpectedFiles.app(testOptions); + assert.file(expectedFiles); + return assertOnlyFiles(expectedFiles, path.normalize(dir)).should.be.fulfilled(); + }); + + it('passes JSCS', function() { + return runCmd('grunt jscs').should.be.fulfilled(); + }); + + it('passes lint', function() { + return runCmd('grunt jshint').should.be.fulfilled(); + }); + + it('should run client tests successfully', function() { + return runCmd('grunt test:client').should.be.fulfilled(); + }); + + it('should run server tests successfully', function() { + return runCmd('grunt test:server').should.be.fulfilled(); + }); + + describe('with a generated endpoint', function() { + beforeEach(function() { + getConfig(path.join(dir, '.yo-rc.json')).then(config => { + return runEndpointGen('foo', {config: config['generator-angular-fullstack']}); + }); + }); + + it('should run server tests successfully', function() { + return runCmd('grunt test:server').should.be.fulfilled(); + }); + }); + + if(!process.env.SKIP_E2E) { + it('should run e2e tests successfully', function() { + return runCmd('grunt test:e2e:prod').should.be.fulfilled(); + }); + + it('should run e2e tests successfully for production app', function() { + return runCmd('grunt test:e2e:prod').should.be.fulfilled(); + }); + } + }); + + describe('with TypeScript, Mocha + Chai (should) and no server options', function() { + var dir; + var testOptions = { + buildtool: 'grunt', + transpiler: 'ts', + markup: 'jade', + stylesheet: 'stylus', + router: 'uirouter', + testing: 'mocha', + chai: 'should', + odms: [], + auth: false, + oauth: [], + socketio: false, + bootstrap: false, + uibootstrap: false + }; + + beforeEach(function() { + return runGen(testOptions).then(_dir => { + dir = _dir; + }); + }); + + it('should generate the proper files', function() { + const expectedFiles = getExpectedFiles.app(testOptions); + assert.file(expectedFiles); + return assertOnlyFiles(expectedFiles, path.normalize(dir)).should.be.fulfilled(); + }); + + it('passes JSCS', function() { + return runCmd('grunt jscs').should.be.fulfilled(); + }); + + it('passes lint', function() { + return runCmd('grunt tslint').should.be.fulfilled(); + }); + + it('should run client tests successfully', function() { + return runCmd('grunt test:client').should.be.fulfilled(); + }); + + it('should run server tests successfully', function() { + return runCmd('grunt test:server').should.be.fulfilled(); + }); + + describe('with a generated endpoint', function() { + beforeEach(function() { + getConfig(path.join(dir, '.yo-rc.json')).then(config => { + return runEndpointGen('foo', {config: config['generator-angular-fullstack']}); + }); + }); + + it('should run server tests successfully', function() { + return runCmd('grunt test:server').should.be.fulfilled(); + }); + }); + + if(!process.env.SKIP_E2E) { + it('should run e2e tests successfully', function() { + return runCmd('grunt test:e2e:prod').should.be.fulfilled(); + }); + + it('should run e2e tests successfully for production app', function() { + return runCmd('grunt test:e2e:prod').should.be.fulfilled(); + }); } }); }); \ No newline at end of file From 5aca55f08af7ddec213f6202939bb8d445c27ecf Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 1 May 2016 16:36:35 -0400 Subject: [PATCH 44/53] fix(e2e:prod): turn off lusca if using saucelabs --- templates/app/server/config/express.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/app/server/config/express.js b/templates/app/server/config/express.js index eeca74e6e..84f82043b 100644 --- a/templates/app/server/config/express.js +++ b/templates/app/server/config/express.js @@ -56,7 +56,7 @@ export default function(app) { * Lusca - express server security * https://github.com/krakenjs/lusca */ - if ('test' !== env) { + if (env !== 'test' && !process.env.SAUCE_USERNAME) { app.use(lusca({ csrf: { angular: true From 53a24a32242fdb155e85485db61cbde03ab59438 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 1 May 2016 17:48:30 -0400 Subject: [PATCH 45/53] test(gen:main): fix reg e2e tests running prod tests instead --- src/test/main.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/main.test.js b/src/test/main.test.js index b6cdea51c..69a3b0509 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -284,7 +284,7 @@ describe('angular-fullstack:app', function() { if(!process.env.SKIP_E2E) { it('should run e2e tests successfully', function() { - return runCmd('grunt test:e2e:prod').should.be.fulfilled(); + return runCmd('grunt test:e2e').should.be.fulfilled(); }); it('should run e2e tests successfully for production app', function() { @@ -352,7 +352,7 @@ describe('angular-fullstack:app', function() { if(!process.env.SKIP_E2E) { it('should run e2e tests successfully', function() { - return runCmd('grunt test:e2e:prod').should.be.fulfilled(); + return runCmd('grunt test').should.be.fulfilled(); }); it('should run e2e tests successfully for production app', function() { @@ -421,7 +421,7 @@ describe('angular-fullstack:app', function() { if(!process.env.SKIP_E2E) { it('should run e2e tests successfully', function() { - return runCmd('grunt test:e2e:prod').should.be.fulfilled(); + return runCmd('grunt test:e2e').should.be.fulfilled(); }); it('should run e2e tests successfully for production app', function() { From b41d4a6936da0ec9938c4bccce93202280713bc2 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 1 May 2016 19:10:46 -0400 Subject: [PATCH 46/53] test(gen:endpoint): add snake-case tests --- src/test/endpoint.test.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/test/endpoint.test.js b/src/test/endpoint.test.js index e52ae077f..aa53858d1 100644 --- a/src/test/endpoint.test.js +++ b/src/test/endpoint.test.js @@ -254,4 +254,31 @@ describe('angular-fullstack:endpoint', function() { return jshintDir(dir, 'foo', 'foo/bar').should.be.fulfilled(); }); }); + + describe('with a generated snake-case endpoint', function() { + var dir; + beforeEach(function() { + return runEndpointGen('foo-bar', {config: config['generator-angular-fullstack']}).then(_dir => { + dir = _dir; + + return Promise.all([ + copyAsync(path.join(genDir, '/server/.jshintrc'), './server/.jshintrc'), + copyAsync(path.join(genDir, '/server/.jshintrc-spec'), './server/.jshintrc-spec'), + copyAsync(path.join(genDir, '/.jscsrc'), './.jscsrc') + ]); + }); + }); + + it('should generate the expected files', function() { + assert.file(getExpectedFiles.endpoint('foo-bar')); + }); + + it('should pass jscs', function() { + return jscsDir(dir, 'foo-bar').should.be.fulfilled(); + }); + + it('should pass lint', function() { + return jshintDir(dir, 'foo-bar').should.be.fulfilled(); + }); + }); }); \ No newline at end of file From 54d4ebd370beb2a22e00af0b41a351b0c4fcc3b0 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 1 May 2016 19:11:10 -0400 Subject: [PATCH 47/53] fix(grunt): exclude jshint config if using TypeScript --- templates/app/Gruntfile(grunt).js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/templates/app/Gruntfile(grunt).js b/templates/app/Gruntfile(grunt).js index 0d137d551..7f5d4e83f 100644 --- a/templates/app/Gruntfile(grunt).js +++ b/templates/app/Gruntfile(grunt).js @@ -141,6 +141,7 @@ module.exports = function(grunt) { tasks: ['wiredep'] }, }, + <%_ if(!filters.ts) { _%> // Make sure code styles are up to par and there are no obvious mistakes jshint: { @@ -164,7 +165,8 @@ module.exports = function(grunt) { test: { src: ['<%%= yeoman.client %>/{app,components}/**/*.{spec,mock}.js'] } - },<% if(filters.ts) { %> + },<% } %> + <%_ if(filters.ts) { _%> tslint: { options: { From daf0540793dbea9457769146adaa19f378fa2156 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 1 May 2016 19:47:58 -0400 Subject: [PATCH 48/53] perf(gen:test:main): lets get some concurrency/re-use going --- src/test/main.test.js | 82 ++++++++++++++++++++++++++++++------------- 1 file changed, 57 insertions(+), 25 deletions(-) diff --git a/src/test/main.test.js b/src/test/main.test.js index 69a3b0509..1d73022aa 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -130,7 +130,7 @@ describe('angular-fullstack:app', function() { describe('with a generated endpoint', function() { beforeEach(function() { - getConfig(path.join(dir, '.yo-rc.json')).then(config => { + return getConfig(path.join(dir, '.yo-rc.json')).then(config => { return runEndpointGen('foo', {config: config['generator-angular-fullstack']}); }); }); @@ -142,7 +142,7 @@ describe('angular-fullstack:app', function() { describe('with a generated capitalized endpoint', function() { beforeEach(function() { - getConfig(path.join(dir, '.yo-rc.json')).then(config => { + return getConfig(path.join(dir, '.yo-rc.json')).then(config => { return runEndpointGen('Foo', {config: config['generator-angular-fullstack']}); }); }); @@ -154,7 +154,7 @@ describe('angular-fullstack:app', function() { describe('with a generated path name endpoint', function() { beforeEach(function() { - getConfig(path.join(dir, '.yo-rc.json')).then(config => { + return getConfig(path.join(dir, '.yo-rc.json')).then(config => { return runEndpointGen('foo/bar', {config: config['generator-angular-fullstack']}); }); }); @@ -166,7 +166,7 @@ describe('angular-fullstack:app', function() { describe('with a generated snake-case endpoint', function() { beforeEach(function() { - getConfig(path.join(dir, '.yo-rc.json')).then(config => { + return getConfig(path.join(dir, '.yo-rc.json')).then(config => { return runEndpointGen('foo-bar', {config: config['generator-angular-fullstack']}); }); }); @@ -189,8 +189,12 @@ describe('angular-fullstack:app', function() { describe('default settings using existing `.yo-rc.json`', function() { var dir; + var jscsResult; + var lintResult; + var clientTestResult; + var serverTestResult; - beforeEach(function() { + before(function() { return runGen(null, { copyConfigFile: true, options: { @@ -199,6 +203,10 @@ describe('angular-fullstack:app', function() { } }).then(_dir => { dir = _dir; + jscsResult = runCmd('grunt jscs'); + lintResult = runCmd('grunt jshint'); + clientTestResult = runCmd('grunt test:client'); + serverTestResult = runCmd('grunt test:server'); }); }); @@ -209,24 +217,28 @@ describe('angular-fullstack:app', function() { }); it('passes JSCS', function() { - return runCmd('grunt jscs').should.be.fulfilled(); + return jscsResult.should.be.fulfilled(); }); it('passes JSHint', function() { - return runCmd('grunt jshint').should.be.fulfilled(); + return lintResult.should.be.fulfilled(); }); it('passes client tests', function() { - return runCmd('grunt test:client').should.be.fulfilled(); + return clientTestResult.should.be.fulfilled(); }); it('passes server tests', function() { - return runCmd('grunt test:server').should.be.fulfilled(); + return serverTestResult.should.be.fulfilled(); }); }); describe('with TypeScript, Jade, Jasmine, LESS, & OAuth', function() { var dir; + var jscsResult; + var lintResult; + var clientTestResult; + var serverTestResult; var testOptions = { buildtool: 'grunt', transpiler: 'ts', @@ -242,9 +254,13 @@ describe('angular-fullstack:app', function() { uibootstrap: true }; - beforeEach(function() { + before(function() { return runGen(testOptions).then(_dir => { dir = _dir; + jscsResult = runCmd('grunt jscs'); + lintResult = runCmd('grunt tslint'); + clientTestResult = runCmd('grunt test:client'); + serverTestResult = runCmd('grunt test:server'); }); }); @@ -255,24 +271,24 @@ describe('angular-fullstack:app', function() { }); it('passes JSCS', function() { - return runCmd('grunt jscs').should.be.fulfilled(); + return jscsResult.should.be.fulfilled(); }); it('passes lint', function() { - return runCmd('grunt tslint').should.be.fulfilled(); + return lintResult.should.be.fulfilled(); }); it('should run client tests successfully', function() { - return runCmd('grunt test:client').should.be.fulfilled(); + return clientTestResult.should.be.fulfilled(); }); it('should run server tests successfully', function() { - return runCmd('grunt test:server').should.be.fulfilled(); + return serverTestResult.should.be.fulfilled(); }); describe('with a generated endpoint', function() { beforeEach(function() { - getConfig(path.join(dir, '.yo-rc.json')).then(config => { + return getConfig(path.join(dir, '.yo-rc.json')).then(config => { return runEndpointGen('foo', {config: config['generator-angular-fullstack']}); }); }); @@ -295,6 +311,10 @@ describe('angular-fullstack:app', function() { describe('with sequelize models, auth', function() { var dir; + var jscsResult; + var lintResult; + var clientTestResult; + var serverTestResult; var testOptions = { buildtool: 'grunt', transpiler: 'babel', @@ -313,6 +333,10 @@ describe('angular-fullstack:app', function() { beforeEach(function() { return runGen(testOptions).then(_dir => { dir = _dir; + jscsResult = runCmd('grunt jscs'); + lintResult = runCmd('grunt jshint'); + clientTestResult = runCmd('grunt test:client'); + serverTestResult = runCmd('grunt test:server'); }); }); @@ -323,24 +347,24 @@ describe('angular-fullstack:app', function() { }); it('passes JSCS', function() { - return runCmd('grunt jscs').should.be.fulfilled(); + return jscsResult.should.be.fulfilled(); }); it('passes lint', function() { - return runCmd('grunt jshint').should.be.fulfilled(); + return lintResult.should.be.fulfilled(); }); it('should run client tests successfully', function() { - return runCmd('grunt test:client').should.be.fulfilled(); + return clientTestResult.should.be.fulfilled(); }); it('should run server tests successfully', function() { - return runCmd('grunt test:server').should.be.fulfilled(); + return serverTestResult.should.be.fulfilled(); }); describe('with a generated endpoint', function() { beforeEach(function() { - getConfig(path.join(dir, '.yo-rc.json')).then(config => { + return getConfig(path.join(dir, '.yo-rc.json')).then(config => { return runEndpointGen('foo', {config: config['generator-angular-fullstack']}); }); }); @@ -363,6 +387,10 @@ describe('angular-fullstack:app', function() { describe('with TypeScript, Mocha + Chai (should) and no server options', function() { var dir; + var jscsResult; + var lintResult; + var clientTestResult; + var serverTestResult; var testOptions = { buildtool: 'grunt', transpiler: 'ts', @@ -382,6 +410,10 @@ describe('angular-fullstack:app', function() { beforeEach(function() { return runGen(testOptions).then(_dir => { dir = _dir; + jscsResult = runCmd('grunt jscs'); + lintResult = runCmd('grunt tslint'); + clientTestResult = runCmd('grunt test:client'); + serverTestResult = runCmd('grunt test:server'); }); }); @@ -392,24 +424,24 @@ describe('angular-fullstack:app', function() { }); it('passes JSCS', function() { - return runCmd('grunt jscs').should.be.fulfilled(); + return jscsResult.should.be.fulfilled(); }); it('passes lint', function() { - return runCmd('grunt tslint').should.be.fulfilled(); + return lintResult.should.be.fulfilled(); }); it('should run client tests successfully', function() { - return runCmd('grunt test:client').should.be.fulfilled(); + return clientTestResult.should.be.fulfilled(); }); it('should run server tests successfully', function() { - return runCmd('grunt test:server').should.be.fulfilled(); + return serverTestResult.should.be.fulfilled(); }); describe('with a generated endpoint', function() { beforeEach(function() { - getConfig(path.join(dir, '.yo-rc.json')).then(config => { + return getConfig(path.join(dir, '.yo-rc.json')).then(config => { return runEndpointGen('foo', {config: config['generator-angular-fullstack']}); }); }); From d64029febdde1ab2ea60ee052815a50525f35af8 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 1 May 2016 20:48:27 -0400 Subject: [PATCH 49/53] refactor(gen:test): rm dead code, promisify fs in mocha.conf, del old test file --- mocha.conf.js | 4 + src/test/endpoint.test.js | 1 - src/test/main.test.js | 1 - src/test/main.test.off.js | 765 -------------------------------------- src/test/pre.test.js | 13 - src/test/test-helpers.js | 2 - 6 files changed, 4 insertions(+), 782 deletions(-) delete mode 100644 src/test/main.test.off.js diff --git a/mocha.conf.js b/mocha.conf.js index 8fbbb39e6..4a47ecbec 100644 --- a/mocha.conf.js +++ b/mocha.conf.js @@ -1,3 +1,7 @@ 'use strict'; global.DEBUG = !!process.env.DEBUG; + +var fs = require('fs'); +var Promise = require('bluebird'); +Promise.promisifyAll(fs); diff --git a/src/test/endpoint.test.js b/src/test/endpoint.test.js index aa53858d1..d35523c65 100644 --- a/src/test/endpoint.test.js +++ b/src/test/endpoint.test.js @@ -3,7 +3,6 @@ import path from 'path'; import fs from 'fs'; import _ from 'lodash'; import Promise from 'bluebird'; -Promise.promisifyAll(fs); import helpers from 'yeoman-test'; import assert from 'yeoman-assert'; import minimatch from 'minimatch'; diff --git a/src/test/main.test.js b/src/test/main.test.js index 1d73022aa..38add4ef9 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -3,7 +3,6 @@ import path from 'path'; import fs from 'fs'; import _ from 'lodash'; import Promise from 'bluebird'; -Promise.promisifyAll(fs); import helpers from 'yeoman-test'; import assert from 'yeoman-assert'; import * as getExpectedFiles from './get-expected-files'; diff --git a/src/test/main.test.off.js b/src/test/main.test.off.js deleted file mode 100644 index 6f706cc70..000000000 --- a/src/test/main.test.off.js +++ /dev/null @@ -1,765 +0,0 @@ -/*global describe, beforeEach, it */ -'use strict'; -var path = require('path'); -var Promise = require('bluebird'); -var fs = require('fs'); -Promise.promisifyAll(fs); -var exec = require('child_process').exec; -var helpers = require('yeoman-test'); -var assert = require('yeoman-assert'); -var chai = require('chai'); -var expect = chai.expect; -var recursiveReadDir = require('recursive-readdir'); - -/**************** - * FileSystem Utils - ****************/ - -function copyAsync(src, dest) { - return fs.readFileAsync(src) - .then(data => fs.writeFileAsync(dest, data)); -} - -describe('angular-fullstack generator', function () { - var gen; - var defaultOptions = { - buildtool: 'grunt', - script: 'js', - transpiler: 'babel', - markup: 'html', - stylesheet: 'sass', - router: 'uirouter', - testing: 'mocha', - chai: 'expect', - bootstrap: true, - uibootstrap: true, - odms: ['mongoose'], - auth: true, - oauth: [], - socketio: true - }; - var dependenciesInstalled = false; - - function generatorTest(generatorType, name, mockPrompt, callback) { - gen.run(function () { - var afGenerator; - var deps = [path.join('../../generators', generatorType)]; - afGenerator = helpers.createGenerator('angular-fullstack:' + generatorType, deps, [name], { - skipInstall: true - }); - - helpers.mockPrompt(afGenerator, mockPrompt); - afGenerator.run(function () { - callback(); - }); - }); - } - - /** - * 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} topLevelPath - top level path to assert files at (optional) - * @param {Array} skip - array of paths to skip/ignore (optional) - * - */ - function assertOnlyFiles( - expectedFiles, - done, - topLevelPath='./', - skip=['node_modules', 'client/bower_components']) { - recursiveReadDir(topLevelPath, skip, function(err, actualFiles) { - if (err) return done(err); - var files = actualFiles.concat(); - - expectedFiles.forEach(function(file, i) { - var index = files.indexOf(path.normalize(file)); - if (index >= 0) { - files.splice(index, 1); - } - }); - - if (files.length !== 0) { - err = new Error('unexpected files found'); - err.expected = expectedFiles.join('\n'); - err.actual = files.join('\n'); - return done(err); - } - - 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); - var endpoint = (args[3] && typeof args[3] === 'string') ? args.splice(3, 1)[0] : null; - var timeout = (args[3] && typeof args[3] === 'number') ? args.splice(3, 1)[0] : null; - - self.timeout(timeout || 60000); - - var execFn = function() { - 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) { - generatorTest('endpoint', endpoint, {}, execFn); - } else { - gen.run(execFn); - } - } - - /** - * 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: { - sass: 'scss', - stylus: 'styl', - less: 'less', - css: 'css' - }, - markup: { - jade: 'jade', - html: 'html' - }, - script: { - js: 'js', - ts: 'ts' - } - }, - 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', - 'server/auth/' + type + '/passport.js', - ]; - }; - - - var script = mapping.script[ops.transpiler === 'ts' ? 'ts' : 'js'], - markup = mapping.markup[ops.markup], - stylesheet = mapping.stylesheet[ops.stylesheet], - models = ops.models ? ops.models : ops.odms[0]; - - /* Core Files */ - files = files.concat([ - 'client/.htaccess', - '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/footer/footer.' + stylesheet, - 'client/components/footer/footer.' + markup, - 'client/components/footer/footer.directive.' + script, - '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', - 'server/index.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.integration.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/config/environment/shared.js', - 'server/views/404.' + markup, - 'e2e/main/main.po.js', - 'e2e/main/main.spec.js', - 'e2e/components/navbar/navbar.po.js', - '.babelrc', - '.bowerrc', - '.buildignore', - '.editorconfig', - '.gitattributes', - '.gitignore', - '.travis.yml', - '.jscsrc', - '.yo-rc.json', - 'Gruntfile.js', - 'package.json', - 'bower.json', - 'karma.conf.js', - 'mocha.conf.js', - 'protractor.conf.js', - 'README.md' - ]); - - /* TypeScript */ - if (ops.transpiler === 'ts') { - files = files.concat([ - 'tsconfig.client.test.json', - 'tsconfig.client.json', - 'tsd.json', - 'tsd_test.json', - 'client/tslint.json' - ]); - } else { - files = files.concat([ - 'client/.jshintrc' - ]); - } - - /* 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, - 'client/components/modal/modal.' + stylesheet, - 'client/components/modal/modal.service.' + script - ]); - } - - /* Models - Mongoose or Sequelize */ - if (models) { - files = files.concat([ - 'server/api/thing/thing.model.js', - 'server/api/thing/thing.events.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([ - 'client/app/account/account.' + script, - 'client/app/account/login/login.' + markup, - '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.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, - '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', - 'server/api/user/index.spec.js', - 'server/api/user/user.controller.js', - 'server/api/user/user.integration.js', - 'server/api/user/user.model.js', - 'server/api/user/user.model.spec.js', - 'server/api/user/user.events.js', - 'server/auth/index.js', - 'server/auth/auth.service.js', - 'server/auth/local/index.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' - ]); - } - - 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 */ - 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; - } - - - /** - * Generator tests - */ - - beforeEach(function (done) { - this.timeout(10000); - var deps = [ - '../../generators/app', - '../../generators/endpoint', - [ - helpers.createDummyGenerator(), - 'ng-component:app' - ] - ]; - - helpers.testDirectory(path.join(__dirname, 'temp'), err => { - if(err) return done(err); - - gen = helpers.createGenerator('angular-fullstack:app', deps, [], { - skipInstall: true - }); - gen.conflicter.force = true; - done(); - }); - }); - - describe('making sure test fixtures are present', function() { - it('should have package.json in fixtures', function() { - assert.file([path.join(__dirname, 'fixtures', 'package.json')]); - }); - - it('should have bower.json in fixtures', function() { - assert.file([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); - }); - assert.file(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); - }); - assert.file(deps); - }); - }); - - describe('running app', function() { - beforeEach(function() { - this.timeout(20000); - return Promise.all([ - fs.mkdirAsync(__dirname + '/temp/client'), - fs.symlinkAsync(__dirname + '/fixtures/node_modules', __dirname + '/temp/node_modules'), - fs.symlinkAsync(__dirname +'/fixtures/bower_components', __dirname +'/temp/client/bower_components') - ]); - }); - - describe('with default options', function() { - beforeEach(function() { - helpers.mockPrompt(gen, defaultOptions); - }); - - it('should run client tests successfully', function(done) { - runTest('grunt test:client', this, done); - }); - - it.only('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 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 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 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() { - assert.file([ - '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); - return copyAsync(__dirname + '/fixtures/.yo-rc.json', __dirname + '/temp/.yo-rc.json').then(() => { - var gen = helpers.createGenerator('angular-fullstack:app', [ - '../../generators/app', - '../../generators/endpoint', - [ - helpers.createDummyGenerator(), - 'ng-component:app' - ] - ], [], { - skipInstall: true - }); - helpers.mockPrompt(gen, { - skipConfig: true - }); - gen.run(function () { - assert.file([ - 'client/app/main/main.less', - 'server/auth/google/passport.js' - ]); - done(); - }); - }); - }); - - it('should generate expected files', function (done) { - gen.run(function () { - assert.file(genFiles(defaultOptions)); - done(); - }); - }); - - it('should not generate unexpected files', function (done) { - gen.run(function () { - assertOnlyFiles(genFiles(defaultOptions), 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 other preprocessors and oauth', function() { - var testOptions = { - buildtool: 'grunt', - script: 'js', - transpiler: 'ts', - markup: 'jade', - stylesheet: 'less', - router: 'uirouter', - testing: 'jasmine', - 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 tslint', 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'); - }); - - // TODO: generator-ng-component needs TS support - // 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 () { - 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); - //}); - } - - }); - - describe('with sequelize models, auth', function() { - var testOptions = { - buildtool: 'grunt', - script: 'js', - transpiler: 'babel', - markup: 'jade', - stylesheet: 'stylus', - router: 'uirouter', - testing: 'jasmine', - odms: [ 'sequelize' ], - 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 () { - 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); - //}); - } - - }); - - describe('with other preprocessors and no server options', function() { - var testOptions = { - buildtool: 'grunt', - script: 'js', - transpiler: 'ts', - markup: 'jade', - stylesheet: 'stylus', - router: 'ngroute', - testing: 'mocha', - chai: 'should', - odms: [], - auth: false, - oauth: [], - socketio: false, - bootstrap: false, - uibootstrap: false - }; - - 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 tslint', 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'); - }); - - // TODO: generator-ng-component needs TS support - // 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 () { - 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); - //}); - } - - }); - }); -}); diff --git a/src/test/pre.test.js b/src/test/pre.test.js index d08a90e59..61c88de27 100644 --- a/src/test/pre.test.js +++ b/src/test/pre.test.js @@ -1,19 +1,6 @@ 'use strict'; import path from 'path'; -import fs from 'fs'; -import _ from 'lodash'; -import Promise from 'bluebird'; -Promise.promisifyAll(fs); -import helpers from 'yeoman-test'; import assert from 'yeoman-assert'; -import minimatch from 'minimatch'; -import * as getExpectedFiles from './get-expected-files'; -import { - copyAsync, - runCmd, - assertOnlyFiles, - getConfig -} from './test-helpers'; describe('test fixtures', function() { it('should have package.json in fixtures', function() { diff --git a/src/test/test-helpers.js b/src/test/test-helpers.js index 9745c2cfe..4a3149eff 100644 --- a/src/test/test-helpers.js +++ b/src/test/test-helpers.js @@ -3,11 +3,9 @@ import path from 'path'; import fs from 'fs'; import _ from 'lodash'; import Promise from 'bluebird'; -Promise.promisifyAll(fs); import {exec} from 'child_process'; import helpers from 'yeoman-test'; import assert from 'yeoman-assert'; -import * as getExpectedFiles from './get-expected-files'; import recursiveReadDir from 'recursive-readdir'; export function copyAsync(src, dest) { From 3febf4c722bcdc7f771768a8d7b9f411438641c4 Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 1 May 2016 20:50:15 -0400 Subject: [PATCH 50/53] refactor(gen:test): move runGen to test-helpers, rename getConfig to readJSON --- src/test/endpoint.test.js | 36 ++------------------ src/test/main.test.js | 59 +++++--------------------------- src/test/test-helpers.js | 71 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 82 insertions(+), 84 deletions(-) diff --git a/src/test/endpoint.test.js b/src/test/endpoint.test.js index d35523c65..16cb76c38 100644 --- a/src/test/endpoint.test.js +++ b/src/test/endpoint.test.js @@ -14,7 +14,8 @@ import { copyAsync, runCmd, assertOnlyFiles, - getConfig + readJSON, + runGen } from './test-helpers'; const TEST_DIR = __dirname; @@ -35,37 +36,6 @@ const defaultOptions = { oauth: [], socketio: true }; -function runGen(prompts) { - return new Promise((resolve, reject) => { - let dir; - helpers - .run(require.resolve('../generators/app')) - .inTmpDir(function(_dir) { - // this will create a new temporary directory for each new generator run - var done = this.async(); - if(DEBUG) console.log(`TEMP DIR: ${_dir}`); - dir = _dir; - - // symlink our dependency directories - return Promise.all([ - fs.mkdirAsync(dir + '/client').then(() => { - return fs.symlinkAsync(__dirname + '/fixtures/bower_components', dir + '/client/bower_components'); - }), - fs.symlinkAsync(__dirname + '/fixtures/node_modules', dir + '/node_modules') - ]).then(done); - }) - .withGenerators([ - require.resolve('../generators/endpoint'), - // [helpers.createDummyGenerator(), 'ng-component:app'] - ]) - .withOptions({ - skipInstall: true - }) - .withPrompts(prompts) - .on('error', reject) - .on('end', () => resolve(dir)); - }); -} function runEndpointGen(name, opt={}) { let prompts = opt.prompts || {}; @@ -162,7 +132,7 @@ before(function() { jscs.configure(JSON.parse(data)); }); }), - getConfig(path.join(TEST_DIR, 'fixtures/.yo-rc.json')).then(_config => { + readJSON(path.join(TEST_DIR, 'fixtures/.yo-rc.json')).then(_config => { _config['generator-angular-fullstack'].insertRoutes = false; _config['generator-angular-fullstack'].pluralizeRoutes = false; _config['generator-angular-fullstack'].insertSockets = false; diff --git a/src/test/main.test.js b/src/test/main.test.js index 38add4ef9..cfe269f2a 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -10,7 +10,8 @@ import { copyAsync, runCmd, assertOnlyFiles, - getConfig + readJSON, + runGen } from './test-helpers'; const defaultOptions = { @@ -30,48 +31,6 @@ const defaultOptions = { }; const TEST_DIR = __dirname; -function runGen(prompts, opts={}) { - let options = opts.options || {skipInstall: true}; - - return new Promise((resolve, reject) => { - let dir; - let gen = helpers - .run(require.resolve('../generators/app')) - .inTmpDir(function(_dir) { - // this will create a new temporary directory for each new generator run - var done = this.async(); - if(DEBUG) console.log(`TEMP DIR: ${_dir}`); - dir = _dir; - - let promises = [ - fs.mkdirAsync(dir + '/client').then(() => { - return fs.symlinkAsync(__dirname + '/fixtures/bower_components', dir + '/client/bower_components'); - }), - fs.symlinkAsync(__dirname + '/fixtures/node_modules', dir + '/node_modules') - ]; - - if(opts.copyConfigFile) { - promises.push(copyAsync(path.join(TEST_DIR, 'fixtures/.yo-rc.json'), path.join(dir, '.yo-rc.json'))); - } - - // symlink our dependency directories - return Promise.all(promises).then(done); - }) - .withGenerators([ - require.resolve('../generators/endpoint'), - // [helpers.createDummyGenerator(), 'ng-component:app'] - ]) - // .withArguments(['upperCaseBug']) - .withOptions(options); - - if(prompts) gen.withPrompts(prompts); - - gen - .on('error', reject) - .on('end', () => resolve(dir)); - }); -} - function runEndpointGen(name, opt={}) { let prompts = opt.prompts || {}; let options = opt.options || {}; @@ -129,7 +88,7 @@ describe('angular-fullstack:app', function() { describe('with a generated endpoint', function() { beforeEach(function() { - return getConfig(path.join(dir, '.yo-rc.json')).then(config => { + return readJSON(path.join(dir, '.yo-rc.json')).then(config => { return runEndpointGen('foo', {config: config['generator-angular-fullstack']}); }); }); @@ -141,7 +100,7 @@ describe('angular-fullstack:app', function() { describe('with a generated capitalized endpoint', function() { beforeEach(function() { - return getConfig(path.join(dir, '.yo-rc.json')).then(config => { + return readJSON(path.join(dir, '.yo-rc.json')).then(config => { return runEndpointGen('Foo', {config: config['generator-angular-fullstack']}); }); }); @@ -153,7 +112,7 @@ describe('angular-fullstack:app', function() { describe('with a generated path name endpoint', function() { beforeEach(function() { - return getConfig(path.join(dir, '.yo-rc.json')).then(config => { + return readJSON(path.join(dir, '.yo-rc.json')).then(config => { return runEndpointGen('foo/bar', {config: config['generator-angular-fullstack']}); }); }); @@ -165,7 +124,7 @@ describe('angular-fullstack:app', function() { describe('with a generated snake-case endpoint', function() { beforeEach(function() { - return getConfig(path.join(dir, '.yo-rc.json')).then(config => { + return readJSON(path.join(dir, '.yo-rc.json')).then(config => { return runEndpointGen('foo-bar', {config: config['generator-angular-fullstack']}); }); }); @@ -287,7 +246,7 @@ describe('angular-fullstack:app', function() { describe('with a generated endpoint', function() { beforeEach(function() { - return getConfig(path.join(dir, '.yo-rc.json')).then(config => { + return readJSON(path.join(dir, '.yo-rc.json')).then(config => { return runEndpointGen('foo', {config: config['generator-angular-fullstack']}); }); }); @@ -363,7 +322,7 @@ describe('angular-fullstack:app', function() { describe('with a generated endpoint', function() { beforeEach(function() { - return getConfig(path.join(dir, '.yo-rc.json')).then(config => { + return readJSON(path.join(dir, '.yo-rc.json')).then(config => { return runEndpointGen('foo', {config: config['generator-angular-fullstack']}); }); }); @@ -440,7 +399,7 @@ describe('angular-fullstack:app', function() { describe('with a generated endpoint', function() { beforeEach(function() { - return getConfig(path.join(dir, '.yo-rc.json')).then(config => { + return readJSON(path.join(dir, '.yo-rc.json')).then(config => { return runEndpointGen('foo', {config: config['generator-angular-fullstack']}); }); }); diff --git a/src/test/test-helpers.js b/src/test/test-helpers.js index 4a3149eff..5a192e936 100644 --- a/src/test/test-helpers.js +++ b/src/test/test-helpers.js @@ -8,6 +8,14 @@ import helpers from 'yeoman-test'; import assert from 'yeoman-assert'; import recursiveReadDir from 'recursive-readdir'; +const TEST_DIR = __dirname; + +/** + * Copy file from src to dest + * @param {string} src + * @param {string} dest + * @returns {Promise} + */ export function copyAsync(src, dest) { return fs.readFileAsync(src) .then(data => fs.writeFileAsync(dest, data)); @@ -37,6 +45,13 @@ export function runCmd(cmd) { }); } +/** + * Assert that only the expected files are present + * @param {string[]} expectedFiles - array of expected files + * @param {string} [topLevelPath='./'] - root dir of expected files to recursively search + * @param {string[]} [skip=['node_modules','bower_components']] - files/folders recursiveReadDir should skip + * @returns {Promise} + */ export function assertOnlyFiles(expectedFiles, topLevelPath='./', skip=['node_modules', 'bower_components']) { return new Promise((resolve, reject) => { recursiveReadDir(topLevelPath, skip, function(err, actualFiles) { @@ -55,8 +70,62 @@ export function assertOnlyFiles(expectedFiles, topLevelPath='./', skip=['node_mo }); } -export function getConfig(path) { +/** + * Read JSON from a file + * @param {string} path + * @returns {Promise} - parsed JSON + */ +export function readJSON(path) { return fs.readFileAsync(path, 'utf8').then(data => { return JSON.parse(data); }); } + +/** + * Run angular-fullstack:app + * @param {object} [prompts] + * @param {object} [opts={}] + * @param {boolean} [opts.copyConfigFile] - copy default .yo-rc.json + * @returns {Promise} + */ +export function runGen(prompts, opts={}) { + let options = opts.options || {skipInstall: true}; + + return new Promise((resolve, reject) => { + let dir; + let gen = helpers + .run(require.resolve('../generators/app')) + .inTmpDir(function(_dir) { + // this will create a new temporary directory for each new generator run + var done = this.async(); + if(DEBUG) console.log(`TEMP DIR: ${_dir}`); + dir = _dir; + + let promises = [ + fs.mkdirAsync(dir + '/client').then(() => { + return fs.symlinkAsync(__dirname + '/fixtures/bower_components', dir + '/client/bower_components'); + }), + fs.symlinkAsync(__dirname + '/fixtures/node_modules', dir + '/node_modules') + ]; + + if(opts.copyConfigFile) { + promises.push(copyAsync(path.join(TEST_DIR, 'fixtures/.yo-rc.json'), path.join(dir, '.yo-rc.json'))); + } + + // symlink our dependency directories + return Promise.all(promises).then(done); + }) + .withGenerators([ + require.resolve('../generators/endpoint'), + // [helpers.createDummyGenerator(), 'ng-component:app'] + ]) + // .withArguments(['upperCaseBug']) + .withOptions(options); + + if(prompts) gen.withPrompts(prompts); + + gen + .on('error', reject) + .on('end', () => resolve(dir)); + }); +} \ No newline at end of file From 97ddb8bc95d60316ff70644c603a7c6830e7155c Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Sun, 1 May 2016 23:54:40 -0400 Subject: [PATCH 51/53] chore(package): bump yeoman-test to ^1.3.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 168f15fed..6d407e4c0 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "shelljs": "^0.6.0", "should": "^8.3.1", "yeoman-assert": "^2.0.0", - "yeoman-test": "^1.1.0" + "yeoman-test": "^1.3.0" }, "engines": { "node": "^5.10.1", From ae514e117e079a85108b54812476479a3b85bafe Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Mon, 2 May 2016 15:20:26 -0400 Subject: [PATCH 52/53] test(gen): slow tests are 500ms and above [skip ci] --- gulpfile.js | 1 + 1 file changed, 1 insertion(+) diff --git a/gulpfile.js b/gulpfile.js index b08c3968e..0f6dcdf23 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -22,6 +22,7 @@ const mocha = lazypipe() .pipe(gulpMocha, { reporter: 'spec', timeout: 120000, + slow: 500, globals: { should: require('should') }, From 3b613e70e1f8973954689a4f6dab11fe66075b5e Mon Sep 17 00:00:00 2001 From: Andrew Koroluk Date: Mon, 2 May 2016 15:26:04 -0400 Subject: [PATCH 53/53] test(gen:main): retry e2e tests twice --- src/test/main.test.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/main.test.js b/src/test/main.test.js index cfe269f2a..849b221b5 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -136,10 +136,12 @@ describe('angular-fullstack:app', function() { if(!process.env.SKIP_E2E) { it('should run e2e tests successfully', function() { + this.retries(2); return runCmd('grunt test:e2e').should.be.fulfilled(); }); it('should run e2e tests successfully for production app', function() { + this.retries(2); return runCmd('grunt test:e2e:prod').should.be.fulfilled(); }); } @@ -258,10 +260,12 @@ describe('angular-fullstack:app', function() { if(!process.env.SKIP_E2E) { it('should run e2e tests successfully', function() { + this.retries(2); return runCmd('grunt test:e2e').should.be.fulfilled(); }); it('should run e2e tests successfully for production app', function() { + this.retries(2); return runCmd('grunt test:e2e:prod').should.be.fulfilled(); }); } @@ -334,10 +338,12 @@ describe('angular-fullstack:app', function() { if(!process.env.SKIP_E2E) { it('should run e2e tests successfully', function() { + this.retries(2); return runCmd('grunt test').should.be.fulfilled(); }); it('should run e2e tests successfully for production app', function() { + this.retries(2); return runCmd('grunt test:e2e:prod').should.be.fulfilled(); }); } @@ -411,10 +417,12 @@ describe('angular-fullstack:app', function() { if(!process.env.SKIP_E2E) { it('should run e2e tests successfully', function() { + this.retries(2); return runCmd('grunt test:e2e').should.be.fulfilled(); }); it('should run e2e tests successfully for production app', function() { + this.retries(2); return runCmd('grunt test:e2e:prod').should.be.fulfilled(); }); }