├── .gitignore ├── .jscsrc ├── .jshintrc ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── app └── index.js ├── assets ├── angular.png ├── bower.png ├── cordova.png ├── gulp.png ├── libsass.png └── yeoman.png ├── c └── index.js ├── cp └── index.js ├── d └── index.js ├── decorator └── index.js ├── default-settings.js ├── f └── index.js ├── filter └── index.js ├── helper.js ├── p └── index.js ├── package-lock.json ├── package.json ├── r └── index.js ├── s └── index.js ├── sub-generator-base.js ├── templates ├── app │ ├── _app.js │ ├── _app.spec.js │ ├── _component.scss │ ├── _controller.scss │ ├── _directive.scss │ ├── component.html │ ├── component.js │ ├── component.spec.js │ ├── controller.html │ ├── controller.js │ ├── controller.spec.js │ ├── decorator.js │ ├── decorator.spec.js │ ├── directive.html │ ├── directive.js │ ├── directive.spec.js │ ├── factory.js │ ├── factory.spec.js │ ├── filter.js │ ├── filter.spec.js │ ├── provider.js │ ├── provider.spec.js │ ├── routes.js │ ├── routes.spec.js │ ├── service.js │ └── service.spec.js ├── e2e-tests │ ├── example.e2e.js │ └── po │ │ └── home.po.js ├── index.html ├── root │ ├── README.md │ ├── _bower.json │ ├── _bowerrc │ ├── _config.xml │ ├── _editorconfig │ ├── _gitattributes │ ├── _gitignore │ ├── _gulpfile.js │ ├── _jshintrc │ ├── _karma-e2e.conf.js │ ├── _karma.conf.js │ ├── _package.json │ └── _travis.yml ├── styles │ ├── _functions │ │ └── _some-function.scss │ ├── _mixins │ │ └── _some-mixin.scss │ ├── _placeholders │ │ └── _some-placeholder.scss │ ├── _variables.scss │ ├── base │ │ ├── _buttons.scss │ │ ├── _fonts.scss │ │ ├── _forms.scss │ │ ├── _icons.scss │ │ ├── _lists.scss │ │ ├── _page.scss │ │ ├── _tables.scss │ │ └── _typography.scss │ └── main.scss └── tasks │ ├── build.js │ ├── config.js │ ├── cordova.js │ ├── deploy.js │ ├── dev.js │ └── e2e.js ├── test-app ├── injections.spec.js └── styles.spec.js └── test ├── app.spec.js ├── component.spec.js ├── controller.spec.js ├── custom-templates-from-file.spec.js ├── custom-templates-in-yo-rc.spec.js ├── decorator.spec.js ├── directive.spec.js ├── factory.spec.js ├── filter.spec.js ├── helper.spec.js ├── provider.spec.js ├── route.spec.js └── service.spec.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .tmp 3 | .sass-cache 4 | .grunt 5 | bower_components 6 | dist/example 7 | .idea/ 8 | *.DS_* 9 | npm-debug.log 10 | coverage/ 11 | .test-instance/ -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "requireCurlyBraces": [ 3 | "if", 4 | "else", 5 | "for", 6 | "while", 7 | "do", 8 | "try", 9 | "catch" 10 | ], 11 | "requireOperatorBeforeLineBreak": true, 12 | "requireCamelCaseOrUpperCaseIdentifiers": { 13 | "allowedPrefixes": [ 14 | "opt_" 15 | ], 16 | "allExcept": [ 17 | "var_args" 18 | ] 19 | }, 20 | "maximumLineLength": false, 21 | "validateIndentation": 4, 22 | "validateQuoteMarks": "'", 23 | "disallowMultipleLineStrings": true, 24 | "disallowMixedSpacesAndTabs": true, 25 | "disallowTrailingWhitespace": true, 26 | "disallowSpaceAfterPrefixUnaryOperators": true, 27 | "disallowMultipleVarDecl": true, 28 | "disallowKeywordsOnNewLine": [ 29 | "else" 30 | ], 31 | "requireSpaceAfterKeywords": [ 32 | "if", 33 | "else", 34 | "for", 35 | "while", 36 | "do", 37 | "switch", 38 | "return", 39 | "try", 40 | "catch" 41 | ], 42 | "requireSpaceBeforeBinaryOperators": [ 43 | "=", 44 | "+=", 45 | "-=", 46 | "*=", 47 | "/=", 48 | "%=", 49 | "<<=", 50 | ">>=", 51 | ">>>=", 52 | "&=", 53 | "|=", 54 | "^=", 55 | "+=", 56 | "+", 57 | "-", 58 | "*", 59 | "/", 60 | "%", 61 | "<<", 62 | ">>", 63 | ">>>", 64 | "&", 65 | "|", 66 | "^", 67 | "&&", 68 | "||", 69 | "===", 70 | "==", 71 | ">=", 72 | "<=", 73 | "<", 74 | ">", 75 | "!=", 76 | "!==" 77 | ], 78 | "requireSpaceAfterBinaryOperators": true, 79 | "requireSpacesInConditionalExpression": true, 80 | "requireSpaceBeforeBlockStatements": true, 81 | "requireSpacesInForStatement": true, 82 | "requireLineFeedAtFileEnd": true, 83 | "requireSpacesInFunctionExpression": { 84 | "beforeOpeningCurlyBrace": true 85 | }, 86 | "disallowSpacesInAnonymousFunctionExpression": { 87 | "beforeOpeningRoundBrace": true 88 | }, 89 | "disallowSpacesInsideObjectBrackets": "all", 90 | "disallowSpacesInsideArrayBrackets": "all", 91 | "disallowSpacesInsideParentheses": true, 92 | "disallowMultipleLineBreaks": false, 93 | "disallowNewlineBeforeBlockStatements": true, 94 | "disallowKeywords": [ 95 | "with" 96 | ], 97 | "disallowSpacesInFunctionExpression": { 98 | "beforeOpeningRoundBrace": true 99 | }, 100 | "disallowSpacesInFunctionDeclaration": { 101 | "beforeOpeningRoundBrace": true 102 | }, 103 | "disallowSpacesInCallExpression": true, 104 | "disallowSpaceAfterObjectKeys": true, 105 | "requireSpaceBeforeObjectValues": true, 106 | "requireCapitalizedConstructors": true, 107 | "requireDotNotation": true, 108 | "requireSemicolons": true, 109 | "validateParameterSeparator": ", ", 110 | "jsDoc": { 111 | "checkParamNames": true, 112 | "requireParamTypes": true, 113 | "checkRedundantParams": true, 114 | "checkReturnTypes": true, 115 | "checkRedundantReturns": true, 116 | "requireReturnTypes": true, 117 | "checkTypes": true, 118 | "checkRedundantAccess": true, 119 | "requireNewlineAfterDescription": true 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "esnext": true, 5 | "bitwise": true, 6 | "camelcase": true, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "indent": 4, 10 | "latedef": "nofunc", 11 | "noarg": true, 12 | "quotmark": "single", 13 | "undef": true, 14 | "unused": true, 15 | "strict": true, 16 | "trailing": true, 17 | "smarttabs": true, 18 | "globals": { 19 | "angular": false, 20 | "browser": false, 21 | "jasmine": false, 22 | "describe": false, 23 | "xdescribe": false, 24 | "before": false, 25 | "beforeEach": false, 26 | "after": false, 27 | "afterEach": false, 28 | "it": false, 29 | "xit": false, 30 | "it": false, 31 | "inject": false, 32 | "expect": false, 33 | "spyOn": false 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | before_install: 3 | - "export DISPLAY=:99.0" 4 | - "sh -e /etc/init.d/xvfb start" 5 | node_js: 6 | - '5' 7 | before_script: 8 | - npm install -g istanbul 9 | - npm install -g mocha 10 | 11 | script: make test-full 12 | after_success: 13 | - make coveralls 14 | addons: 15 | apt: 16 | sources: 17 | - ubuntu-toolchain-r-test 18 | packages: 19 | - gcc-4.9 20 | - g++-4.9 21 | before_install: 22 | - export CC="gcc-4.9" CXX="g++-4.9" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Johannes Millan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TESTS = ./test/**/*.spec.js 2 | INSTANCE_TESTS_DIR = .test-instance 3 | INSTANCE_TESTS = ./test-app/**/*.spec.js 4 | REPORTER = spec 5 | COVERAGE_REPORT = ./coverage/lcov.info 6 | COVERALLS = ./node_modules/.bin/coveralls 7 | 8 | test: test-mocha 9 | 10 | test-mocha: 11 | @NODE_ENV=test ./node_modules/.bin/mocha \ 12 | --timeout 200 \ 13 | --reporter $(REPORTER) \ 14 | $(TESTS) 15 | 16 | test-full: ./node_modules/.bin/istanbul create-app-instance test-app-instance test-node-module 17 | 18 | istanbul: 19 | ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- -R spec $(TESTS) 20 | 21 | coveralls: 22 | cat $(COVERAGE_REPORT) | $(COVERALLS) 23 | 24 | cov-html: test-cov html-cov-report 25 | 26 | html-cov-report: 27 | ./node_modules/.bin/istanbul report html 28 | 29 | npm: 30 | npm publish ./ 31 | 32 | check: 33 | travis-lint .travis.yml 34 | 35 | clean: 36 | rm -rf ./coverage 37 | 38 | test-app-instance: 39 | ./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- -R spec $(INSTANCE_TESTS) 40 | 41 | create-app-instance: 42 | rm -rf $(INSTANCE_TESTS_DIR)/ 43 | mkdir $(INSTANCE_TESTS_DIR) 44 | npm install -g yo bower node-gyp 45 | npm link 46 | cd $(INSTANCE_TESTS_DIR) && echo "CDing into $(INSTANCE_TESTS_DIR)" && \ 47 | yo moda --skip-install --skipPrompts && \ 48 | npm install && \ 49 | bower install 50 | 51 | test-node-module: 52 | rm -rf $(INSTANCE_TESTS_DIR)/ 53 | mkdir $(INSTANCE_TESTS_DIR) 54 | npm install -g yo bower generator-moda node-gyp 55 | cd $(INSTANCE_TESTS_DIR) && echo "CDing into $(INSTANCE_TESTS_DIR)" && \ 56 | yo moda --skipPrompts --skip-install && \ 57 | npm cache clean && \ 58 | npm install && \ 59 | bower install && \ 60 | gulp injectAll && \ 61 | yo moda:r hello-route --useDefaults && \ 62 | yo moda:d hello-directive --useDefaults && \ 63 | yo moda:s hello-service --useDefaults && \ 64 | gulp testSingle && \ 65 | gulp build -------------------------------------------------------------------------------- /app/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var fs = require('fs'); 3 | var path = require('path'); 4 | var util = require('util'); 5 | var helper = require('../helper.js'); 6 | var defaultSettings = require('../default-settings.js'); 7 | var yeoman = require('yeoman-generator'); 8 | var wiredep = require('wiredep'); 9 | var chalk = require('chalk'); 10 | var _s = require('underscore.string'); 11 | 12 | module.exports = yeoman.Base.extend({ 13 | constructor: function() { 14 | yeoman.Base.apply(this, arguments); 15 | 16 | // get app name 17 | this.argument('appname', {type: String, required: false}); 18 | this.appname = this.appname || path.basename(process.cwd()); 19 | this.appname = _s.camelize(_s.slugify(_s.humanize(this.appname))); 20 | this.slugAppName = _s.slugify(this.appname); 21 | this.humanizedAppName = _s.humanize(this.appname); 22 | this.scriptAppName = this.appname; 23 | 24 | 25 | // get app path 26 | try { 27 | this.env.options.appPath = require(path.join(process.cwd(), 'bower.json')).appPath; 28 | } catch (e) { 29 | } 30 | this.env.options.appPath = this.env.options.appPath || 'app'; 31 | this.options.appPath = this.env.options.appPath; 32 | this.appPath = this.env.options.appPath; 33 | 34 | 35 | this.pkg = require('../package.json'); 36 | this.sourceRoot(path.join(__dirname, '../templates')); 37 | }, 38 | 39 | config: function() { 40 | this.config.defaults(defaultSettings); 41 | }, 42 | 43 | askForModules: function askForModules() { 44 | var cb = this.async(); 45 | 46 | if (this.options.skipPrompts) { 47 | cb(); 48 | // set defaults if skipping this one 49 | this.animateModule = false; 50 | this.ariaModule = false; 51 | this.cookiesModule = false; 52 | this.messagesModule = false; 53 | this.resourceModule = false; 54 | this.routeModule = false; 55 | this.uiRouterModule = false; 56 | this.ngFabFormModule = false; 57 | this.sanitizeModule = false; 58 | this.ngMaterialModule = false; 59 | this.touchModule = false; 60 | return; 61 | } 62 | 63 | var prompts = [{ 64 | type: 'checkbox', 65 | name: 'modules', 66 | message: 'Which modules would you like to include?', 67 | choices: [ 68 | { 69 | value: 'animateModule', 70 | name: 'angular-animate.js', 71 | checked: true 72 | }, { 73 | value: 'ariaModule', 74 | name: 'angular-aria.js', 75 | checked: true 76 | }, { 77 | value: 'cookiesModule', 78 | name: 'angular-cookies.js', 79 | checked: false 80 | }, { 81 | value: 'resourceModule', 82 | name: 'angular-resource.js', 83 | checked: true 84 | }, { 85 | value: 'sanitizeModule', 86 | name: 'angular-sanitize.js', 87 | checked: false 88 | }, { 89 | value: 'touchModule', 90 | name: 'angular-touch.js', 91 | checked: false 92 | }, { 93 | value: 'ngMaterialModule', 94 | name: 'angular material design', 95 | checked: false 96 | }, { 97 | value: 'ngFabFormModule', 98 | name: 'ng-fab-form (form helper)', 99 | checked: false 100 | }, { 101 | value: 'messagesModule', 102 | name: 'angular-messages.js (included with ngFabForm)', 103 | checked: false 104 | }, { 105 | value: 'uiRouterModule', 106 | name: 'ui-router.js', 107 | checked: true 108 | }, { 109 | value: 'routeModule', 110 | name: 'angular-route.js (standard router dot\'t use with ui-router)', 111 | checked: false 112 | } 113 | ] 114 | }]; 115 | 116 | this.prompt(prompts, function(props) { 117 | var hasMod = function(mod) { 118 | // prevent test errors if no values mocked 119 | if (props && props.modules) { 120 | return props.modules.indexOf(mod) !== -1; 121 | } 122 | }; 123 | this.animateModule = hasMod('animateModule'); 124 | this.ariaModule = hasMod('ariaModule'); 125 | this.cookiesModule = hasMod('cookiesModule'); 126 | this.messagesModule = hasMod('messagesModule'); 127 | this.resourceModule = hasMod('resourceModule'); 128 | this.routeModule = hasMod('routeModule'); 129 | this.uiRouterModule = hasMod('uiRouterModule'); 130 | this.ngFabFormModule = hasMod('ngFabFormModule'); 131 | this.sanitizeModule = hasMod('sanitizeModule'); 132 | this.ngMaterialModule = hasMod('ngMaterialModule'); 133 | this.touchModule = hasMod('touchModule'); 134 | 135 | var angMods = []; 136 | 137 | if (this.animateModule) { 138 | angMods.push('\'ngAnimate\''); 139 | } 140 | 141 | if (this.ariaModule) { 142 | angMods.push('\'ngAria\''); 143 | } 144 | 145 | if (this.cookiesModule) { 146 | angMods.push('\'ngCookies\''); 147 | } 148 | 149 | if (this.messagesModule) { 150 | angMods.push('\'ngMessages\''); 151 | } 152 | 153 | if (this.resourceModule) { 154 | angMods.push('\'ngResource\''); 155 | } 156 | 157 | if (this.routeModule) { 158 | angMods.push('\'ngRoute\''); 159 | this.env.options.ngRoute = true; 160 | } 161 | 162 | if (this.sanitizeModule) { 163 | angMods.push('\'ngSanitize\''); 164 | } 165 | 166 | if (this.touchModule) { 167 | angMods.push('\'ngTouch\''); 168 | } 169 | 170 | if (this.uiRouterModule) { 171 | angMods.push('\'ui.router\''); 172 | this.config.set('uiRouter', true); 173 | this.env.options.uiRouter = true; 174 | } 175 | 176 | if (this.ngMaterialModule) { 177 | angMods.push('\'ngMaterial\''); 178 | this.env.options.ngMaterial = true; 179 | } 180 | 181 | if (this.ngFabFormModule) { 182 | angMods.push('\'ngFabForm\''); 183 | } 184 | 185 | if (angMods.length) { 186 | this.env.options.angularDeps = '\n ' + angMods.join(',\n ') + '\n '; 187 | } 188 | 189 | cb(); 190 | }.bind(this)); 191 | }, 192 | 193 | askForCodingStyle: function askForModules() { 194 | var cb = this.async(); 195 | 196 | if (this.options.skipPrompts) { 197 | cb(); 198 | return; 199 | } 200 | 201 | var prompts = [{ 202 | type: 'list', 203 | name: 'jscsCfg', 204 | message: 'What javascript coding style would you like to use (JSCS - see: http://jscs.info/)?', 205 | choices: [ 206 | { 207 | value: 'emptyCfg', 208 | name: 'empty configuration file' 209 | }, 210 | { 211 | value: 'manualCfg', 212 | name: 'configure via --auto-configure' 213 | } 214 | ] 215 | }]; 216 | 217 | this.prompt(prompts, function(props) { 218 | var that = this; 219 | 220 | fs.writeFile('./.jscsrc', '{}', function(err) { 221 | if (err) { 222 | return console.log(err); 223 | } 224 | if (props.jscsCfg === 'manualCfg') { 225 | var jscsrcPath = path.join('./.jscsrc') 226 | that.spawnCommand('jscs', ['--auto-configure', jscsrcPath]) 227 | .on('close', function() { 228 | cb(); 229 | }); 230 | } else { 231 | cb(); 232 | } 233 | }); 234 | 235 | }.bind(this)); 236 | }, 237 | 238 | readOptions: function readOptions() { 239 | this.ngRoute = this.env.options.ngRoute; 240 | this.uiRouter = this.env.options.uiRouter; 241 | this.ngMaterial = this.env.options.ngMaterial; 242 | }, 243 | 244 | cssFiles: function copyCssFiles() { 245 | this.fs.copy( 246 | this.templatePath('styles/**/*'), 247 | this.destinationPath(path.join(this.appPath, 'styles/') 248 | ) 249 | ); 250 | }, 251 | 252 | createIndexHtml: function createIndexHtml() { 253 | this.template('index.html', path.join(this.appPath, 'index.html')); 254 | }, 255 | 256 | appJs: function appJs() { 257 | this.angularModules = this.env.options.angularDeps; 258 | 259 | this.template('app/_app.js', this.appPath + '/scripts/_app.js'); 260 | this.template('app/_app.spec.js', this.appPath + '/scripts/_app.spec.js'); 261 | if (this.env.options.uiRouter) { 262 | this.template('app/routes.js', this.appPath + '/scripts/routes.js'); 263 | this.template('app/routes.spec.js', this.appPath + '/scripts/routes.spec.js'); 264 | } 265 | }, 266 | 267 | packageFiles: function packageFiles() { 268 | this.template('root/_bower.json', 'bower.json'); 269 | this.template('root/_bowerrc', '.bowerrc'); 270 | this.template('root/_package.json', 'package.json'); 271 | this.template('root/_gulpfile.js', 'gulpfile.js'); 272 | this.template('root/_config.xml', 'config.xml'); 273 | this.template('root/_gitignore', '.gitignore'); 274 | this.template('root/_gitattributes', '.gitattributes'); 275 | this.template('root/_editorconfig', '.editorconfig'); 276 | this.template('root/_jshintrc', '.jshintrc'); 277 | this.template('root/README.md', 'README.md'); 278 | this.template('root/_travis.yml', '.travis.yml'); 279 | this.template('root/_karma.conf.js', 'karma.conf.js'); 280 | this.template('root/_karma-e2e.conf.js', 'karma-e2e.conf.js'); 281 | }, 282 | 283 | tasks: function packageFiles() { 284 | // fixing lodash issue with ngconfig 285 | this.ngConfModulePlaceholder = '<%= module %>'; 286 | 287 | this.template('tasks/config.js', 'tasks/config.js'); 288 | this.template('tasks/build.js', 'tasks/build.js'); 289 | this.template('tasks/dev.js', 'tasks/dev.js'); 290 | this.template('tasks/deploy.js', 'tasks/deploy.js'); 291 | this.template('tasks/e2e.js', 'tasks/e2e.js'); 292 | 293 | // TODO make cordova optional 294 | this.template('tasks/cordova.js', 'tasks/cordova.js'); 295 | }, 296 | 297 | install: function packageFiles() { 298 | this.on('end', function() { 299 | //save configuration 300 | this.config.save(); 301 | if (!this.options['skip-install']) { 302 | this.installDependencies({ 303 | callback: function() { 304 | // Emit a new event - dependencies installed 305 | this.emit('dependenciesInstalled'); 306 | }.bind(this) 307 | }); 308 | } 309 | }); 310 | }, 311 | postRun: function() { 312 | this.on('dependenciesInstalled', function() { 313 | this.spawnCommand('gulp', ['serve']); 314 | }); 315 | } 316 | }); 317 | 318 | -------------------------------------------------------------------------------- /assets/angular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johannesjo/generator-modular-angular/06e3d19b171ab4beba97cdcfa5c60b9d827c7d7b/assets/angular.png -------------------------------------------------------------------------------- /assets/bower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johannesjo/generator-modular-angular/06e3d19b171ab4beba97cdcfa5c60b9d827c7d7b/assets/bower.png -------------------------------------------------------------------------------- /assets/cordova.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johannesjo/generator-modular-angular/06e3d19b171ab4beba97cdcfa5c60b9d827c7d7b/assets/cordova.png -------------------------------------------------------------------------------- /assets/gulp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johannesjo/generator-modular-angular/06e3d19b171ab4beba97cdcfa5c60b9d827c7d7b/assets/gulp.png -------------------------------------------------------------------------------- /assets/libsass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johannesjo/generator-modular-angular/06e3d19b171ab4beba97cdcfa5c60b9d827c7d7b/assets/libsass.png -------------------------------------------------------------------------------- /assets/yeoman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johannesjo/generator-modular-angular/06e3d19b171ab4beba97cdcfa5c60b9d827c7d7b/assets/yeoman.png -------------------------------------------------------------------------------- /c/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var ScriptBase = require('../sub-generator-base.js'); 3 | 4 | module.exports = ScriptBase.extend({ 5 | initializing: function() { 6 | // needs to be called manually 7 | this.init(); 8 | }, 9 | createFactoryFiles: function createFactoryFiles() { 10 | var cb = this.async(), 11 | defaults = { 12 | createTemplate: true, 13 | createService: false 14 | }; 15 | 16 | var createFiles = function(props) { 17 | this.createService = props.createService; 18 | this.createTemplate = props.createTemplate; 19 | 20 | this.generateSourceAndTest('controller'); 21 | // NOTE: never forget the callback! 22 | cb(); 23 | }; 24 | 25 | if (this.options.useDefaults || this.config.get('alwaysSkipDialog')) { 26 | createFiles.bind(this)(defaults); 27 | } else { 28 | this.prompt( 29 | [ 30 | { 31 | type: 'confirm', 32 | name: 'createTemplate', 33 | message: 'Would you like to create a html-template-file and a scss-file for the controller?', 34 | default: defaults.createTemplate 35 | }, 36 | { 37 | type: 'list', 38 | name: 'createService', 39 | message: 'Would you like to create a service or factory for the controller?', 40 | default: defaults.createService, 41 | choices: [ 42 | { 43 | name: 'No', 44 | value: false 45 | }, 46 | { 47 | name: 'a service', 48 | value: 'service' 49 | }, 50 | { 51 | name: 'a factory', 52 | value: 'service' 53 | } 54 | ] 55 | } 56 | ], 57 | createFiles.bind(this)); 58 | } 59 | } 60 | }); 61 | -------------------------------------------------------------------------------- /cp/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var ScriptBase = require('../sub-generator-base.js'); 3 | 4 | module.exports = ScriptBase.extend({ 5 | initializing: function() { 6 | // needs to be called manually 7 | this.init(); 8 | }, 9 | createFactoryFiles: function createFactoryFiles() { 10 | var cb = this.async(), 11 | defaults = { 12 | createTemplate: true, 13 | createService: false 14 | }; 15 | 16 | var createFiles = function(props) { 17 | this.createService = props.createService; 18 | this.createTemplate = props.createTemplate; 19 | 20 | this.generateSourceAndTest('component'); 21 | // NOTE: never forget the callback! 22 | cb(); 23 | }; 24 | 25 | if (this.options.useDefaults || this.config.get('alwaysSkipDialog')) { 26 | createFiles.bind(this)(defaults); 27 | } else { 28 | this.prompt( 29 | [ 30 | { 31 | type: 'confirm', 32 | name: 'createTemplate', 33 | message: 'Would you like to create a html-template-file and a scss-file for the component?', 34 | default: defaults.createTemplate 35 | }, 36 | { 37 | type: 'list', 38 | name: 'createService', 39 | message: 'Would you like to create a service or factory for the component?', 40 | default: defaults.createService, 41 | choices: [ 42 | { 43 | name: 'No', 44 | value: false 45 | }, 46 | { 47 | name: 'a service', 48 | value: 'service' 49 | }, 50 | { 51 | name: 'a factory', 52 | value: 'service' 53 | } 54 | ] 55 | } 56 | ], 57 | createFiles.bind(this)); 58 | } 59 | } 60 | }); 61 | 62 | -------------------------------------------------------------------------------- /d/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var ScriptBase = require('../sub-generator-base.js'); 3 | 4 | module.exports = ScriptBase.extend({ 5 | initializing: function() { 6 | // needs to be called manually 7 | this.init(); 8 | }, 9 | createFactoryFiles: function createFactoryFiles() { 10 | var cb = this.async(), 11 | defaults = { 12 | createTemplate: true, 13 | createService: false 14 | }; 15 | 16 | var createFiles = function(props) { 17 | this.createService = props.createService; 18 | this.createTemplate = props.createTemplate; 19 | 20 | this.generateSourceAndTest('directive'); 21 | // NOTE: never forget the callback! 22 | cb(); 23 | }; 24 | 25 | if (this.options.useDefaults || this.config.get('alwaysSkipDialog')) { 26 | createFiles.bind(this)(defaults); 27 | } else { 28 | this.prompt( 29 | [ 30 | { 31 | type: 'confirm', 32 | name: 'createTemplate', 33 | message: 'Would you like to create a html-template-file and a scss-file for the directive?', 34 | default: defaults.createTemplate 35 | }, 36 | { 37 | type: 'list', 38 | name: 'createService', 39 | message: 'Would you like to create a service or factory for the directive?', 40 | default: defaults.createService, 41 | choices: [ 42 | { 43 | name: 'No', 44 | value: false 45 | }, 46 | { 47 | name: 'a service', 48 | value: 'service' 49 | }, 50 | { 51 | name: 'a factory', 52 | value: 'service' 53 | } 54 | ] 55 | } 56 | ], 57 | createFiles.bind(this)); 58 | } 59 | } 60 | }); 61 | 62 | -------------------------------------------------------------------------------- /decorator/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var ScriptBase = require('../sub-generator-base.js'); 3 | 4 | module.exports = ScriptBase.extend({ 5 | initializing: function() { 6 | // needs to be called manually 7 | this.init(); 8 | }, 9 | createFactoryFiles: function createFactoryFiles() { 10 | this.generateSourceAndTest('decorator'); 11 | } 12 | }); 13 | 14 | 15 | -------------------------------------------------------------------------------- /default-settings.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testSuffix: '.spec', 3 | testPassOnDefault: true, 4 | alwaysSkipDialog: false, 5 | stylePrefix: '_', 6 | editorCommand: 'idea', 7 | uiRouter: false, 8 | pathOutputStyle: 'dasherize', 9 | routesFile: 'app/scripts/routes.js', 10 | fileExt: { 11 | script: '.js', 12 | tpl: '.html', 13 | style: '.scss' 14 | }, 15 | dirs: { 16 | app: 'app', 17 | appModules: 'scripts', 18 | globalComponents: 'main', 19 | routes: 'routes' 20 | }, 21 | subGenerators: { 22 | directive: { 23 | suffix: '-d', 24 | globalDir: '', 25 | createDirectory: true 26 | }, 27 | controller: { 28 | suffix: '-c', 29 | nameSuffix: 'Ctrl', 30 | globalDir: '', 31 | createDirectory: true 32 | }, 33 | component: { 34 | suffix: '-cp', 35 | globalDir: '', 36 | createDirectory: true 37 | }, 38 | service: { 39 | suffix: '-s', 40 | globalDir: 'main/global-services' 41 | }, 42 | factory: { 43 | suffix: '-f', 44 | globalDir: 'main/global-services' 45 | }, 46 | filter: { 47 | suffix: '-filter', 48 | globalDir: 'main/global-filters' 49 | }, 50 | provider: { 51 | suffix: '-p', 52 | globalDir: 'main/global-services' 53 | }, 54 | decorator: { 55 | suffix: '-decorator', 56 | nameSuffix: 'Decorator', 57 | globalDir: 'main/global-services' 58 | }, 59 | mod: { 60 | prefix: '_', 61 | createDirectory: true 62 | } 63 | } 64 | }; -------------------------------------------------------------------------------- /f/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var ScriptBase = require('../sub-generator-base.js'); 3 | 4 | module.exports = ScriptBase.extend({ 5 | initializing: function() { 6 | // needs to be called manually 7 | this.init(); 8 | }, 9 | createFactoryFiles: function createFactoryFiles() { 10 | this.generateSourceAndTest('factory'); 11 | } 12 | }); 13 | 14 | 15 | -------------------------------------------------------------------------------- /filter/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var ScriptBase = require('../sub-generator-base.js'); 3 | 4 | module.exports = ScriptBase.extend({ 5 | initializing: function() { 6 | // needs to be called manually 7 | this.init(); 8 | }, 9 | createFactoryFiles: function createFactoryFiles() { 10 | this.generateSourceAndTest('filter'); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /helper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var path = require('path'); 3 | var fs = require('fs'); 4 | var chalk = require('chalk'); 5 | 6 | exports.STATE_NEEDLE = '/* STATES-NEEDLE - DO NOT REMOVE THIS */'; 7 | 8 | // inspired by https://github.com/cgross/generator-cg-angular/blob/master/utils.js 9 | exports.addToFile = function(filename, lineToAdd, beforeMarker) { 10 | try { 11 | var fullPath = path.resolve(process.cwd(), filename); 12 | var fileSrc = fs.readFileSync(fullPath, 'utf8'); 13 | 14 | var indexOf = fileSrc.indexOf(beforeMarker); 15 | var lineStart = fileSrc.substring(0, indexOf) 16 | .lastIndexOf('\n') + 1; 17 | var indent = fileSrc.substring(lineStart, indexOf); 18 | fileSrc = fileSrc.substring(0, indexOf) + lineToAdd + '\n' + indent + fileSrc.substring(indexOf); 19 | 20 | fs.writeFileSync(fullPath, fileSrc); 21 | } catch (e) { 22 | throw e; 23 | } 24 | }; 25 | 26 | exports.injectRoute = function(routesFile, name, url, tplUrl, ctrl, that) { 27 | var IND = ' '; 28 | var template = tplUrl ? ',\n' + IND + IND + IND + IND + 'templateUrl: \'' + tplUrl + '\'' : ''; 29 | ctrl = ctrl ? ',\n' + IND + IND + IND + IND + 'controller: \'' + ctrl + '\'' : ''; 30 | var ctrlAs = ctrl ? ',\n' + IND + IND + IND + IND + 'controllerAs: \'vm\'' : ''; 31 | 32 | var code = '' + 33 | '.state(\'' + name + '\', {' + 34 | '\n' + IND + IND + IND + IND + 'url: \'' + url + '\'' + 35 | ctrl + 36 | ctrlAs + 37 | template + 38 | '\n' + IND + IND + IND + '})'; 39 | exports.addToFile(routesFile, code, exports.STATE_NEEDLE); 40 | 41 | that.log.writeln(chalk.green(' updating') + ' %s', path.basename(routesFile)); 42 | }; 43 | 44 | -------------------------------------------------------------------------------- /p/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var ScriptBase = require('../sub-generator-base.js'); 3 | 4 | module.exports = ScriptBase.extend({ 5 | initializing: function() { 6 | // needs to be called manually 7 | this.init(); 8 | }, 9 | createFactoryFiles: function createFactoryFiles() { 10 | this.generateSourceAndTest('provider'); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "generator-moda", 3 | "version": "2.0.0", 4 | "description": "A truly modular yeoman generator for AngularJS all device apps.", 5 | "keywords": [ 6 | "yeoman-generator", 7 | "scaffold", 8 | "front-end", 9 | "app", 10 | "angular", 11 | "modular", 12 | "sass", 13 | "scss", 14 | "cordova", 15 | "gulp" 16 | ], 17 | "author": "johannesjo", 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/johannesjo/generator-modular-angular.git" 21 | }, 22 | "dependencies": { 23 | "chalk": "latest", 24 | "lodash": "latest", 25 | "underscore.string": "latest", 26 | "wiredep": "latest", 27 | "yeoman-generator": "^0.22.5", 28 | "yosay": "latest" 29 | }, 30 | "engines": { 31 | "node": ">=4.1" 32 | }, 33 | "licenses": [ 34 | { 35 | "type": "MIT" 36 | } 37 | ], 38 | "main": "app/index.js", 39 | "scripts": { 40 | "test": "istanbul cover _mocha -- -R list" 41 | }, 42 | "files": [ 43 | "app", 44 | "c", 45 | "cp", 46 | "constant", 47 | "d", 48 | "decorator", 49 | "f", 50 | "filter", 51 | "m", 52 | "mod", 53 | "p", 54 | "route", 55 | "r", 56 | "sr", 57 | "s", 58 | "templates", 59 | "script-base.js", 60 | "util.js", 61 | "helper.js", 62 | "default-settings.js", 63 | "sub-generator-base.js" 64 | ], 65 | "devDependencies": { 66 | "coveralls": "latest", 67 | "gulp": "latest", 68 | "istanbul": "latest", 69 | "mocha": "latest", 70 | "mocha-lcov-reporter": "latest", 71 | "underscore": "latest" 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /r/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var ScriptBase = require('../sub-generator-base.js'); 3 | var helper = require('../helper.js'); 4 | var path = require('path'); 5 | var fs = require('fs'); 6 | var chalk = require('chalk'); 7 | var defaultSettings = require('../default-settings.js'); 8 | 9 | module.exports = ScriptBase.extend({ 10 | initializing: function() { 11 | // needs to be called manually 12 | this.init(); 13 | 14 | // the state name is the argument 15 | this.stateName = this.name; 16 | 17 | // create path string from name 18 | var PARENT_STATES_REG_EXP = new RegExp('([^\\.]+)\\.', 'g'); 19 | var parentStates = this.name.match(PARENT_STATES_REG_EXP); 20 | var parentStatePath = ''; 21 | if (parentStates) { 22 | for (var i = 0; i < parentStates.length; i++) { 23 | var stateStr = parentStates[i].replace('.', ''); 24 | stateStr = this.formatNamePath(stateStr); 25 | parentStatePath = path.join(parentStatePath, stateStr); 26 | } 27 | } 28 | 29 | // set name to base-name only to work with the usual generators 30 | this.name = this.name.replace(PARENT_STATES_REG_EXP, ''); 31 | // instead use target folder to set the path 32 | this.targetFolder = path.join(this.dirs.routes, parentStatePath); 33 | 34 | // names need to be reset 35 | this.setModuleNames(this.name); 36 | }, 37 | 38 | prompting: function() { 39 | var done = this.async(); 40 | var defaults = { 41 | createTemplate: true, 42 | createService: false, 43 | createCtrl: true 44 | }; 45 | 46 | function createControllerFiles(props) { 47 | // set context vars 48 | this.createService = props.createService; 49 | this.createTemplate = props.createTemplate; 50 | this.skipMainFiles = !props.createCtrl; 51 | this.createController = props.createCtrl; 52 | 53 | // create controller files 54 | this.generateSourceAndTest('controller'); 55 | done(); 56 | } 57 | 58 | if (this.options.useDefaults || this.config.get('alwaysSkipDialog')) { 59 | createControllerFiles.bind(this)(defaults); 60 | } else { 61 | this.prompt( 62 | [ 63 | { 64 | type: 'confirm', 65 | name: 'createCtrl', 66 | message: 'Would you like to create a controller for the route?', 67 | default: defaults.createCtrl 68 | }, 69 | { 70 | type: 'confirm', 71 | name: 'createTemplate', 72 | message: 'Would you like to create a html-template-file and a scss-file for the route?', 73 | default: defaults.createTemplate 74 | }, 75 | { 76 | type: 'list', 77 | name: 'createService', 78 | message: 'Would you like to create a service or factory for the route?', 79 | default: defaults.createService, 80 | choices: [ 81 | { 82 | name: 'No', 83 | value: false 84 | }, 85 | { 86 | name: 'a service', 87 | value: 'service' 88 | }, 89 | { 90 | name: 'a factory', 91 | value: 'service' 92 | } 93 | ] 94 | } 95 | ], 96 | createControllerFiles.bind(this)); 97 | } 98 | }, 99 | 100 | writing: function(props) { 101 | var that = this; 102 | var done = this.async(); 103 | 104 | // check if routes file does exist and create it if not 105 | if (that.uiRouter && that.routesFile) { 106 | fs.stat(that.routesFile, function(err, stat) { 107 | // if no route-file exist 108 | if (err) { 109 | that.fs.copyTpl( 110 | that.templatePath('routes' + that.fileExt.script), 111 | that.destinationPath(that.routesFile), 112 | that 113 | ); 114 | that.log.writeln(chalk.yellow('Creating routes file at ' + that.routesFile + ' as none was present at the specified location')); 115 | that.injectIntoRoutesFile = true; 116 | done(); 117 | } else { 118 | that.injectIntoRoutesFile = true; 119 | done(); 120 | } 121 | }); 122 | } else { 123 | this.log.writeln(chalk.yellow('No routes file provided in config or injection deactivated')); 124 | done(); 125 | } 126 | }, 127 | 128 | install: function() { 129 | // SOMEWHAT HACKY, but not possible otherwise to run 130 | // after file creation due to how the run queue works 131 | // @see http://yeoman.io/authoring/running-context.html 132 | 133 | if (this.injectIntoRoutesFile) { 134 | this.log.writeln(chalk.yellow('injecting state into ' + this.routesFile)); 135 | 136 | var routeUrl = '/' + this.formatNamePath(this.name), 137 | tplUrl = this.tplUrl, 138 | ctrl = !!this.createController && this.classedName + (this.subGenerators.controller.nameSuffix || ''); 139 | 140 | helper.injectRoute( 141 | this.routesFile, 142 | this.stateName, 143 | routeUrl, 144 | tplUrl, 145 | ctrl, 146 | this 147 | ); 148 | } 149 | } 150 | }); 151 | -------------------------------------------------------------------------------- /s/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var ScriptBase = require('../sub-generator-base.js'); 3 | 4 | module.exports = ScriptBase.extend({ 5 | initializing: function() { 6 | // needs to be called manually 7 | this.init(); 8 | }, 9 | createFactoryFiles: function createFactoryFiles() { 10 | this.generateSourceAndTest('service'); 11 | } 12 | }); -------------------------------------------------------------------------------- /sub-generator-base.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var path = require('path'); 3 | var yeoman = require('yeoman-generator'); 4 | var defaultSettings = require('./default-settings.js'); 5 | var helper = require('./helper.js'); 6 | var chalk = require('chalk'); 7 | var fs = require('fs'); 8 | var _s = require('underscore.string'); 9 | var _ = require('lodash'); 10 | 11 | module.exports = yeoman.Base.extend({ 12 | constructor: function() { 13 | // super constructor needs to be called manually 14 | // as the constructor-function is overwritten by this 15 | yeoman.Base.apply(this, arguments); 16 | this.argument('name', {type: String, required: true}); 17 | 18 | // define global options 19 | this.option('useDefaults'); 20 | this.option('openInEditor'); 21 | this.option('noParentFolder'); 22 | this.option('skipInject'); 23 | 24 | // define arguments 25 | this.argument('targetFolder', { 26 | type: String, 27 | required: false, 28 | description: 'The path of the parent module. Strips app and scripts folders' 29 | }); 30 | 31 | 32 | // set all the different name versions to be used in the templates 33 | this.setModuleNames(this.name); 34 | 35 | // set app name 36 | this.setAppVariables(); 37 | 38 | 39 | // set sources root (for file-templates) 40 | var sourceRoot = '/templates/app'; 41 | this.sourceRoot(path.join(__dirname, sourceRoot)); 42 | 43 | // additional variables 44 | this.createdFiles = []; 45 | 46 | // init here, although its double the trouble for now 47 | //this.mergeConfig(); 48 | }, 49 | 50 | /** 51 | * parent initialize function, inherited by sub-gens 52 | */ 53 | init: function() { 54 | this.mergeConfig(); 55 | this.overWriteTplPathIfSet(); 56 | }, 57 | 58 | /** 59 | * helper function to merge default settings with the ones 60 | * provided by the .yo-rc.json 61 | */ 62 | mergeConfig: function() { 63 | // get either default or from config 64 | 65 | // create a clone to avoid testing issues 66 | var defaultCfg = _.cloneDeep(defaultSettings); 67 | _.merge(defaultCfg, this.config.getAll()); 68 | _.merge(this, defaultCfg); 69 | }, 70 | 71 | /** 72 | * allows overwriting of the template path of the generator 73 | * so users can specifiy their own template path 74 | */ 75 | overWriteTplPathIfSet: function() { 76 | if (this.customTemplatesPath) { 77 | if (fs.existsSync(this.customTemplatesPath)) { 78 | this.sourceRoot(this.customTemplatesPath); 79 | } else { 80 | throw (new Error('custom template path ' + this.customTemplatesPath + ' does not exist. Check your .yo-rc.json.')); 81 | } 82 | } 83 | }, 84 | 85 | /** 86 | * set the app variables, e.g. the name of the app in the 87 | * different required formats such as camelized or slugified 88 | */ 89 | setAppVariables: function() { 90 | // define app name variables 91 | var bowerJson = {}; 92 | try { 93 | bowerJson = require(path.join(process.cwd(), 'bower.json')); 94 | } catch (e) { 95 | } 96 | if (bowerJson.name) { 97 | this.appname = bowerJson.name; 98 | } else { 99 | this.appname = path.basename(process.cwd()); 100 | } 101 | this.appname = _s.camelize(_s.slugify(_s.humanize(this.appname))); 102 | this.scriptAppName = bowerJson.moduleName || this.appname; 103 | 104 | // define app path variable 105 | if (typeof this.env.options.appPath === 'undefined') { 106 | this.env.options.appPath = this.options.appPath || bowerJson.appPath || 'app'; 107 | this.options.appPath = this.env.options.appPath; 108 | } 109 | }, 110 | 111 | /** 112 | * sets all the different name versions to be used in the templates 113 | */ 114 | setModuleNames: function(name) { 115 | this.cameledName = _s.camelize(name); 116 | this.classedName = _s.classify(name); 117 | this.sluggedName = _s.slugify(name); 118 | this.dashedName = _s.dasherize(name); 119 | this.humanizedName = _s.humanize(name); 120 | }, 121 | 122 | /** 123 | * helper function to get rid of potential parent paths 124 | * @param path{string} 125 | * @returns {string} 126 | */ 127 | cleanUpPath: function(path) { 128 | path = path 129 | .replace(this.dirs.appModules, '') 130 | .replace(this.dirs.app, ''); 131 | return path; 132 | }, 133 | 134 | /** 135 | * helper function to format the path names to the preferred 136 | * style as configured in the .yo-rc.json 137 | * @param name{string} 138 | * @returns {string} 139 | */ 140 | formatNamePath: function(name) { 141 | var style = this.config.get('pathOutputStyle') || 'dasherize'; 142 | return _s[style](name); 143 | }, 144 | 145 | /** 146 | * 147 | * @returns {string} 148 | */ 149 | defineTargetFolder: function() { 150 | var realTargetFolder; 151 | 152 | // allow creating sub-modules via reading and parsing the path argument 153 | if (this.targetFolder) { 154 | this.targetFolder = this.cleanUpPath(this.targetFolder); 155 | realTargetFolder = path.join(this.targetFolder); 156 | } else { 157 | 158 | if (this.curGenCfg.globalDir) { 159 | realTargetFolder = this.curGenCfg.globalDir; 160 | } else { 161 | realTargetFolder = '.' 162 | } 163 | } 164 | 165 | // check if a same named parent directory should be created 166 | // for directives and routes 167 | if (this.curGenCfg.createDirectory && !this.options.noParentFolder) { 168 | realTargetFolder = path.join(realTargetFolder, this.formatNamePath(this.name)); 169 | } 170 | 171 | return realTargetFolder; 172 | }, 173 | 174 | /** 175 | * main file-creation pipeline function 176 | * @param templateName 177 | */ 178 | generateSourceAndTest: function(templateName) { 179 | this.templateName = templateName; 180 | this.curGenCfg = this.subGenerators[templateName]; 181 | 182 | var realTargetFolder = this.defineTargetFolder(), 183 | filesToCreate = []; 184 | 185 | // create file paths 186 | var inAppPath = path.join(this.dirs.appModules, realTargetFolder); 187 | var generatorTargetPath = path.join(this.env.options.appPath, inAppPath); 188 | var standardFileName = (this.curGenCfg.prefix || '') + this.formatNamePath(this.name) + (this.curGenCfg.suffix || ''); 189 | 190 | // prepare template template and data 191 | if (this.createTemplate) { 192 | this.tplUrl = path.join(inAppPath, standardFileName + this.fileExt.tpl) 193 | // windows fix for url path 194 | .replace(/\\/g, '/'); 195 | filesToCreate.push({ 196 | tpl: this.templateName + this.fileExt.tpl, 197 | targetFileName: standardFileName + this.fileExt.tpl 198 | }); 199 | filesToCreate.push({ 200 | tpl: this.stylePrefix + this.templateName + this.fileExt.style, 201 | targetFileName: this.stylePrefix + standardFileName + this.fileExt.style 202 | }); 203 | } else { 204 | // needs to be set for the _s.templates to work 205 | this.tplUrl = false; 206 | } 207 | 208 | // run create service or factory if option is given 209 | if (this.createService === 'service' || this.createService === 'factory') { 210 | // add service to queue 211 | this.svcName = this.classedName; 212 | 213 | // add service or factory to queue 214 | filesToCreate.push({ 215 | tpl: this.createService + this.fileExt.script, 216 | targetFileName: this.formatNamePath(this.name) + (this.subGenerators[this.createService].suffix || '') + this.fileExt.script, 217 | gen: this.createService 218 | }); 219 | // add service test to queue 220 | filesToCreate.push({ 221 | tpl: this.createService + this.testSuffix + this.fileExt.script, 222 | targetFileName: this.formatNamePath(this.name) + (this.subGenerators[this.createService].suffix || '') + this.testSuffix + this.fileExt.script, 223 | gen: this.createService 224 | }); 225 | } 226 | 227 | if (!this.skipMainFiles) { 228 | // add main file to queue 229 | filesToCreate.push({ 230 | tpl: templateName + this.fileExt.script, 231 | targetFileName: standardFileName + this.fileExt.script 232 | }); 233 | 234 | // add test file to queue 235 | filesToCreate.push({ 236 | tpl: templateName + this.testSuffix + this.fileExt.script, 237 | targetFileName: standardFileName + this.testSuffix + this.fileExt.script 238 | }); 239 | } 240 | 241 | // create files and create a files array for further use 242 | for (var i = 0; i < filesToCreate.length; i++) { 243 | var fileToCreate = filesToCreate[i]; 244 | var outputFile = path.join(generatorTargetPath, fileToCreate.targetFileName); 245 | var customYoRcTpl = this.getCustomTplFromYoRc(fileToCreate); 246 | 247 | // add to created files array 248 | this.createdFiles.push(outputFile); 249 | 250 | // set name suffix accordingly to template 251 | if (fileToCreate.gen) { 252 | this.nameSuffix = fileToCreate.gen.nameSuffix || ''; 253 | } else { 254 | this.nameSuffix = this.curGenCfg.nameSuffix || ''; 255 | } 256 | 257 | 258 | if (customYoRcTpl) { 259 | this.writeCustomYoRcTpl(customYoRcTpl, outputFile); 260 | } else { 261 | this.fs.copyTpl( 262 | this.templatePath(fileToCreate.tpl), 263 | this.destinationPath(outputFile), 264 | this 265 | ); 266 | } 267 | } 268 | this.afterFileCreationHook(); 269 | }, 270 | 271 | /** 272 | * checks for custom templates defined in the .yo-rc.json 273 | * if set they will be used instead of the default ones 274 | * @param fileToCreate 275 | * @returns {string} 276 | */ 277 | getCustomTplFromYoRc: function(fileToCreate) { 278 | var customYoRcTpl; 279 | var curGenCfg = null; 280 | var SPEC_REG_EX = new RegExp(this.testSuffix + '\\' + this.fileExt.script + '$'); 281 | var SCRIPTS_REG_EX = new RegExp(this.fileExt.script + '$'); 282 | var TPL_REG_EX = new RegExp(this.fileExt.tpl + '$'); 283 | var STYLE_REG_EX = new RegExp(this.fileExt.style + '$'); 284 | 285 | if (fileToCreate.gen) { 286 | curGenCfg = this.subGenerators[fileToCreate.gen]; 287 | } else { 288 | curGenCfg = this.curGenCfg; 289 | } 290 | 291 | // WHY is this necessary?? 292 | if (curGenCfg.tpl) { 293 | if (fileToCreate.tpl.match(SPEC_REG_EX)) { 294 | customYoRcTpl = curGenCfg.tpl['spec']; 295 | } else if (fileToCreate.tpl.match(SCRIPTS_REG_EX)) { 296 | customYoRcTpl = curGenCfg.tpl['script']; 297 | } else if (fileToCreate.tpl.match(TPL_REG_EX)) { 298 | customYoRcTpl = curGenCfg.tpl['tpl']; 299 | } else if (fileToCreate.tpl.match(STYLE_REG_EX)) { 300 | customYoRcTpl = curGenCfg.tpl['style']; 301 | } 302 | 303 | if (customYoRcTpl && typeof customYoRcTpl === 'string') { 304 | return customYoRcTpl; 305 | } 306 | } 307 | }, 308 | 309 | /** 310 | * helper function used to create files by using the custom 311 | * template string and underscores templating language 312 | * @param customYoRcTpl{string} 313 | * @param targetDir{string} 314 | */ 315 | writeCustomYoRcTpl: function(customYoRcTpl, targetDir) { 316 | var tpl = _.template(customYoRcTpl, {})(this); 317 | this.fs.write(targetDir, tpl); 318 | }, 319 | 320 | /** 321 | * things done after all files are created 322 | */ 323 | afterFileCreationHook: function() { 324 | // run favorite ide (first to smooth the experiance) 325 | if (this.options.openInEditor) { 326 | this.spawnCommand(this.editorCommand, this.createdFiles); 327 | } 328 | 329 | // inject all files after creation 330 | if (!this.options.skipInject) { 331 | this.spawnCommand('gulp', ['injectAll']); 332 | } 333 | } 334 | }); 335 | 336 | 337 | -------------------------------------------------------------------------------- /templates/app/_app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @ngdoc overview 3 | * @name <%= scriptAppName %> 4 | * @description 5 | * # <%= scriptAppName %> 6 | * 7 | * Main module of the application. 8 | */ 9 | 10 | (() => { 11 | 'use strict'; 12 | 13 | angular 14 | .module('<%= scriptAppName %>', [<%- angularModules %>]); 15 | })(); -------------------------------------------------------------------------------- /templates/app/_app.spec.js: -------------------------------------------------------------------------------- 1 | describe('<%= scriptAppName %>', () => { 2 | 'use strict'; 3 | 4 | beforeEach(module('<%= scriptAppName %>')); 5 | 6 | it('should always work', () => { 7 | expect(true) 8 | .toBe(true); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /templates/app/_component.scss: -------------------------------------------------------------------------------- 1 | <%=sluggedName %> { 2 | 3 | } -------------------------------------------------------------------------------- /templates/app/_controller.scss: -------------------------------------------------------------------------------- 1 | .page-<%=sluggedName %> { 2 | 3 | } -------------------------------------------------------------------------------- /templates/app/_directive.scss: -------------------------------------------------------------------------------- 1 | <%=sluggedName %> { 2 | 3 | } -------------------------------------------------------------------------------- /templates/app/component.html: -------------------------------------------------------------------------------- 1 | This is the <%= cameledName %> component. 2 | 3 | -------------------------------------------------------------------------------- /templates/app/component.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @ngdoc component 3 | * @name <%= scriptAppName %>.component:<%= cameledName %><%= nameSuffix %> 4 | * @description 5 | * # <%= cameledName %><%= nameSuffix %> 6 | */ 7 | 8 | (() => { 9 | 'use strict'; 10 | 11 | class <%= classedName %><%= nameSuffix %>Ctrl { 12 | /* @ngInject */ 13 | constructor(<% if(createService) {%><%= svcName %><% } %>){ 14 | } 15 | } 16 | 17 | angular 18 | .module('<%= scriptAppName %>') 19 | .component('<%= cameledName %><%= nameSuffix %>', {<% if(tplUrl) {%> 20 | templateUrl: '<%= tplUrl %>',<% } %> 21 | controller: <%= classedName %><%= nameSuffix %>Ctrl, 22 | controllerAs: '$ctrl', 23 | bindToController: { 24 | }, 25 | }); 26 | 27 | // hacky fix for ff 28 | <%= classedName %><%= nameSuffix %>Ctrl.$$ngIsClass = true; 29 | })(); 30 | -------------------------------------------------------------------------------- /templates/app/component.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Component: <%= cameledName %><%= nameSuffix %>', () => { 4 | 5 | // load the directive's module 6 | beforeEach(module('<%= scriptAppName %>')); 7 | beforeEach(module('templates')); 8 | 9 | let element; 10 | let scope; 11 | 12 | beforeEach(inject(($rootScope) => { 13 | scope = $rootScope.$new(); 14 | })); 15 | 16 | it('should do something', inject(($compile) => { 17 | element = $compile('<<%= dashedName %>>>')(scope); 18 | scope.$digest(); 19 | expect(true).toBe(<%= testPassOnDefault %>); 20 | })); 21 | }); -------------------------------------------------------------------------------- /templates/app/controller.html: -------------------------------------------------------------------------------- 1 |
2 |

This is the <%= classedName %> view

3 |
4 | -------------------------------------------------------------------------------- /templates/app/controller.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @ngdoc function 3 | * @name <%= scriptAppName %>.controller:<%= classedName %><%= nameSuffix %> 4 | * @description 5 | * # <%= classedName %><%= nameSuffix %> 6 | * Controller of the <%= scriptAppName %> 7 | */ 8 | 9 | (() => { 10 | 'use strict'; 11 | 12 | class <%= classedName %><%= nameSuffix %> { 13 | /* @ngInject */ 14 | constructor(<% if(createService) {%><%= svcName %><% } %>){ 15 | } 16 | } 17 | 18 | angular 19 | .module('<%= scriptAppName %>') 20 | .controller('<%= classedName %><%= nameSuffix %>', <%= classedName %><%= nameSuffix %>); 21 | 22 | // hacky fix for ff 23 | <%= classedName %><%= nameSuffix %>.$$ngIsClass = true; 24 | 25 | })(); 26 | -------------------------------------------------------------------------------- /templates/app/controller.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: <%= classedName %><%= nameSuffix %>', () => { 4 | 5 | // load the controller's module 6 | beforeEach(module('<%= scriptAppName %>')); 7 | 8 | let <%= classedName %><%= nameSuffix %>; 9 | let scope; 10 | 11 | // Initialize the controller and a mock scope 12 | beforeEach(inject(($controller, $rootScope) => { 13 | scope = $rootScope.$new(); 14 | <%= classedName %><%= nameSuffix %> = $controller('<%= classedName %><%= nameSuffix %>', { 15 | $scope: scope 16 | // place mocked dependencies here 17 | }); 18 | })); 19 | 20 | it('should ...', () => { 21 | expect(true).toBe(<%= testPassOnDefault %>); 22 | }); 23 | }); -------------------------------------------------------------------------------- /templates/app/decorator.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @ngdoc function 3 | * @name <%= scriptAppName %>.decorator:<%= classedName %><%= nameSuffix %> 4 | * @description 5 | * # <%= classedName %><%= nameSuffix %> 6 | * Decorator of the <%= scriptAppName %> 7 | */ 8 | 9 | (() => { 10 | 'use strict'; 11 | 12 | angular 13 | .module('<%= scriptAppName %>') 14 | .config(<%= classedName %><%= nameSuffix %>); 15 | 16 | function <%= classedName %><%= nameSuffix %>($provide) { 17 | $provide.decorator('<%= classedName %>', ($delegate) => { 18 | return $delegate; 19 | }); 20 | } 21 | })(); 22 | -------------------------------------------------------------------------------- /templates/app/decorator.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Decorator: <%= classedName %><%= nameSuffix %>', () => { 4 | // load the service's module 5 | beforeEach(module('<%= scriptAppName %>')); 6 | 7 | // instantiate service 8 | let <%= classedName %><%= nameSuffix %>; 9 | beforeEach(inject(function (_<%= classedName %><%= nameSuffix %>_) { 10 | <%= classedName %><%= nameSuffix %> = _<%= classedName %><%= nameSuffix %>_; 11 | })); 12 | 13 | it('should be defined', () => { 14 | expect(true).toBe(<%= testPassOnDefault %>); 15 | }); 16 | 17 | }); -------------------------------------------------------------------------------- /templates/app/directive.html: -------------------------------------------------------------------------------- 1 | This is the <%= cameledName %> directive. 2 | 3 | -------------------------------------------------------------------------------- /templates/app/directive.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @ngdoc directive 3 | * @name <%= scriptAppName %>.directive:<%= cameledName %><%= nameSuffix %> 4 | * @description 5 | * # <%= cameledName %><%= nameSuffix %> 6 | */ 7 | 8 | (() => { 9 | 'use strict'; 10 | 11 | class <%= classedName %><%= nameSuffix %>Ctrl { 12 | /* @ngInject */ 13 | constructor(<% if(createService) {%><%= svcName %><% } %>){ 14 | } 15 | } 16 | 17 | angular 18 | .module('<%= scriptAppName %>') 19 | .directive('<%= cameledName %><%= nameSuffix %>', {<% if(tplUrl) {%> 20 | templateUrl: '<%= tplUrl %>',<% } %> 21 | bindToController: { 22 | }, 23 | controller: <%= classedName %><%= nameSuffix %>Ctrl, 24 | controllerAs: '$ctrl', 25 | restrict: 'A', 26 | scope: true 27 | }); 28 | 29 | // hacky fix for ff 30 | <%= classedName %><%= nameSuffix %>Ctrl.$$ngIsClass = true; 31 | })(); 32 | -------------------------------------------------------------------------------- /templates/app/directive.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Directive: <%= cameledName %><%= nameSuffix %>', () => { 4 | 5 | // load the directive's module 6 | beforeEach(module('<%= scriptAppName %>')); 7 | beforeEach(module('templates')); 8 | 9 | let element; 10 | let scope; 11 | 12 | beforeEach(inject(($rootScope) => { 13 | scope = $rootScope.$new(); 14 | })); 15 | 16 | it('should do something', inject(($compile) => { 17 | element = $compile('<<%= dashedName %>>>')(scope); 18 | scope.$digest(); 19 | expect(true).toBe(<%= testPassOnDefault %>); 20 | })); 21 | }); -------------------------------------------------------------------------------- /templates/app/factory.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @ngdoc factory 3 | * @name <%= scriptAppName %>.<%= classedName %><%= nameSuffix %> 4 | * @description 5 | * # <%= classedName %><%= nameSuffix %> 6 | * Factory in the <%= scriptAppName %>. 7 | */ 8 | 9 | (() => { 10 | 'use strict'; 11 | 12 | class <%= classedName %><%= nameSuffix %> { 13 | /* @ngInject */ 14 | constructor(){ 15 | } 16 | } 17 | 18 | angular 19 | .module('<%= scriptAppName %>') 20 | .factory('<%= classedName %><%= nameSuffix %>', <%= classedName %><%= nameSuffix %>); 21 | 22 | // hacky fix for ff 23 | <%= classedName %><%= nameSuffix %>.$$ngIsClass = true; 24 | })(); 25 | -------------------------------------------------------------------------------- /templates/app/factory.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Factory: <%= classedName %><%= nameSuffix %>', () => { 4 | // load the service's module 5 | beforeEach(module('<%= scriptAppName %>')); 6 | 7 | // instantiate service 8 | let <%= classedName %><%= nameSuffix %>; 9 | beforeEach(inject((_<%= classedName %><%= nameSuffix %>_) => { 10 | <%= classedName %><%= nameSuffix %> = _<%= classedName %><%= nameSuffix %>_; 11 | })); 12 | 13 | it('should be defined', () => { 14 | expect(true).toBe(<%= testPassOnDefault %>); 15 | }); 16 | 17 | }); -------------------------------------------------------------------------------- /templates/app/filter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @ngdoc filter 3 | * @name <%= scriptAppName %>.filter:<%= cameledName %><%= nameSuffix %> 4 | * @function 5 | * @description 6 | * # <%= cameledName %><%= nameSuffix %> 7 | * Filter in the <%= scriptAppName %>. 8 | */ 9 | 10 | (() => { 11 | 'use strict'; 12 | 13 | angular 14 | .module('<%= scriptAppName %>') 15 | .filter('<%= cameledName %><%= nameSuffix %>', <%= cameledName %><%= nameSuffix %>); 16 | 17 | function <%= cameledName %><%= nameSuffix %>() { 18 | return (parameters) => { 19 | return parameters; 20 | } 21 | } 22 | })(); 23 | -------------------------------------------------------------------------------- /templates/app/filter.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Filter: <%= cameledName %><%= nameSuffix %>', () => { 4 | 5 | // load the filter's module 6 | beforeEach(module('<%= scriptAppName %>')); 7 | 8 | // initialize a new instance of the filter before each test 9 | let <%= cameledName %><%= nameSuffix %>; 10 | beforeEach(inject(($filter) => { 11 | <%= cameledName %><%= nameSuffix %> = $filter('<%= cameledName %><%= nameSuffix %>'); 12 | })); 13 | 14 | it('should change some output:"', () => { 15 | // var text = 'angularjs'; 16 | // expect(<%= cameledName %><%= nameSuffix %>(text)).toBe('something else'); 17 | expect(true).toBe(<%= testPassOnDefault %>); 18 | 19 | }); 20 | 21 | }); -------------------------------------------------------------------------------- /templates/app/provider.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @ngdoc provider 3 | * @name <%= scriptAppName %>.<%= classedName %><%= nameSuffix %> 4 | * @description 5 | * # <%= classedName %><%= nameSuffix %> 6 | * Provider in the <%= scriptAppName %>. 7 | */ 8 | 9 | (() => { 10 | 'use strict'; 11 | 12 | let config; 13 | 14 | // Private constructor-function aka factory definition 15 | class <%= classedName %><%= nameSuffix %> { 16 | /* @ngInject */ 17 | constructor() { 18 | } 19 | 20 | someServiceFunction() { 21 | }; 22 | } 23 | 24 | class <%= classedName %><%= nameSuffix %>Provider { 25 | /* @ngInject */ 26 | constructor() { 27 | config = {}; 28 | } 29 | 30 | // PROVIDER-FUNCTIONS 31 | extendConfig(additionalConfig) { 32 | config = angular.extend(config, additionalConfig); 33 | } 34 | 35 | // return service definition 36 | $get() { 37 | return new <%= classedName %><%= nameSuffix %>(); 38 | } 39 | } 40 | 41 | angular 42 | .module('<%= scriptAppName %>') 43 | .provider('<%= classedName %><%= nameSuffix %>', <%= classedName %><%= nameSuffix %>Provider); 44 | 45 | // hacky fix for ff 46 | <%= classedName %><%= nameSuffix %>Provider.$$ngIsClass = true; 47 | <%= classedName %><%= nameSuffix %>.$$ngIsClass = true; 48 | })(); -------------------------------------------------------------------------------- /templates/app/provider.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Provider: <%= classedName %><%= nameSuffix %>', () => { 4 | // load the service's module 5 | let provider; 6 | 7 | beforeEach(module('<%= scriptAppName %>', (<%= classedName %><%= nameSuffix %>Provider) => { 8 | provider = <%= classedName %><%= nameSuffix %>Provider; 9 | })); 10 | 11 | // instantiate service-function 12 | let <%= classedName %><%= nameSuffix %>; 13 | beforeEach(inject(function (_<%= classedName %><%= nameSuffix %>_) { 14 | <%= classedName %><%= nameSuffix %> = _<%= classedName %><%= nameSuffix %>_; 15 | })); 16 | 17 | it('should be defined', () => { 18 | // provider.extendConfig({}); 19 | expect(true).toBe(<%= testPassOnDefault %>); 20 | }); 21 | 22 | }); -------------------------------------------------------------------------------- /templates/app/routes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @ngdoc overview 3 | * @name <%= scriptAppName %>.routes 4 | * @description 5 | * # <%= scriptAppName %>.routes 6 | * 7 | * Routes module. All app states are defined here. 8 | */ 9 | 10 | (() => { 11 | 'use strict'; 12 | 13 | angular 14 | .module('<%= scriptAppName %>') 15 | .config(routerHelperProvider); 16 | 17 | /* @ngInject */ 18 | function routerHelperProvider($stateProvider, $urlRouterProvider) { 19 | 20 | $urlRouterProvider.otherwise('/'); 21 | 22 | $stateProvider 23 | .state('home', { 24 | url: '/', 25 | template: '

Hello!

All clean here, as intended! Why not build some routes via "yo moda:r my-route"?

' 26 | }) 27 | /* STATES-NEEDLE - DO NOT REMOVE THIS */; 28 | } 29 | })(); 30 | -------------------------------------------------------------------------------- /templates/app/routes.spec.js: -------------------------------------------------------------------------------- 1 | describe('<%= scriptAppName %>.routes', () => { 2 | 'use strict'; 3 | 4 | beforeEach(module('<%= scriptAppName %>')); 5 | 6 | it('should be defined', () => { 7 | expect(true) 8 | .toBe(true); 9 | }); 10 | }); -------------------------------------------------------------------------------- /templates/app/service.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @ngdoc service 3 | * @name <%= scriptAppName %>.<%= classedName %><%= nameSuffix %> 4 | * @description 5 | * # <%= classedName %><%= nameSuffix %> 6 | * Service in the <%= scriptAppName %>. 7 | */ 8 | 9 | (() => { 10 | 'use strict'; 11 | 12 | class <%= classedName %><%= nameSuffix %> { 13 | /* @ngInject */ 14 | constructor(){ 15 | } 16 | } 17 | 18 | angular 19 | .module('<%= scriptAppName %>') 20 | .service('<%= classedName %><%= nameSuffix %>', <%= classedName %><%= nameSuffix %>); 21 | 22 | // hacky fix for ff 23 | <%= classedName %><%= nameSuffix %>.$$ngIsClass = true; 24 | })(); 25 | -------------------------------------------------------------------------------- /templates/app/service.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Service: <%= classedName %><%= nameSuffix %>', () => { 4 | // load the service's module 5 | beforeEach(module('<%= scriptAppName %>')); 6 | 7 | // instantiate service 8 | let <%= classedName %><%= nameSuffix %>; 9 | beforeEach(inject((_<%= classedName %><%= nameSuffix %>_) => { 10 | <%= classedName %><%= nameSuffix %> = _<%= classedName %><%= nameSuffix %>_; 11 | })); 12 | 13 | it('should be defined', () => { 14 | expect(true).toBe(<%= testPassOnDefault %>); 15 | }); 16 | 17 | }); -------------------------------------------------------------------------------- /templates/e2e-tests/example.e2e.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('The home view', function () 4 | { 5 | var page; 6 | 7 | beforeEach(function () 8 | { 9 | browser.get('http://localhost:3000/index.html'); 10 | page = require('./home.po'); 11 | }); 12 | 13 | it('runs e2e tests', function () 14 | { 15 | expect(page.body.count()).toBeGreaterThan(1); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /templates/e2e-tests/po/home.po.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file uses the Page Object pattern 3 | * @see https://docs.google.com/presentation/d/1B6manhG0zEXkC-H-tPo2vwU06JhL8w9-XCF9oehXzAQ 4 | */ 5 | 6 | 'use strict'; 7 | 8 | var MainPage = function () 9 | { 10 | this.body = element(by.css('body')); 11 | }; 12 | 13 | MainPage.prototype.goTo = function () 14 | { 15 | return browser.get('/'); 16 | }; 17 | 18 | module.exports = new MainPage(); 19 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= humanizedAppName %> 5 | 6 | 8 | 10 | 12 | 14 | 15 | 19 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | 34 | 35 | 36 | 37 | 38 | <% if (ngRoute) { 39 | %>
<% 40 | } %><% if (uiRouter) { 41 | %>
<% } %> 42 | 43 | 44 | 48 | 49 | 50 | 51 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /templates/root/README.md: -------------------------------------------------------------------------------- 1 | # <%= appname %> 2 | 3 | This project was generated with [yo angular modular generator](https://github.com/johannesjo/generator-modular-angular) 4 | version <%= pkg.version %>. 5 | 6 | ## Build & development 7 | 8 | Run `gulp` for development, `gulp build` for building and `gulp buildCordova` for building the hybrid-app. 9 | 10 | ## Testing 11 | 12 | Unit tests are automatically run with the default task. End-to-End tests are run via `gulp e2e`. 13 | 14 | ## The gulp tasks 15 | As per default the following tasks are available at your convenience: 16 | 17 | * `gulp`: The development task. Runs all the injectors on file-change, file-creation or file-deletion. Unit-tests are run in parallel, as well as the sass-compilation. 18 | * `gulp injectAll`: Runs all the injectors once. 19 | * `gulp build`: Minifies your JavaScript via ng-annotate, your css, your images and your html files and copies everything to the www-folder. 20 | * `gulp test`: Runs your unit tests with the keep-alive option. 21 | * `gulp testSingle`: Runs your unit tests once. 22 | * `gulp e2e`: Runs your end to end tests once. 23 | 24 | The mobile tasks require a little preparation described in the next section. 25 | 26 | * `gulp cordovaDev`: Symlinks your app-folder to www and runs the emulator for easy live development. 27 | * `gulp cordovaRun`: Symlinks your app-folder to www and runs it on your device if connected. 28 | 29 | Of course there are also all the [standard cordova commands](https://cordova.apache.org/docs/en/4.0.0/guide_cli_index.md.html) available as well. If you want to build a release run: 30 | ``` 31 | gulp build 32 | cordova build android --release 33 | ``` 34 | 35 | For all cordova related commands there is an optional platform parameter you can use to specify the platform for the cordova task. E.g. `gulp cordovaDev --platform=android` to run the android emulator. Alternatively you can edit the config.js to change the default platform. 36 | 37 | All tasks can be edited freely and can be found in the /tasks folder. 38 | 39 | ## Setting up the hybrid build 40 | Compiling your app to a hybrid app requires a little bit of configuration and you need to have cordova installed. Fortunately [that is quite easy](http://cordova.apache.org/docs/en/4.0.0/guide_cli_index.md.html#The%20Command-Line%20Interface). 41 | 42 | If everything is in place, you need to add the platforms you want to build your app on. For Android you would run: 43 | ``` 44 | cordova platform add android 45 | ``` 46 | If you get the message `Current working directory is not a Cordova-based project` you need to create the www-folder first (e.g.: `mkdir www` from your projects root directory). 47 | 48 | After that you should build your current state via `gulp build` then you can run `gulp run` or `gulp emulate` to check out your app on your device or in the emulator. -------------------------------------------------------------------------------- /templates/root/_bower.json: -------------------------------------------------------------------------------- 1 | {<% var ngVer = "1.6.6" %> 2 | "name": "<%= slugAppName %>", 3 | "version": "0.0.0", 4 | "authors": [ 5 | ], 6 | "license": "none", 7 | "private": true, 8 | "ignore": [ 9 | "**/.*", 10 | "node_modules", 11 | "bower_components", 12 | "test", 13 | "tests" 14 | ], 15 | "dependencies": { 16 | "json3": "latest", 17 | "es5-shim": "latest", 18 | "animate.css-scss": "latest", 19 | "angular": "^<%= ngVer %>"<% if (animateModule) { %>, 20 | "angular-animate": "^<%= ngVer %>"<% } %><% if (ariaModule) { %>, 21 | "angular-aria": "^<%= ngVer %>"<% } %><% if (cookiesModule) { %>, 22 | "angular-cookies": "^<%= ngVer %>"<% } %><% if (messagesModule) { %>, 23 | "angular-messages": "^<%= ngVer %>"<% } %><% if (resourceModule) { %>, 24 | "angular-resource": "^<%= ngVer %>"<% } %><% if (routeModule) { %>, 25 | "angular-route": "^<%= ngVer %>"<% } %><% if (sanitizeModule) { %>, 26 | "angular-sanitize": "^<%= ngVer %>"<% } %><% if (touchModule) { %>, 27 | "angular-touch": "^<%= ngVer %>"<% } %><% if (uiRouterModule) { %>, 28 | "angular-ui-router": "latest"<% } %><% if (ngMaterialModule) { %>, 29 | "angular-material": "latest"<% } %><% if (ngFabFormModule) { %>, 30 | "ng-fab-form": "latest"<% } %> 31 | }, 32 | "devDependencies": { 33 | "angular-mocks": "^<%= ngVer %>" 34 | }, 35 | "scripts":{ 36 | "postinstall": "gulp wiredep" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /templates/root/_bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "app/bower_components" 3 | } 4 | -------------------------------------------------------------------------------- /templates/root/_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | <%= humanizedAppName %> 4 | 5 | <%= humanizedAppName %> is fabulous 6 | 7 | 8 | Your Name 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /templates/root/_editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | charset = utf-8 10 | end_of_line = lf 11 | indent_size = 4 12 | indent_style = space 13 | insert_final_newline = true 14 | trim_trailing_whitespace = true 15 | 16 | [*.md] 17 | trim_trailing_whitespace = false 18 | 19 | [{package.json,bower.json,.travis.yml}] 20 | indent_size = 2 21 | -------------------------------------------------------------------------------- /templates/root/_gitattributes: -------------------------------------------------------------------------------- 1 | # Automatically normalize line endings for all text-based files 2 | # http://git-scm.com/docs/gitattributes#_end_of_line_conversion 3 | * text=auto 4 | 5 | # For the following file types, normalize line endings to LF on 6 | # checkin and prevent conversion to CRLF when they are checked out 7 | # (this is required in order to prevent newline related issues like, 8 | # for example, after the build script is run) 9 | .* text eol=lf 10 | *.css text eol=lf 11 | *.html text eol=lf 12 | *.js text eol=lf 13 | *.json text eol=lf 14 | *.md text eol=lf 15 | *.sh text eol=lf 16 | *.txt text eol=lf 17 | *.xml text eol=lf 18 | 19 | # Exclude the `.htaccess` file from GitHub's language statistics 20 | # https://github.com/github/linguist#using-gitattributes 21 | dist/.htaccess linguist-vendored -------------------------------------------------------------------------------- /templates/root/_gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | www 4 | platforms 5 | release 6 | .tmp 7 | app/styles/**/*.css 8 | app/styles/**/*.css.map 9 | .sass-cache 10 | bower_components 11 | app/bower_components 12 | *.log 13 | -------------------------------------------------------------------------------- /templates/root/_gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | // require all task files 3 | var requireDir = require('require-dir'); 4 | requireDir('./tasks'); 5 | -------------------------------------------------------------------------------- /templates/root/_jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "esnext": true, 5 | "bitwise": true, 6 | "camelcase": true, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "indent": 4, 10 | "latedef": "nofunc", 11 | "noarg": true, 12 | "quotmark": "single", 13 | "undef": true, 14 | "unused": true, 15 | "strict": true, 16 | "trailing": true, 17 | "smarttabs": true, 18 | "globals": { 19 | "angular": false, 20 | "browser": false, 21 | "jasmine": false, 22 | "describe": false, 23 | "xdescribe": false, 24 | "before": false, 25 | "beforeEach": false, 26 | "after": false, 27 | "afterEach": false, 28 | "it": false, 29 | "xit": false, 30 | "it": false, 31 | "inject": false, 32 | "expect": false, 33 | "spyOn": false 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /templates/root/_karma-e2e.conf.js: -------------------------------------------------------------------------------- 1 | // An example configuration file. 2 | 'use strict'; 3 | 4 | exports.config = { 5 | // The address of a running selenium server. 6 | seleniumAddress: 'http://localhost:4444/wd/hub', 7 | 8 | // Spec patterns are relative to the current working directly when 9 | // protractor is called. 10 | specs: ['e2e-tests/**/*.js'], 11 | 12 | // Options to be passed to Jasmine-node. 13 | jasmineNodeOpts: { 14 | showColors: true, 15 | defaultTimeoutInterval: 30000, 16 | isVerbose: true 17 | }, 18 | 19 | onPrepare: function() { 20 | browser.manage() 21 | .window() 22 | .setSize(1360, 768); 23 | browser.manage() 24 | .timeouts() 25 | .setScriptTimeout(20000); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /templates/root/_karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | 'use strict'; 3 | 4 | module.exports = function(config) { 5 | config.set({ 6 | // base path that will be used to resolve all patterns (eg. files, exclude) 7 | basePath: '', 8 | 9 | // frameworks to use 10 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 11 | frameworks: ['jasmine'], 12 | 13 | 14 | // list of files / patterns to load in the browser 15 | files: [ 16 | // bower:js 17 | // endbower 18 | 19 | // modules first 20 | 'app/scripts/**/_*.js', 21 | // all the rest of the files 22 | 'app/scripts/**/*.js', 23 | // load html as well as required for karma-ng-html2js-preprocessor 24 | 'app/scripts/**/*.html' 25 | ], 26 | 27 | 28 | // list of files to exclude 29 | exclude: [], 30 | 31 | 32 | // web server port 33 | port: 9876, 34 | 35 | 36 | // enable / disable colors in the output (reporters and logs) 37 | colors: true, 38 | 39 | 40 | // level of logging 41 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 42 | logLevel: config.LOG_INFO, 43 | 44 | plugins: [ 45 | 'karma-jasmine', 46 | //'karma-coverage', 47 | 'karma-phantomjs-launcher', 48 | 'karma-ng-html2js-preprocessor' 49 | ], 50 | 51 | preprocessors: { 52 | //'**/app/scripts/**/!(*spec).js': 'coverage', 53 | '**/app/scripts/**/*.html': 'ng-html2js' 54 | }, 55 | 56 | ngHtml2JsPreprocessor: { 57 | moduleName: 'templates', 58 | stripPrefix: 'app/' 59 | }, 60 | 61 | // enable / disable watching file and executing tests whenever any file changes 62 | autoWatch: false, 63 | 64 | 65 | // start these browsers 66 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 67 | browsers: ['PhantomJS'], 68 | 69 | 70 | // Continuous Integration mode 71 | // if true, Karma captures browsers, runs the tests and exits 72 | singleRun: true 73 | }); 74 | }; 75 | -------------------------------------------------------------------------------- /templates/root/_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "<%= slugAppName %>", 3 | "version": "0.0.0", 4 | "description": "", 5 | "main": "gulpfile.js", 6 | "repository": {}, 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "author": "", 11 | "license": "none", 12 | "devDependencies": { 13 | "autoprefixer-core": "latest", 14 | "browser-sync": "latest", 15 | "del": "latest", 16 | "ecstatic": "latest", 17 | "gulp": "latest", 18 | "gulp-autoprefixer": "latest", 19 | "gulp-clean-css": "latest", 20 | "gulp-if": "latest", 21 | "gulp-imagemin": "latest", 22 | "gulp-inject": "latest", 23 | "gulp-jscs": "latest", 24 | "gulp-jshint": "latest", 25 | "gulp-livereload": "latest", 26 | "gulp-minify-html": "latest", 27 | "gulp-natural-sort": "latest", 28 | "gulp-ng-annotate": "latest", 29 | "gulp-ng-config": "latest", 30 | "gulp-plumber": "latest", 31 | "gulp-protractor": "latest", 32 | "gulp-sass": "latest", 33 | "gulp-shell": "latest", 34 | "gulp-sourcemaps": "latest", 35 | "gulp-symlink": "latest", 36 | "gulp-uglify": "latest", 37 | "gulp-useref": "latest", 38 | "gulp-util": "latest", 39 | "gulp-watch": "latest", 40 | "jasmine-core": "latest", 41 | "jshint": "latest", 42 | "jshint-stylish": "latest", 43 | "karma": "latest", 44 | "karma-jasmine": "latest", 45 | "karma-ng-html2js-preprocessor": "latest", 46 | "karma-phantomjs-launcher": "latest", 47 | "lazypipe": "latest", 48 | "merge-stream": "latest", 49 | "node-sass": "latest", 50 | "protractor": "latest", 51 | "phantomjs-prebuilt": "latest", 52 | "require-dir": "latest", 53 | "run-sequence": "latest", 54 | "uglify-save-license": "^0.4.1", 55 | "wiredep": "latest", 56 | "yargs": "latest" 57 | }, 58 | "dependencies": { 59 | "cordova-android": "latest" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /templates/root/_travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.10' 4 | before_script: 5 | - 'npm install -g bower grunt-cli' 6 | - 'bower install' 7 | -------------------------------------------------------------------------------- /templates/styles/_functions/_some-function.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johannesjo/generator-modular-angular/06e3d19b171ab4beba97cdcfa5c60b9d827c7d7b/templates/styles/_functions/_some-function.scss -------------------------------------------------------------------------------- /templates/styles/_mixins/_some-mixin.scss: -------------------------------------------------------------------------------- 1 | @mixin some-mixin() { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /templates/styles/_placeholders/_some-placeholder.scss: -------------------------------------------------------------------------------- 1 | %some-placeholder { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /templates/styles/_variables.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johannesjo/generator-modular-angular/06e3d19b171ab4beba97cdcfa5c60b9d827c7d7b/templates/styles/_variables.scss -------------------------------------------------------------------------------- /templates/styles/base/_buttons.scss: -------------------------------------------------------------------------------- 1 | button { 2 | text-align: center; 3 | 4 | &:hover { 5 | 6 | } 7 | &:active { 8 | 9 | } 10 | &:focus { 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /templates/styles/base/_fonts.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johannesjo/generator-modular-angular/06e3d19b171ab4beba97cdcfa5c60b9d827c7d7b/templates/styles/base/_fonts.scss -------------------------------------------------------------------------------- /templates/styles/base/_forms.scss: -------------------------------------------------------------------------------- 1 | form { 2 | 3 | } 4 | 5 | fieldset { 6 | 7 | } 8 | 9 | input { 10 | &[type="text"], 11 | &[type="password"], 12 | &[type="email"] { 13 | 14 | } 15 | 16 | &[type="radio"] { 17 | 18 | } 19 | 20 | &[type="checkbox"] { 21 | 22 | } 23 | 24 | &[type="number"] { 25 | 26 | } 27 | } 28 | 29 | select { 30 | 31 | } 32 | 33 | textarea { 34 | 35 | } 36 | -------------------------------------------------------------------------------- /templates/styles/base/_icons.scss: -------------------------------------------------------------------------------- 1 | [class^="icon-"], [class*=" icon-"] { 2 | font-family: 'icon-font'; 3 | speak: none; 4 | font-style: normal; 5 | font-weight: normal; 6 | font-variant: normal; 7 | text-transform: none; 8 | line-height: 1; 9 | /* Better Font Rendering =========== */ 10 | -webkit-font-smoothing: antialiased; 11 | -moz-osx-font-smoothing: grayscale; 12 | } 13 | -------------------------------------------------------------------------------- /templates/styles/base/_lists.scss: -------------------------------------------------------------------------------- 1 | ul { 2 | li { 3 | 4 | } 5 | } 6 | 7 | ol { 8 | li { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /templates/styles/base/_page.scss: -------------------------------------------------------------------------------- 1 | * { 2 | // global reset and border-box 3 | &, 4 | &:after, 5 | &:before { 6 | -webkit-box-sizing: border-box; 7 | -moz-box-sizing: border-box; 8 | box-sizing: border-box; 9 | } 10 | } 11 | 12 | body, 13 | html { 14 | // prevent overflow 15 | width: 100%; 16 | max-width: 100%; 17 | overflow-x: hidden; 18 | } 19 | 20 | main { 21 | 22 | } 23 | 24 | article { 25 | 26 | } 27 | -------------------------------------------------------------------------------- /templates/styles/base/_tables.scss: -------------------------------------------------------------------------------- 1 | table { 2 | 3 | } 4 | 5 | thead { 6 | 7 | } 8 | 9 | tbody { 10 | 11 | } 12 | 13 | tfoot { 14 | 15 | } 16 | 17 | tr { 18 | 19 | } 20 | 21 | td { 22 | 23 | } 24 | -------------------------------------------------------------------------------- /templates/styles/base/_typography.scss: -------------------------------------------------------------------------------- 1 | h1, 2 | h2, 3 | h3, 4 | h4, 5 | h5, 6 | h6 { 7 | 8 | } 9 | 10 | p { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /templates/styles/main.scss: -------------------------------------------------------------------------------- 1 | /* 2 | IMPORTANT NOTE: 3 | This file SHOULD NOT BE EDITED MANUALLY, as its purpose 4 | is to be the point where all your stylesheet-files will 5 | be imported 6 | */ 7 | 8 | 9 | 10 | // inject:sass 11 | 12 | @import '_variables.scss'; 13 | 14 | @import 'base/_buttons.scss'; 15 | 16 | @import 'base/_fonts.scss'; 17 | 18 | @import 'base/_forms.scss'; 19 | 20 | @import 'base/_icons.scss'; 21 | 22 | @import 'base/_lists.scss'; 23 | 24 | @import 'base/_page.scss'; 25 | 26 | @import 'base/_tables.scss'; 27 | 28 | @import 'base/_typography.scss'; 29 | 30 | @import 'functions/_some-function.scss'; 31 | 32 | @import 'mixins/_some-mixin.scss'; 33 | 34 | @import 'placeholders/_some-placeholder.scss'; 35 | 36 | // endinject 37 | -------------------------------------------------------------------------------- /templates/tasks/build.js: -------------------------------------------------------------------------------- 1 | var config = require('./config'); 2 | var gulp = require('gulp'); 3 | 4 | /** 5 | * Build-Task Files 6 | * 7 | * NOTE: Depends on sme of the dev-tasks as well 8 | */ 9 | 10 | 11 | var del = require('del'); 12 | var gulpif = require('gulp-if'); 13 | var minifyHtml = require('gulp-minify-html'); 14 | var cleanCSS = require('gulp-clean-css'); 15 | var useref = require('gulp-useref'); 16 | var sourcemaps = require('gulp-sourcemaps'); 17 | var ngAnnotate = require('gulp-ng-annotate'); 18 | var uglify = require('gulp-uglify'); 19 | var saveLicense = require('uglify-save-license'); 20 | var imagemin = require('gulp-imagemin'); 21 | var runSequence = require('run-sequence') 22 | .use(gulp); 23 | var wiredep = require('wiredep').stream; 24 | 25 | var merge = require('merge-stream'); 26 | var lazypipe = require('lazypipe'); 27 | 28 | 29 | // main task 30 | gulp.task('build', function(callback) { 31 | runSequence( 32 | 'cleanDist', 33 | 'wiredepBuild', 34 | 'injectAll', 35 | 'testSingle', 36 | 'lint', 37 | 'sass', 38 | 'minFiles', 39 | 'copy', 40 | // reset config 41 | //'ngConfig', 42 | callback); 43 | }); 44 | 45 | gulp.task('wiredepBuild', function() { 46 | return gulp.src([config.karmaConf, config.mainFile], {base: './'}) 47 | .pipe(wiredep({ 48 | exclude: [ 49 | // TODO inject excluded 50 | ], 51 | devDependencies: false 52 | })) 53 | .pipe(gulp.dest('./')); 54 | }); 55 | 56 | gulp.task('cleanDist', function() { 57 | return del.sync(config.dist); 58 | }); 59 | 60 | 61 | gulp.task('copy', function() { 62 | var html = gulp.src(config.htmlF, {base: config.base}) 63 | .pipe(minifyHtml({ 64 | conditionals: true, 65 | loose: true, 66 | empty: true, 67 | quotes: true 68 | })) 69 | .pipe(gulp.dest(config.dist)); 70 | 71 | var fonts = gulp.src(config.fontsF, {base: config.base}) 72 | .pipe(gulp.dest(config.dist)); 73 | 74 | // TODO this ain't perfect 75 | var images = gulp.src(config.imagesF, {base: config.base}) 76 | .pipe(imagemin({ 77 | progressive: true, 78 | svgoPlugins: [{removeViewBox: false}] 79 | })) 80 | .pipe(gulp.dest(config.dist)); 81 | 82 | return merge(html, fonts, images); 83 | }); 84 | 85 | 86 | gulp.task('minFiles', function() { 87 | return gulp.src(config.mainFile) 88 | .pipe(useref({}, lazypipe() 89 | .pipe(sourcemaps.init, {loadMaps: true}))) 90 | .pipe(gulpif('*.js', ngAnnotate())) 91 | .pipe(gulpif(/\.js$/, uglify({ 92 | output: { 93 | comments: saveLicense 94 | } 95 | }))) 96 | .pipe(gulpif('*.css', cleanCSS())) 97 | .pipe(gulp.dest(config.dist)); 98 | }); 99 | -------------------------------------------------------------------------------- /templates/tasks/config.js: -------------------------------------------------------------------------------- 1 | module.exports = (function() { 2 | 'use strict'; 3 | 4 | // config vars 5 | var base = './app'; 6 | var scripts = base + '/scripts'; 7 | var sass = base + '/styles'; 8 | 9 | var data = { 10 | browserSyncPort: 3000, 11 | cordovaPath: 'cordova', 12 | defaultPlatform: 'ios', 13 | excludedBowerComponents: ['es5-shim', 'json3'], 14 | base: base, 15 | mainFile: base + '/index.html', 16 | mainSassFile: sass + '/main.scss', 17 | routesFiles: base + '/scripts/_routes.js', 18 | e2eBaseUrl: 'http://localhost:3000/', 19 | styles: base + '/styles/', 20 | stylesF: [ 21 | base + '/styles/**/_*.{scss,sass,less}', 22 | scripts + '/**/*.{scss,sass,less}' 23 | ], 24 | stylesAllF: [ 25 | base + '/styles/**/*.{scss,sass,less}', 26 | scripts + '/**/*.{scss,sass,less}' 27 | ], 28 | scripts: base + '/scripts/', 29 | scriptsF: [ 30 | // modules first 31 | base + '/scripts/**/_*.js', 32 | base + '/scripts/**/*.js', 33 | '!' + base + '/scripts/**/*.spec.js' 34 | ], 35 | scriptsAllF: base + '/scripts/**/*.js', 36 | scriptTestsF: base + '/scripts/**/*.spec.js', 37 | html: base + '/scripts/', 38 | htmlF: [ 39 | base + '/scripts/**/*.html' 40 | ], 41 | images: base + '/images/', 42 | imagesF: base + '/images/**/*.*', 43 | fonts: base + '/fonts/', 44 | fontsF: base + '/fonts/**/*.*', 45 | tmp: './.tmp', 46 | dist: 'www', 47 | wwwDestination: '', 48 | karmaConf: './karma.conf.js', 49 | karmaConfE2E: './karma-e2e.conf.js' 50 | }; 51 | 52 | data.allHtmlF = data.htmlF.slice() 53 | data.allHtmlF.push(data.mainFile); 54 | 55 | return data; 56 | })(); 57 | -------------------------------------------------------------------------------- /templates/tasks/cordova.js: -------------------------------------------------------------------------------- 1 | var config = require('./config'); 2 | var gulp = require('gulp'); 3 | 4 | /** 5 | * Cordova-Build-Task Files 6 | * 7 | * NOTE: Depends on some of the build-tasks as well 8 | * inspired by: 9 | * @url https://github.com/kamrik/CordovaGulpTemplate 10 | */ 11 | 12 | var plugins = ['org.apache.cordova.file']; 13 | 14 | var path = require('path'); 15 | var shell = require('gulp-shell'); 16 | var runSequence = require('run-sequence') 17 | .use(gulp); 18 | var symlink = require('gulp-symlink'); 19 | var argv = require('yargs').argv; 20 | 21 | var watch = require('gulp-watch'); 22 | var livereload = require('gulp-livereload'); 23 | var http = require('http'); 24 | var ecstatic = require('ecstatic'); 25 | var gutil = require('gulp-util'); 26 | var sass = require('gulp-sass'); 27 | 28 | function platformArg() { 29 | return (argv.platform || config.defaultPlatform); 30 | } 31 | 32 | gulp.task('cordovaDev', function(cb) { 33 | //gulp.start('test'); 34 | 35 | runSequence( 36 | 'cleanDist', 37 | 'symlinkApp', 38 | 'ngConfig', 39 | 'injectAll', 40 | 'buildStyles', 41 | 'browserSync', 42 | 'cordovaServer', 43 | 'cordovaEmulate', 44 | ['watchForCordova', 'watch'], 45 | cb 46 | ); 47 | }); 48 | 49 | 50 | gulp.task('cordovaRun', function(cb) { 51 | runSequence( 52 | 'cleanDist', 53 | 'symlinkApp', 54 | 'ngConfig', 55 | 'injectAll', 56 | 'buildStyles', 57 | 'browserSync', 58 | 'cordovaServer', 59 | 'cordovaRunOnDevice', 60 | ['watchForCordova', 'watch'], 61 | cb 62 | ); 63 | }); 64 | 65 | 66 | gulp.task('watchForCordova', function() { 67 | livereload.listen(); 68 | var projectFiles = config.base + '/**/*.*'; 69 | return gulp.src(projectFiles) 70 | .pipe(watch(projectFiles)) 71 | .pipe(gulp.dest('./platforms/' + platformArg() + '/www/')) 72 | .pipe(livereload()); 73 | }); 74 | 75 | 76 | gulp.task('cordovaServer', function() { 77 | var port = 8000; 78 | var url = "http://localhost:" + port + "/"; 79 | http.createServer(ecstatic({ 80 | root: "platforms", 81 | cache: 0 82 | })) 83 | .listen(port); 84 | 85 | gutil.log(gutil.colors.blue("HTTP server listening on " + port)); 86 | }); 87 | 88 | 89 | gulp.task('cordovaEmulate', shell.task([ 90 | config.cordovaPath + ' emulate ' + platformArg() + ' -l -s -c' 91 | ])); 92 | 93 | 94 | gulp.task('cordovaRunOnDevice', shell.task([ 95 | config.cordovaPath + ' run ' + platformArg() + ' -l -s -c' 96 | ])); 97 | 98 | 99 | gulp.task('symlinkApp', function() { 100 | return gulp.src(config.base) 101 | .pipe(symlink(config.dist)); 102 | }); 103 | 104 | 105 | gulp.task('buildCordova', shell.task([ 106 | config.cordovaPath + ' build ' + platformArg() + '' 107 | ])); 108 | 109 | -------------------------------------------------------------------------------- /templates/tasks/deploy.js: -------------------------------------------------------------------------------- 1 | var config = require('./config'); 2 | var gulp = require('gulp'); 3 | //var rsync = require('rsyncwrapper').rsync; 4 | 5 | /** 6 | * Build-Task Files 7 | * 8 | * NOTE: Hard to make assumptions about this one 9 | * so be creative ;) 10 | */ 11 | 12 | //gulp.task('deploy', function () 13 | //{ 14 | // rsync({ 15 | // ssh: true, 16 | // src: config.dist, 17 | // recursive: true, 18 | // dest: config.wwwDestination, 19 | // syncDest: true, 20 | // args: ['--verbose'] 21 | // }, function (error, stdout, stderr) 22 | // { 23 | // console.log(error); 24 | // console.log(stdout); 25 | // console.log(stderr); 26 | // }); 27 | //}); -------------------------------------------------------------------------------- /templates/tasks/dev.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /* jshint camelcase: false */ 3 | 4 | var config = require('./config'); 5 | var gulp = require('gulp'); 6 | 7 | /** 8 | * Dev Task File 9 | * 10 | */ 11 | 12 | 13 | var sass = require('gulp-sass').sync; 14 | var autoprefixer = require('gulp-autoprefixer'); 15 | var sourcemaps = require('gulp-sourcemaps'); 16 | var wiredep = require('wiredep').stream; 17 | var inj = require('gulp-inject'); 18 | 19 | var browserSync = require('browser-sync'); 20 | var reload = browserSync.reload; 21 | var watch = require('gulp-watch'); 22 | var runSequence = require('run-sequence') 23 | .use(gulp); 24 | 25 | var jshint = require('gulp-jshint'); 26 | var jscs = require('gulp-jscs'); 27 | var KarmaServer = require('karma').Server; 28 | 29 | // var gulpNgConfig = require('gulp-ng-config'); 30 | 31 | var merge = require('merge-stream'); 32 | var plumber = require('gulp-plumber'); 33 | var sort = require('gulp-natural-sort'); 34 | 35 | // main task 36 | gulp.task('default', function(cb) { 37 | runSequence( 38 | //'ngConfig', 39 | 'wiredep', 40 | 'lint', 41 | 'beautify', 42 | 'injectAll', 43 | 'buildStyles', 44 | 'browserSync', 45 | 'watch', 46 | function() { 47 | // run in parallel but afterwards 48 | gulp.start('test'); 49 | cb(); 50 | } 51 | ); 52 | }); 53 | gulp.task('serve', ['default']); 54 | gulp.task('server', ['default']); 55 | 56 | 57 | gulp.task('injectAll', function(callback) { 58 | runSequence( 59 | 'wiredep', 60 | 'injectScripts', 61 | 'injectStyles', 62 | 'beautify', 63 | callback 64 | ); 65 | }); 66 | 67 | 68 | gulp.task('watch', function(cb) { 69 | watch(config.stylesF, function() { 70 | gulp.start('buildStyles') 71 | .on('end', cb); 72 | }); 73 | watch(config.scriptsF, function() { 74 | gulp.start('injectScripts') 75 | .on('end', cb); 76 | }); 77 | watch(config.scriptsAllF, function() { 78 | gulp.start('lint') 79 | .on('end', cb); 80 | }); 81 | watch(config.allHtmlF, function() { 82 | gulp.start('html') 83 | .on('end', cb); 84 | }); 85 | 86 | //gulp.watch('bower.json', ['wiredep']); 87 | 88 | // enable at your convenience 89 | //watch(config.scripts + '*.json', function() { 90 | // gulp.start('ngConfig') 91 | // .on('end', cb); 92 | //}); 93 | }); 94 | 95 | 96 | gulp.task('buildStyles', function(cb) { 97 | runSequence( 98 | 'injectStyles', 99 | 'sass', 100 | cb 101 | ); 102 | }); 103 | 104 | 105 | gulp.task('injectStyles', function() { 106 | var sources = gulp.src(config.stylesF, {read: false}) 107 | .pipe(sort()); 108 | var target = gulp.src(config.mainSassFile); 109 | var outputFolder = gulp.dest(config.styles); 110 | 111 | return target 112 | .pipe(inj(sources, 113 | { 114 | starttag: '// inject:sass', 115 | endtag: '// endinject', 116 | ignorePath: [config.base.replace('./', ''), 'styles'], 117 | relative: true, 118 | addRootSlash: false, 119 | transform: function(filepath) { 120 | if (filepath) { 121 | return '@import \'' + filepath + '\';'; 122 | } 123 | } 124 | } 125 | )) 126 | .pipe(outputFolder); 127 | }); 128 | 129 | 130 | gulp.task('injectScripts', function() { 131 | var sources = gulp.src(config.scriptsF, {read: true}) 132 | .pipe(sort()); 133 | var target = gulp.src(config.mainFile); 134 | return target 135 | .pipe(inj(sources, 136 | { 137 | ignorePath: config.base.replace('./', ''), 138 | addRootSlash: false 139 | } 140 | )) 141 | .pipe(gulp.dest(config.base)); 142 | }); 143 | 144 | 145 | gulp.task('sass', function() { 146 | var sources = gulp.src(config.mainSassFile); 147 | var outputFolder = gulp.dest(config.styles); 148 | 149 | return sources 150 | .pipe(plumber({ 151 | handleError: function(err) { 152 | console.log(err); 153 | this.emit('end'); 154 | } 155 | })) 156 | .pipe(sourcemaps.init()) 157 | .pipe(sass({errLogToConsole: true})) 158 | .pipe(autoprefixer({ 159 | browsers: ['> 0.1%'] 160 | })) 161 | .pipe(sourcemaps.write('.')) 162 | .pipe(gulp.dest(config.tmp)) 163 | .pipe(gulp.dest(config.styles)) 164 | .pipe(outputFolder) 165 | .pipe(browserSync.stream()); 166 | }); 167 | 168 | 169 | gulp.task('browserSync', function() { 170 | browserSync({ 171 | port: config.browserSyncPort, 172 | server: { 173 | baseDir: config.base, 174 | livereload: true 175 | } 176 | }); 177 | }); 178 | 179 | 180 | gulp.task('html', function() { 181 | return gulp.src(config.allHtmlF) 182 | .pipe(reload({stream: true})); 183 | }); 184 | 185 | 186 | gulp.task('wiredep', ['wirdepKarma', 'wiredepIndex']); 187 | 188 | gulp.task('wirdepKarma', function() { 189 | return gulp.src(config.karmaConf, {base: './'}) 190 | .pipe(wiredep({ 191 | devDependencies: true, 192 | exclude: config.excludedBowerComponents 193 | })) 194 | // required as weird workaround for not messing up the files 195 | .pipe(gulp.dest(config.tmp)) 196 | .pipe(gulp.dest('./')); 197 | }); 198 | 199 | gulp.task('wiredepIndex', function() { 200 | return gulp.src(config.mainFile, {base: './'}) 201 | .pipe(wiredep({ 202 | devDependencies: false, 203 | exclude: config.excludedBowerComponents 204 | })) 205 | // required as weird workaround for not messing up the files 206 | .pipe(gulp.dest(config.tmp)) 207 | .pipe(gulp.dest('./')); 208 | }); 209 | 210 | 211 | gulp.task('test', function(done) { 212 | new KarmaServer({ 213 | configFile: __dirname + '/../karma.conf.js', 214 | action: 'watch', 215 | autoWatch: true, 216 | singleRun: false 217 | }, done).start(); 218 | }); 219 | 220 | 221 | gulp.task('testSingle', function(done) { 222 | new KarmaServer({ 223 | configFile: __dirname + '/../karma.conf.js', 224 | action: 'run', 225 | autoWatch: false, 226 | singleRun: true 227 | }, done).start(); 228 | }); 229 | 230 | 231 | gulp.task('lint', function() { 232 | return gulp.src([ 233 | config.scriptsAllF, 234 | './karma-e2e.conf.js', 235 | './karma.conf.js', 236 | './gulpfile.js' 237 | ], {base: './'}) 238 | .pipe(jshint()) 239 | .pipe(jshint.reporter('jshint-stylish')) 240 | .pipe(jscs()); 241 | }); 242 | 243 | gulp.task('beautify', function() { 244 | return gulp.src([ 245 | config.scriptsAllF, 246 | './karma-e2e.conf.js', 247 | './karma.conf.js', 248 | './gulpfile.js' 249 | ], {base: './'}) 250 | .pipe(jscs({fix: true})) 251 | .pipe(gulp.dest('./')); 252 | }); 253 | 254 | 255 | //gulp.task('ngConfig', function () { 256 | // return gulp.src(config.scripts + 'constants.json') 257 | // .pipe(gulpNgConfig('config', { 258 | // wrap: '(function () {\n\'use strict\';\n/*jshint ignore:start*/\n return <%= ngConfModulePlaceholder %> /*jshint ignore:end*/\n})();', 259 | // environment: 'dev' 260 | // })) 261 | // .pipe(gulp.dest(config.scripts)) 262 | //}); 263 | 264 | -------------------------------------------------------------------------------- /templates/tasks/e2e.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /* jshint camelcase: false */ 3 | 4 | var config = require('./config'); 5 | var gulp = require('gulp'); 6 | 7 | var protractor = require('gulp-protractor'); 8 | var browserSync = require('browser-sync'); 9 | 10 | 11 | gulp.task('protractor', ['protractor:src']); 12 | gulp.task('e2e', [ 13 | 'browserSync', 14 | 'webdriver-update' 15 | ], runProtractor); 16 | 17 | 18 | gulp.task('webdriver-update', protractor.webdriver_update); 19 | gulp.task('webdriver-standalone', protractor.webdriver_standalone); 20 | 21 | function runProtractor(done) { 22 | gulp.src('.nonononoNOTHING') 23 | .pipe(protractor.protractor({ 24 | configFile: './karma-e2e.conf.js' 25 | })) 26 | .on('error', function(err) { 27 | // Make sure failed tests cause gulp to exit non-zero 28 | throw err; 29 | }) 30 | .on('end', function() { 31 | // Close browser sync server 32 | browserSync.exit(); 33 | done(); 34 | }); 35 | } 36 | 37 | -------------------------------------------------------------------------------- /test-app/injections.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var path = require('path'); 3 | var helpers = require('yeoman-test'); 4 | var assert = require('yeoman-assert'); 5 | var exec = require('child_process').exec; 6 | var fs = require('fs'); 7 | 8 | 9 | describe('gulp inject', function() { 10 | var instancePath = path.join(__dirname, '../.test-instance'); 11 | var gulp = '$(which gulp)'; 12 | this.timeout(20000); 13 | 14 | 15 | describe('styles', function() { 16 | var mainScss = path.join(instancePath, 'app/styles/main.scss'); 17 | var injectStylesCmd = gulp + ' injectStyles'; 18 | 19 | describe('scss partials in styles folder', function() { 20 | var expectedContent = [ 21 | [mainScss, /_variables/], 22 | [mainScss, /base\/_buttons\.scss/], 23 | [mainScss, /base\/_fonts\.scss/], 24 | [mainScss, /base\/_forms\.scss/], 25 | [mainScss, /base\/_icons\.scss/], 26 | [mainScss, /base\/_lists\.scss/], 27 | [mainScss, /base\/_page\.scss/], 28 | [mainScss, /base\/_tables\.scss/], 29 | [mainScss, /base\/_typography\.scss/], 30 | [mainScss, /functions\/_some-function\.scss/], 31 | [mainScss, /mixins\/_some-mixin\.scss/], 32 | [mainScss, /placeholders\/_some-placeholder\.scss/] 33 | ]; 34 | var expected = [ 35 | mainScss 36 | ]; 37 | 38 | beforeEach(function(done) { 39 | fs.truncateSync(mainScss); 40 | fs.writeFileSync(mainScss, '// inject:sass\n\n// endinject'); 41 | exec(injectStylesCmd, { 42 | cwd: instancePath 43 | }, function() { 44 | done(); 45 | }); 46 | }); 47 | 48 | it('adds imports for default files', function() { 49 | assert.file([].concat( 50 | expected 51 | )); 52 | assert.fileContent([].concat( 53 | expectedContent 54 | )); 55 | }); 56 | }); 57 | }); 58 | 59 | describe('scripts', function() { 60 | var mainHtml = path.join(instancePath, 'app/index.html'); 61 | var injectScriptsCmd = gulp + ' injectScripts'; 62 | var cachedMainFileContent; 63 | 64 | describe('scripts into index.html', function() { 65 | var expectedContent = [ 66 | [mainHtml, /_app\.js/] 67 | ]; 68 | var expected = [ 69 | mainHtml 70 | ]; 71 | 72 | beforeEach(function(done) { 73 | cachedMainFileContent = fs.readFileSync(mainHtml, 'utf8'); 74 | fs.truncateSync(mainHtml); 75 | fs.writeFileSync(mainHtml, '\n'); 76 | exec(injectScriptsCmd, { 77 | cwd: instancePath 78 | }, function() { 79 | done(); 80 | }); 81 | }); 82 | 83 | afterEach(function() { 84 | // restore old html 85 | fs.truncateSync(mainHtml); 86 | fs.writeFileSync(mainHtml, cachedMainFileContent); 87 | }); 88 | 89 | it('adds imports for script files', function() { 90 | assert.file([].concat( 91 | expected 92 | )); 93 | assert.fileContent([].concat( 94 | expectedContent 95 | )); 96 | }); 97 | }); 98 | }); 99 | 100 | 101 | describe('wiredep', function() { 102 | var mainHtml = path.join(instancePath, 'app/index.html'); 103 | var wiredepCmd = gulp + ' wiredep'; 104 | var cachedMainFileContent; 105 | 106 | describe('bower-components into index.html', function() { 107 | var expectedContent = [ 108 | [mainHtml, /bower_components\/angular\/angular\.js/] 109 | ]; 110 | var expected = [ 111 | mainHtml 112 | ]; 113 | 114 | beforeEach(function(done) { 115 | cachedMainFileContent = fs.readFileSync(mainHtml, 'utf8'); 116 | fs.truncateSync(mainHtml); 117 | fs.writeFileSync(mainHtml, '\n'); 118 | exec(wiredepCmd, { 119 | cwd: instancePath 120 | }, function() { 121 | done(); 122 | }); 123 | }); 124 | 125 | afterEach(function() { 126 | // restore old html 127 | fs.truncateSync(mainHtml); 128 | fs.writeFileSync(mainHtml, cachedMainFileContent); 129 | }); 130 | 131 | it('adds imports for bower-components', function() { 132 | assert.file([].concat( 133 | expected 134 | )); 135 | assert.fileContent([].concat( 136 | expectedContent 137 | )); 138 | }); 139 | }); 140 | }); 141 | }); -------------------------------------------------------------------------------- /test-app/styles.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var path = require('path'); 3 | var helpers = require('yeoman-test'); 4 | var assert = require('yeoman-assert'); 5 | var exec = require('child_process').exec; 6 | var fs = require('fs'); 7 | 8 | 9 | describe('gulp buildStyles', function() { 10 | var instancePath = path.join(__dirname, '../.test-instance'); 11 | var gulp = '$(which gulp)'; 12 | this.timeout(20000); 13 | var stylesDir = path.join(instancePath, 'app/styles'); 14 | var testFileInStylesDir = path.join(stylesDir, 'base/_test.scss'); 15 | var testFileInScritsDir = path.join(instancePath, 'app/scripts/_test.scss'); 16 | var mainScss = path.join(stylesDir, 'main.scss'); 17 | var mainCss = path.join(stylesDir, 'main.css'); 18 | var injectStylesCmd = gulp + ' injectStyles'; 19 | var sassCmd = gulp + ' sass'; 20 | 21 | 22 | describe('autoprefixer, sourcemap as base 64 and general compilation', function() { 23 | var expectedContent = [ 24 | [mainScss, /_variables/], 25 | [mainScss, /base\/_buttons\.scss/], 26 | [mainScss, /base\/_fonts\.scss/], 27 | [mainScss, /base\/_forms\.scss/], 28 | [mainScss, /base\/_icons\.scss/], 29 | [mainScss, /base\/_lists\.scss/], 30 | [mainScss, /base\/_page\.scss/], 31 | [mainScss, /base\/_tables\.scss/], 32 | [mainScss, /base\/_typography\.scss/], 33 | [mainScss, /functions\/_some-function\.scss/], 34 | [mainScss, /mixins\/_some-mixin\.scss/], 35 | [mainScss, /placeholders\/_some-placeholder\.scss/], 36 | [mainScss, /base\/_test\.scss/], 37 | [mainScss, /\.\.\/scripts\/_test\.scss/], 38 | [mainCss, /\.styles/], 39 | [mainCss, /\.scripts/], 40 | [mainCss, /color: blue;/], 41 | [mainCss, /sourceMappingURL=main\.css\.map/] 42 | ]; 43 | 44 | beforeEach(function(done) { 45 | fs.truncateSync(mainScss); 46 | fs.writeFileSync(testFileInScritsDir, '.scripts-class{color:blue;}'); 47 | fs.writeFileSync(testFileInStylesDir, '.styles-class{background: linear-gradient(to bottom right, yellow, green);}'); 48 | fs.writeFileSync(mainScss, '// inject:sass\n\n// endinject'); 49 | exec(injectStylesCmd, { 50 | cwd: instancePath 51 | }, function(err, stdout) { 52 | exec(sassCmd, { 53 | cwd: instancePath 54 | }, function(err, stdout) { 55 | done(); 56 | }); 57 | }); 58 | }); 59 | 60 | afterEach(function() { 61 | fs.unlinkSync(testFileInScritsDir); 62 | fs.unlinkSync(testFileInStylesDir); 63 | }); 64 | 65 | it('creates expected files', function() { 66 | assert.file([ 67 | mainCss, 68 | mainScss, 69 | testFileInScritsDir, 70 | testFileInStylesDir 71 | ]); 72 | assert.fileContent([].concat( 73 | expectedContent 74 | )); 75 | }); 76 | }); 77 | }); -------------------------------------------------------------------------------- /test/app.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var path = require('path'); 3 | var helpers = require('yeoman-test'); 4 | var assert = require('yeoman-assert'); 5 | 6 | describe('moda generator', function() { 7 | var alwaysExpected = [ 8 | '.editorconfig', 9 | '.gitignore', 10 | '.gitattributes', 11 | 'package.json', 12 | 'bower.json', 13 | '.bowerrc', 14 | 'gulpfile.js', 15 | 'config.xml', 16 | '.jshintrc', 17 | '.jscsrc', 18 | '.travis.yml', 19 | 'karma.conf.js', 20 | 'karma-e2e.conf.js', 21 | 'app/index.html', 22 | 'app/scripts/_app.js', 23 | 'app/scripts/_app.spec.js', 24 | 'tasks/config.js', 25 | 'tasks/cordova.js', 26 | 'tasks/deploy.js', 27 | 'tasks/build.js', 28 | 'tasks/dev.js', 29 | 'tasks/e2e.js' 30 | ]; 31 | 32 | var alwaysExpectedContent = [ 33 | ['gulpfile.js', /tasks/], 34 | ['app/index.html', /main\.css/], 35 | ['bower.json', /angular/], 36 | ['package.json', /gulp/], 37 | ['app/styles/main.scss', /\/\/ inject:sass/], 38 | ['app/styles/main.scss', /\/\/ endinject/], 39 | ['app/index.html', //], 40 | ['app/index.html', //], 41 | ['app/index.html', //], 42 | ['app/index.html', //] 43 | ]; 44 | 45 | 46 | it('can be required without throwing', function() { 47 | this.app = require('../app'); 48 | }); 49 | 50 | describe('basic file creation', function() { 51 | 52 | var expectedContent = alwaysExpectedContent 53 | .slice() 54 | .concat([]); 55 | 56 | var expected = alwaysExpected 57 | .slice() 58 | .concat([]); 59 | 60 | var options = { 61 | 'skip-install-message': true, 62 | 'skip-install': true, 63 | 'skip-welcome-message': true, 64 | 'skip-message': true 65 | }; 66 | 67 | var runGen; 68 | 69 | beforeEach(function() { 70 | runGen = helpers 71 | .run(path.join(__dirname, '../app')) 72 | .inDir(path.join(__dirname, '.tmp')) 73 | }); 74 | 75 | it('creates expected files', function(done) { 76 | runGen.withOptions(options) 77 | .on('end', function() { 78 | assert.file(expected); 79 | assert.noFile([ 80 | 'app/styles/main.css' 81 | ]); 82 | assert.fileContent(expectedContent); 83 | done(); 84 | }); 85 | }); 86 | }); 87 | 88 | 89 | describe('module file creation and app.js injection', function() { 90 | 91 | var expectedContent = alwaysExpectedContent 92 | .slice() 93 | .concat([ 94 | // cfg 95 | ['.yo-rc.json', /"uiRouter": true/], 96 | 97 | // module injection 98 | ['app/scripts/_app.js', /ngAnimate/], 99 | ['app/scripts/_app.js', /ngAria/], 100 | ['app/scripts/_app.js', /ngCookies/], 101 | ['app/scripts/_app.js', /ngMessages/], 102 | ['app/scripts/_app.js', /ngResource/], 103 | ['app/scripts/_app.js', /ngRoute/], 104 | ['app/scripts/_app.js', /ngSanitize/], 105 | ['app/scripts/_app.js', /ngTouch/], 106 | ['app/scripts/_app.js', /ui.router/], 107 | ['app/scripts/_app.js', /ngMaterial/], 108 | ['app/scripts/_app.js', /ngFabForm/], 109 | 110 | ['bower.json', /angular-animate/], 111 | ['bower.json', /angular-aria/], 112 | ['bower.json', /angular-cookies/], 113 | ['bower.json', /angular-messages/], 114 | ['bower.json', /angular-resource/], 115 | ['bower.json', /angular-route/], 116 | ['bower.json', /angular-sanitize/], 117 | ['bower.json', /angular-touch/], 118 | ['bower.json', /ui-router/], 119 | ['bower.json', /angular-material/], 120 | ['bower.json', /ng-fab-form/] 121 | ]); 122 | 123 | var expected = alwaysExpected 124 | .slice() 125 | .concat([]); 126 | 127 | var options = { 128 | 'skip-install-message': true, 129 | 'skip-install': true, 130 | 'skip-welcome-message': true, 131 | 'skip-message': true 132 | }; 133 | 134 | var runGen; 135 | 136 | beforeEach(function() { 137 | runGen = helpers 138 | .run(path.join(__dirname, '../app')) 139 | .inDir(path.join(__dirname, '.tmp')) 140 | }); 141 | 142 | it('creates expected files', function(done) { 143 | runGen 144 | .withOptions(options) 145 | .withPrompts({ 146 | modules: [ 147 | 'animateModule', 148 | 'ariaModule', 149 | 'cookiesModule', 150 | 'messagesModule', 151 | 'resourceModule', 152 | 'routeModule', 153 | 'uiRouterModule', 154 | 'ngFabFormModule', 155 | 'sanitizeModule', 156 | 'ngMaterialModule', 157 | 'touchModule' 158 | ] 159 | }) 160 | .on('end', function() { 161 | assert.file([].concat( 162 | expected 163 | )); 164 | assert.noFile([ 165 | 'app/styles/main.css' 166 | ]); 167 | assert.fileContent(expectedContent); 168 | done(); 169 | }); 170 | }); 171 | }); 172 | 173 | 174 | describe('route files with ui router', function() { 175 | 176 | var expectedContent = alwaysExpectedContent 177 | .slice() 178 | .concat([ 179 | // module injection 180 | ['app/scripts/_app.js', /ui.router/], 181 | ['bower.json', /ui-router/], 182 | ['.yo-rc.json', /"uiRouter": true/], 183 | ['app/scripts/routes.js', '/* STATES-NEEDLE - DO NOT REMOVE THIS */'] 184 | ]); 185 | 186 | var expected = alwaysExpected 187 | .slice() 188 | .concat([ 189 | 'app/scripts/routes.js', 190 | 'app/scripts/routes.spec.js' 191 | ]); 192 | 193 | var options = { 194 | 'skip-install-message': true, 195 | 'skip-install': true, 196 | 'skip-welcome-message': true, 197 | 'skip-message': true 198 | }; 199 | 200 | var runGen; 201 | 202 | beforeEach(function() { 203 | runGen = helpers 204 | .run(path.join(__dirname, '../app')) 205 | .inDir(path.join(__dirname, '.tmp')); 206 | }); 207 | 208 | it('creates expected files', function(done) { 209 | runGen 210 | .withOptions(options) 211 | .withPrompts({ 212 | modules: [ 213 | 'uiRouterModule' 214 | ] 215 | }) 216 | .on('end', function() { 217 | assert.file([].concat( 218 | expected 219 | )); 220 | assert.noFile([ 221 | 'app/styles/main.css' 222 | ]); 223 | assert.fileContent(expectedContent); 224 | done(); 225 | }); 226 | }); 227 | }); 228 | }); 229 | 230 | 231 | -------------------------------------------------------------------------------- /test/component.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var path = require('path'); 3 | var helpers = require('yeoman-test'); 4 | var assert = require('yeoman-assert'); 5 | 6 | describe('moda Component generator', function() { 7 | var SUB_GEN_PATH = '../cp'; 8 | 9 | // not testing the actual run of generators yet 10 | it('can be required without throwing', function() { 11 | this.app = require(SUB_GEN_PATH); 12 | }); 13 | 14 | describe('basic file creation', function() { 15 | var testArguments = 'test-name'; 16 | var expectedContent = [ 17 | ['app/scripts/test-name/test-name-cp.js', /testName/], 18 | ['app/scripts/test-name/test-name-cp.js', /module\('tmp'\)/], 19 | ['app/scripts/test-name/test-name-cp.js', /scripts\/test-name\/test-name-cp\.html/], 20 | ['app/scripts/test-name/test-name-cp.spec.js', /\('<\/test-name>'\)/], 21 | ['app/scripts/test-name/test-name-cp.html', /testName/], 22 | ]; 23 | var expected = [ 24 | 'app/scripts/test-name/test-name-cp.js', 25 | 'app/scripts/test-name/test-name-cp.spec.js', 26 | 'app/scripts/test-name/test-name-cp.html', 27 | 'app/scripts/test-name/_test-name-cp.scss' 28 | ]; 29 | 30 | var noFile = [ 31 | 'app/scripts/test-name/test-name-s.js', 32 | 'app/scripts/test-name/test-name-f.js', 33 | 'app/scripts/test-name-cp.js' 34 | ]; 35 | 36 | var nonExpected = [ 37 | ['app/scripts/test-name/test-name-cp.js', /testNamea/] 38 | ]; 39 | 40 | var options = { 41 | 'useDefaults': true, 42 | 'skipInject': true 43 | }; 44 | 45 | var runGen; 46 | 47 | beforeEach(function() { 48 | runGen = helpers 49 | .run(path.join(__dirname, SUB_GEN_PATH)) 50 | .inDir(path.join(__dirname, '.tmp')) 51 | }); 52 | 53 | it('creates expected files', function(done) { 54 | runGen 55 | .withArguments(testArguments) 56 | .withOptions(options) 57 | .on('end', function() { 58 | assert.file([].concat( 59 | expected 60 | )); 61 | assert.noFile([].concat( 62 | noFile 63 | )); 64 | assert.fileContent([].concat( 65 | expectedContent 66 | )); 67 | assert.noFileContent([].concat( 68 | nonExpected 69 | )); 70 | done(); 71 | }); 72 | }); 73 | }); 74 | 75 | 76 | describe('file in sub folder creation', function() { 77 | var testArguments = 'test-name test-path'; 78 | var expectedContent = [ 79 | ['app/scripts/test-path/test-name/test-name-cp.js', /testName/], 80 | ['app/scripts/test-path/test-name/test-name-cp.js', /module\('tmp'\)/], 81 | ['app/scripts/test-path/test-name/test-name-cp.js', /scripts\/test-path\/test-name\/test-name-cp\.html/], 82 | ['app/scripts/test-path/test-name/test-name-cp.spec.js', /\('<\/test-name>'\)/], 83 | ['app/scripts/test-path/test-name/test-name-cp.html', /testName/], 84 | ]; 85 | var expected = [ 86 | 'app/scripts/test-path/test-name/test-name-cp.js', 87 | 'app/scripts/test-path/test-name/test-name-cp.spec.js', 88 | 'app/scripts/test-path/test-name/test-name-cp.html', 89 | 'app/scripts/test-path/test-name/_test-name-cp.scss' 90 | ]; 91 | 92 | var noFile = [ 93 | 'app/scripts/test-path/test-name/test-name-s.js', 94 | 'app/scripts/test-path/test-name/test-name-f.js', 95 | 'app/scripts/test-name-cp.js' 96 | ]; 97 | 98 | var nonExpected = [ 99 | ['app/scripts/test-path/test-name/test-name-cp.js', /testNamea/] 100 | ]; 101 | 102 | var options = { 103 | 'useDefaults': true, 104 | 'skipInject': true 105 | }; 106 | 107 | var runGen; 108 | 109 | beforeEach(function() { 110 | runGen = helpers 111 | .run(path.join(__dirname, SUB_GEN_PATH)) 112 | .inDir(path.join(__dirname, '.tmp')) 113 | }); 114 | 115 | it('creates expected files', function(done) { 116 | runGen 117 | .withArguments(testArguments) 118 | .withOptions(options) 119 | .on('end', function() { 120 | assert.file([].concat( 121 | expected 122 | )); 123 | assert.noFile([].concat( 124 | noFile 125 | )); 126 | assert.fileContent([].concat( 127 | expectedContent 128 | )); 129 | assert.noFileContent([].concat( 130 | nonExpected 131 | )); 132 | done(); 133 | }); 134 | }); 135 | }); 136 | 137 | 138 | describe('file with service creation and no template (in sub folder)', function() { 139 | var testArguments = 'test-name test-path'; 140 | var expectedContent = [ 141 | ['app/scripts/test-path/test-name/test-name-cp.js', /testName/], 142 | ['app/scripts/test-path/test-name/test-name-cp.js', /module\('tmp'\)/], 143 | ['app/scripts/test-path/test-name/test-name-s.js', /module\('tmp'\)/], 144 | ['app/scripts/test-path/test-name/test-name-s.js', /TestName/], 145 | ['app/scripts/test-path/test-name/test-name-s.spec.js', /TestName/], 146 | ['app/scripts/test-path/test-name/test-name-cp.spec.js', /\('<\/test-name>'\)/], 147 | ]; 148 | var expected = [ 149 | 'app/scripts/test-path/test-name/test-name-cp.js', 150 | 'app/scripts/test-path/test-name/test-name-cp.spec.js', 151 | 'app/scripts/test-path/test-name/test-name-s.js', 152 | 'app/scripts/test-path/test-name/test-name-s.spec.js' 153 | ]; 154 | 155 | var noFile = [ 156 | 'app/scripts/test-path/test-name/test-name-f.js', 157 | 'app/scripts/test-path/test-name/test-name-f.spec.js', 158 | 'app/scripts/test-name-cp.js', 159 | 'app/scripts/test-path/test-name/test-name-cp.html', 160 | 'app/scripts/test-path/test-name/_test-name-cp.scss' 161 | ]; 162 | 163 | var nonExpected = [ 164 | ['app/scripts/test-path/test-name/test-name-cp.js', /templateUrl/] 165 | ]; 166 | 167 | var options = { 168 | 'skipInject': true 169 | }; 170 | 171 | var runGen; 172 | 173 | beforeEach(function() { 174 | runGen = helpers 175 | .run(path.join(__dirname, SUB_GEN_PATH)) 176 | .inDir(path.join(__dirname, '.tmp')) 177 | 178 | }); 179 | 180 | it('creates expected files', function(done) { 181 | runGen 182 | .withArguments(testArguments) 183 | .withPrompts({ 184 | createService: 'service', 185 | createTemplate: false 186 | }) 187 | .withOptions(options) 188 | .on('end', function() { 189 | assert.file([].concat( 190 | expected 191 | )); 192 | assert.noFile([].concat( 193 | noFile 194 | )); 195 | assert.fileContent([].concat( 196 | expectedContent 197 | )); 198 | assert.noFileContent([].concat( 199 | nonExpected 200 | )); 201 | done(); 202 | }); 203 | }); 204 | }); 205 | }); -------------------------------------------------------------------------------- /test/controller.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var path = require('path'); 3 | var helpers = require('yeoman-test'); 4 | var assert = require('yeoman-assert'); 5 | 6 | describe('moda Controller generator', function() { 7 | var generatorPath = '../c'; 8 | // not testing the actual run of generators yet 9 | it('can be required without throwing', function() { 10 | this.app = require(generatorPath); 11 | }); 12 | 13 | describe('basic file creation', function() { 14 | var testArguments = 'test-name'; 15 | var expectedContent = [ 16 | ['app/scripts/test-name/test-name-c.js', /TestNameCtrl/], 17 | ['app/scripts/test-name/test-name-c.js', /module\('tmp'\)/], 18 | ['app/scripts/test-name/test-name-c.spec.js', /TestNameCtrl/], 19 | ['app/scripts/test-name/test-name-c.html', /class="page-test-name"/], 20 | ]; 21 | var expected = [ 22 | 'app/scripts/test-name/test-name-c.js', 23 | 'app/scripts/test-name/test-name-c.spec.js', 24 | 'app/scripts/test-name/test-name-c.html', 25 | 'app/scripts/test-name/_test-name-c.scss' 26 | ]; 27 | 28 | var noFile = [ 29 | 'app/scripts/test-name/test-name-s.js', 30 | 'app/scripts/test-name/test-name-f.js', 31 | 'app/scripts/test-name-c.js' 32 | ]; 33 | 34 | var nonExpected = [ 35 | ['app/scripts/test-name/test-name-c.js', /TestNamea/], 36 | ['app/scripts/test-name/test-name-c.js', /testName/], 37 | ]; 38 | 39 | var options = { 40 | 'useDefaults': true, 41 | 'skipInject': true 42 | }; 43 | 44 | var runGen; 45 | 46 | beforeEach(function() { 47 | runGen = helpers 48 | .run(path.join(__dirname, generatorPath)) 49 | .inDir(path.join(__dirname, '.tmp')) 50 | }); 51 | 52 | it('creates expected files', function(done) { 53 | runGen 54 | .withArguments(testArguments) 55 | .withOptions(options) 56 | .on('end', function() { 57 | assert.file([].concat( 58 | expected 59 | )); 60 | assert.noFile([].concat( 61 | noFile 62 | )); 63 | assert.fileContent([].concat( 64 | expectedContent 65 | )); 66 | assert.noFileContent([].concat( 67 | nonExpected 68 | )); 69 | done(); 70 | }); 71 | }); 72 | }); 73 | 74 | 75 | describe('files in sub folder creation', function() { 76 | var testArguments = 'test-name test-path'; 77 | var expectedContent = [ 78 | ['app/scripts/test-path/test-name/test-name-c.js', /TestNameCtrl/], 79 | ['app/scripts/test-path/test-name/test-name-c.js', /module\('tmp'\)/], 80 | ['app/scripts/test-path/test-name/test-name-c.spec.js', /TestNameCtrl/], 81 | ['app/scripts/test-path/test-name/test-name-c.html', /class="page-test-name"/], 82 | ]; 83 | var expected = [ 84 | 'app/scripts/test-path/test-name/test-name-c.js', 85 | 'app/scripts/test-path/test-name/test-name-c.spec.js', 86 | 'app/scripts/test-path/test-name/test-name-c.html', 87 | 'app/scripts/test-path/test-name/_test-name-c.scss' 88 | ]; 89 | 90 | var noFile = [ 91 | 'app/scripts/test-path/test-name/test-name-s.js', 92 | 'app/scripts/test-path/test-name/test-name-f.js', 93 | 'app/scripts/test-name-c.js' 94 | ]; 95 | 96 | var nonExpected = [ 97 | ['app/scripts/test-path/test-name/test-name-c.js', /testName/] 98 | ]; 99 | 100 | var options = { 101 | 'useDefaults': true, 102 | 'skipInject': true 103 | }; 104 | 105 | var runGen; 106 | 107 | beforeEach(function() { 108 | runGen = helpers 109 | .run(path.join(__dirname, generatorPath)) 110 | .inDir(path.join(__dirname, '.tmp')) 111 | }); 112 | 113 | it('creates expected files', function(done) { 114 | runGen 115 | .withArguments(testArguments) 116 | .withOptions(options) 117 | .on('end', function() { 118 | assert.file([].concat( 119 | expected 120 | )); 121 | assert.noFile([].concat( 122 | noFile 123 | )); 124 | assert.fileContent([].concat( 125 | expectedContent 126 | )); 127 | assert.noFileContent([].concat( 128 | nonExpected 129 | )); 130 | done(); 131 | }); 132 | }); 133 | }); 134 | 135 | 136 | describe('file with service creation and no template (in sub folder)', function() { 137 | var testArguments = 'test-name test-path'; 138 | var expectedContent = [ 139 | ['app/scripts/test-path/test-name/test-name-c.js', /TestNameCtrl/], 140 | ['app/scripts/test-path/test-name/test-name-c.js', /module\('tmp'\)/], 141 | ['app/scripts/test-path/test-name/test-name-s.js', /module\('tmp'\)/], 142 | ['app/scripts/test-path/test-name/test-name-s.js', /TestName/], 143 | ['app/scripts/test-path/test-name/test-name-s.spec.js', /TestName/] 144 | ]; 145 | var expected = [ 146 | 'app/scripts/test-path/test-name/test-name-c.js', 147 | 'app/scripts/test-path/test-name/test-name-c.spec.js', 148 | 'app/scripts/test-path/test-name/test-name-s.js', 149 | 'app/scripts/test-path/test-name/test-name-s.spec.js' 150 | ]; 151 | 152 | var noFile = [ 153 | 'app/scripts/test-path/test-name/test-name-f.js', 154 | 'app/scripts/test-path/test-name/test-name-f.spec.js', 155 | 'app/scripts/test-name-c.js', 156 | 'app/scripts/test-path/test-name/test-name-c.html', 157 | 'app/scripts/test-path/test-name/_test-name-c.scss' 158 | ]; 159 | 160 | var nonExpected = []; 161 | 162 | var options = { 163 | 'skipInject': true 164 | }; 165 | 166 | var runGen; 167 | 168 | beforeEach(function() { 169 | runGen = helpers 170 | .run(path.join(__dirname, generatorPath)) 171 | .inDir(path.join(__dirname, '.tmp')) 172 | 173 | }); 174 | 175 | it('creates expected files', function(done) { 176 | runGen 177 | .withArguments(testArguments) 178 | .withPrompts({ 179 | createService: 'service', 180 | createTemplate: false 181 | }) 182 | .withOptions(options) 183 | .on('end', function() { 184 | assert.file([].concat( 185 | expected 186 | )); 187 | assert.noFile([].concat( 188 | noFile 189 | )); 190 | assert.fileContent([].concat( 191 | expectedContent 192 | )); 193 | assert.noFileContent([].concat( 194 | nonExpected 195 | )); 196 | done(); 197 | }); 198 | }); 199 | }); 200 | }); -------------------------------------------------------------------------------- /test/custom-templates-from-file.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var path = require('path'); 3 | var helpers = require('yeoman-test'); 4 | var assert = require('yeoman-assert'); 5 | var fs = require('fs'); 6 | describe('moda custom file templates from folder', function() { 7 | var generatorPath = '../s'; 8 | var yoRc = path.join(__dirname, '.tmp', '.yo-rc.json'); 9 | var templatePath = path.join(__dirname, '.tmp-templates'); 10 | var serviceFile = path.join(templatePath, 'service.js'); 11 | var serviceFileContent = 'SERVICE<%= classedName %><%= nameSuffix %>'; 12 | var serviceSpecFile = path.join(templatePath, 'service.spec.js'); 13 | var serviceSpecFileContent = 'SPEC<%= classedName %><%= nameSuffix %>'; 14 | 15 | 16 | var testArguments = 'test-name'; 17 | var expectedContent = [ 18 | ['app/scripts/main/global-services/test-name-s.js', /SERVICE/], 19 | ['app/scripts/main/global-services/test-name-s.spec.js', /SPEC/], 20 | ['app/scripts/main/global-services/test-name-s.js', /TestName/], 21 | ['app/scripts/main/global-services/test-name-s.spec.js', /TestName/] 22 | ]; 23 | var expected = [ 24 | 'app/scripts/main/global-services/test-name-s.js', 25 | 'app/scripts/main/global-services/test-name-s.spec.js' 26 | ]; 27 | 28 | var options = { 29 | 'useDefaults': true, 30 | 'skipInject': true 31 | }; 32 | 33 | var runGen; 34 | 35 | describe('success', function() { 36 | beforeEach(function() { 37 | if (!fs.existsSync(templatePath)) { 38 | fs.mkdirSync(templatePath); 39 | } 40 | if (!fs.existsSync(serviceFile)) { 41 | fs.writeFileSync(serviceFile, serviceFileContent); 42 | } 43 | if (!fs.existsSync(serviceSpecFile)) { 44 | fs.writeFileSync(serviceSpecFile, serviceSpecFileContent); 45 | } 46 | runGen = helpers 47 | .run(path.join(__dirname, generatorPath)) 48 | .inDir(path.join(__dirname, '.tmp')) 49 | }); 50 | 51 | afterEach(function() { 52 | fs.unlinkSync(yoRc); 53 | fs.unlinkSync(serviceFile); 54 | fs.unlinkSync(serviceSpecFile); 55 | fs.rmdir(templatePath); 56 | }); 57 | 58 | it('should use the custom service templates', function(done) { 59 | runGen 60 | .withArguments(testArguments) 61 | .withLocalConfig({ 62 | customTemplatesPath: templatePath 63 | }) 64 | .withOptions(options) 65 | .on('end', function() { 66 | assert.file([].concat( 67 | expected 68 | )); 69 | assert.fileContent([].concat( 70 | expectedContent 71 | )); 72 | 73 | done(); 74 | }); 75 | }); 76 | }); 77 | 78 | }); -------------------------------------------------------------------------------- /test/custom-templates-in-yo-rc.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var path = require('path'); 3 | var helpers = require('yeoman-test'); 4 | var assert = require('yeoman-assert'); 5 | var fs = require('fs'); 6 | describe('moda custom file templates via .yo-rc.json', function() { 7 | var generatorPath = '../d'; 8 | 9 | var testArguments = 'test-name'; 10 | var expectedContent = [ 11 | ['app/scripts/test-name/test-name-d.js', /testName/], 12 | ['app/scripts/test-name/test-name-d.js', /module\('tmp'\)/], 13 | ['app/scripts/test-name/test-name-d.js', /scripts\/test-name\/test-name-d\.html/], 14 | ['app/scripts/test-name/test-name-d.spec.js', /\('<\/test-name>'\)/], 15 | ['app/scripts/test-name/test-name-d.html', /class="XXXXXX"/] 16 | ]; 17 | var expected = [ 18 | 'app/scripts/test-name/test-name-d.js', 19 | 'app/scripts/test-name/test-name-d.spec.js', 20 | 'app/scripts/test-name/test-name-d.html', 21 | 'app/scripts/test-name/_test-name-d.scss' 22 | ]; 23 | 24 | 25 | var options = { 26 | 'useDefaults': true, 27 | 'skipInject': true 28 | }; 29 | 30 | var runGen; 31 | 32 | beforeEach(function() { 33 | runGen = helpers 34 | .run(path.join(__dirname, generatorPath)) 35 | .inDir(path.join(__dirname, '.tmp')) 36 | }); 37 | 38 | afterEach(function() { 39 | fs.unlinkSync(path.join(__dirname, '.tmp', '.yo-rc.json')); 40 | }); 41 | 42 | it('works for html templates', function(done) { 43 | runGen 44 | .withArguments(testArguments) 45 | .withLocalConfig({ 46 | subGenerators: { 47 | directive: { 48 | tpl: { 49 | tpl: '
' 50 | } 51 | } 52 | } 53 | }) 54 | .withOptions(options) 55 | .on('end', function() { 56 | assert.file([].concat( 57 | expected 58 | )); 59 | assert.fileContent([].concat( 60 | expectedContent 61 | )); 62 | 63 | done(); 64 | }); 65 | }); 66 | 67 | it('has common variables available', function(done) { 68 | runGen 69 | .withArguments(testArguments) 70 | .withLocalConfig({ 71 | subGenerators: { 72 | directive: { 73 | tpl: { 74 | tpl: '<%=cameledName %>|<%=classedName %>|<%=sluggedName %>|<%=dashedName %>|<%=humanizedName %>' 75 | } 76 | } 77 | } 78 | }) 79 | .withOptions(options) 80 | .on('end', function() { 81 | assert.file([].concat( 82 | expected 83 | )); 84 | assert.fileContent([ 85 | ['app/scripts/test-name/test-name-d.html', 'testName|TestName|test-name|test-name|Test name'] 86 | ]); 87 | done(); 88 | }); 89 | }); 90 | 91 | 92 | it('works with services created from directives', function(done) { 93 | runGen 94 | .withArguments(testArguments) 95 | .withOptions({ 96 | 'skipInject': true 97 | }) 98 | .withPrompts({ 99 | createService: 'service' 100 | }) 101 | .withLocalConfig({ 102 | subGenerators: { 103 | directive: { 104 | tpl: { 105 | tpl: 'HTML', 106 | script: 'JS', 107 | style: 'SCSS', 108 | spec: 'SPEC', 109 | } 110 | }, 111 | service: { 112 | tpl: { 113 | script: 'SERVICE_JS', 114 | spec: 'SERVICE_JS_SPEC' 115 | } 116 | } 117 | } 118 | }) 119 | .on('end', function() { 120 | assert.file([].concat( 121 | expected 122 | )); 123 | assert.fileContent([ 124 | ['app/scripts/test-name/test-name-d.js', 'JS'], 125 | ['app/scripts/test-name/test-name-d.spec.js', 'SPEC'], 126 | ['app/scripts/test-name/test-name-d.html', 'HTML'], 127 | ['app/scripts/test-name/_test-name-d.scss', 'SCSS'], 128 | ['app/scripts/test-name/test-name-s.js', 'SERVICE_JS'], 129 | ['app/scripts/test-name/test-name-s.spec.js', 'SERVICE_JS_SPEC'], 130 | ]); 131 | 132 | done(); 133 | }); 134 | }); 135 | }); 136 | -------------------------------------------------------------------------------- /test/decorator.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var path = require('path'); 3 | var assert = require('assert'); 4 | var helpers = require('yeoman-test'); 5 | var assert = require('yeoman-assert'); 6 | 7 | describe('moda Decorator generator', function() { 8 | var generatorPath = '../decorator'; 9 | // not testing the actual run of generators yet 10 | it('can be required without throwing', function() { 11 | this.app = require(generatorPath); 12 | }); 13 | 14 | describe('basic file creation', function() { 15 | var testArguments = 'test-name'; 16 | var expectedContent = [ 17 | ['app/scripts/main/global-services/test-name-decorator.js', /TestName/], 18 | ['app/scripts/main/global-services/test-name-decorator.js', /module\('tmp'\)/], 19 | ['app/scripts/main/global-services/test-name-decorator.spec.js', /TestName/] 20 | ]; 21 | var expected = [ 22 | 'app/scripts/main/global-services/test-name-decorator.js', 23 | 'app/scripts/main/global-services/test-name-decorator.spec.js' 24 | ]; 25 | 26 | var noFile = [ 27 | 'app/scripts/test-name/test-name-decorator.js', 28 | 'app/scripts/test-name-decorator.js', 29 | 'app/scripts/global-services/test-name-s.js' 30 | ]; 31 | 32 | var nonExpected = [ 33 | ['app/scripts/main/global-services/test-name-decorator.js', /testName/] 34 | ]; 35 | 36 | var options = { 37 | 'skipInject': true 38 | }; 39 | 40 | var runGen; 41 | 42 | beforeEach(function() { 43 | runGen = helpers 44 | .run(path.join(__dirname, generatorPath)) 45 | .inDir(path.join(__dirname, '.tmp')) 46 | }); 47 | 48 | it('creates expected files', function(done) { 49 | runGen 50 | .withArguments(testArguments) 51 | .withOptions(options) 52 | .on('end', function() { 53 | assert.file([].concat( 54 | expected 55 | )); 56 | assert.noFile([].concat( 57 | noFile 58 | )); 59 | assert.fileContent([].concat( 60 | expectedContent 61 | )); 62 | assert.noFileContent([].concat( 63 | nonExpected 64 | )); 65 | done(); 66 | }); 67 | }); 68 | }); 69 | 70 | 71 | describe('file in sub folder creation', function() { 72 | var testArguments = 'test-name test-path'; 73 | var expectedContent = [ 74 | ['app/scripts/test-path/test-name-decorator.js', /TestName/], 75 | ['app/scripts/test-path/test-name-decorator.js', /module\('tmp'\)/], 76 | ['app/scripts/test-path/test-name-decorator.spec.js', /TestName/] 77 | ]; 78 | var expected = [ 79 | 'app/scripts/test-path/test-name-decorator.js', 80 | 'app/scripts/test-path/test-name-decorator.spec.js' 81 | 82 | ]; 83 | var noFile = [ 84 | 'app/scripts/test-path/test-name-s.js', 85 | 'app/scripts/test-name-decorator.js', 86 | 'app/scripts/test-path/test-name-d.html', 87 | 'app/scripts/test-path/_test-name-d.scss' 88 | ]; 89 | 90 | var nonExpected = [ 91 | ['app/scripts/test-path/test-name-decorator.js', /testName/] 92 | ]; 93 | 94 | var options = { 95 | 'skipInject': true 96 | }; 97 | 98 | var runGen; 99 | 100 | beforeEach(function() { 101 | runGen = helpers 102 | .run(path.join(__dirname, generatorPath)) 103 | .inDir(path.join(__dirname, '.tmp')) 104 | }); 105 | 106 | it('creates expected files', function(done) { 107 | runGen 108 | .withArguments(testArguments) 109 | .withOptions(options) 110 | .on('end', function() { 111 | assert.file([].concat( 112 | expected 113 | )); 114 | assert.noFile([].concat( 115 | noFile 116 | )); 117 | assert.fileContent([].concat( 118 | expectedContent 119 | )); 120 | assert.noFileContent([].concat( 121 | nonExpected 122 | )); 123 | done(); 124 | }); 125 | }); 126 | }); 127 | }); -------------------------------------------------------------------------------- /test/directive.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var path = require('path'); 3 | var assert = require('assert'); 4 | var helpers = require('yeoman-test'); 5 | var assert = require('yeoman-assert'); 6 | 7 | describe('moda Directive generator', function() { 8 | // not testing the actual run of generators yet 9 | it('can be required without throwing', function() { 10 | this.app = require('../d'); 11 | }); 12 | 13 | describe('basic file creation', function() { 14 | var testArguments = 'test-name'; 15 | var expectedContent = [ 16 | ['app/scripts/test-name/test-name-d.js', /testName/], 17 | ['app/scripts/test-name/test-name-d.js', /module\('tmp'\)/], 18 | ['app/scripts/test-name/test-name-d.js', /scripts\/test-name\/test-name-d\.html/], 19 | ['app/scripts/test-name/test-name-d.spec.js', /\('<\/test-name>'\)/], 20 | ['app/scripts/test-name/test-name-d.html', /testName/], 21 | ]; 22 | var expected = [ 23 | 'app/scripts/test-name/test-name-d.js', 24 | 'app/scripts/test-name/test-name-d.spec.js', 25 | 'app/scripts/test-name/test-name-d.html', 26 | 'app/scripts/test-name/_test-name-d.scss' 27 | ]; 28 | 29 | var noFile = [ 30 | 'app/scripts/test-name/test-name-s.js', 31 | 'app/scripts/test-name/test-name-f.js', 32 | 'app/scripts/test-name-d.js' 33 | ]; 34 | 35 | var nonExpected = [ 36 | ['app/scripts/test-name/test-name-d.js', /testNamea/] 37 | ]; 38 | 39 | var options = { 40 | 'useDefaults': true, 41 | 'skipInject': true 42 | }; 43 | 44 | var runGen; 45 | 46 | beforeEach(function() { 47 | runGen = helpers 48 | .run(path.join(__dirname, '../d')) 49 | .inDir(path.join(__dirname, '.tmp')) 50 | }); 51 | 52 | it('creates expected files', function(done) { 53 | runGen 54 | .withArguments(testArguments) 55 | .withOptions(options) 56 | .on('end', function() { 57 | assert.file([].concat( 58 | expected 59 | )); 60 | assert.noFile([].concat( 61 | noFile 62 | )); 63 | assert.fileContent([].concat( 64 | expectedContent 65 | )); 66 | assert.noFileContent([].concat( 67 | nonExpected 68 | )); 69 | done(); 70 | }); 71 | }); 72 | }); 73 | 74 | 75 | describe('file in sub folder creation', function() { 76 | var testArguments = 'test-name test-path'; 77 | var expectedContent = [ 78 | ['app/scripts/test-path/test-name/test-name-d.js', /testName/], 79 | ['app/scripts/test-path/test-name/test-name-d.js', /module\('tmp'\)/], 80 | ['app/scripts/test-path/test-name/test-name-d.js', /scripts\/test-path\/test-name\/test-name-d\.html/], 81 | ['app/scripts/test-path/test-name/test-name-d.spec.js', /\('<\/test-name>'\)/], 82 | ['app/scripts/test-path/test-name/test-name-d.html', /testName/], 83 | ]; 84 | var expected = [ 85 | 'app/scripts/test-path/test-name/test-name-d.js', 86 | 'app/scripts/test-path/test-name/test-name-d.spec.js', 87 | 'app/scripts/test-path/test-name/test-name-d.html', 88 | 'app/scripts/test-path/test-name/_test-name-d.scss' 89 | ]; 90 | 91 | var noFile = [ 92 | 'app/scripts/test-path/test-name/test-name-s.js', 93 | 'app/scripts/test-path/test-name/test-name-f.js', 94 | 'app/scripts/test-name-d.js' 95 | ]; 96 | 97 | var nonExpected = [ 98 | ['app/scripts/test-path/test-name/test-name-d.js', /testNamea/] 99 | ]; 100 | 101 | var options = { 102 | 'useDefaults': true, 103 | 'skipInject': true 104 | }; 105 | 106 | var runGen; 107 | 108 | beforeEach(function() { 109 | runGen = helpers 110 | .run(path.join(__dirname, '../d')) 111 | .inDir(path.join(__dirname, '.tmp')) 112 | }); 113 | 114 | it('creates expected files', function(done) { 115 | runGen 116 | .withArguments(testArguments) 117 | .withOptions(options) 118 | .on('end', function() { 119 | assert.file([].concat( 120 | expected 121 | )); 122 | assert.noFile([].concat( 123 | noFile 124 | )); 125 | assert.fileContent([].concat( 126 | expectedContent 127 | )); 128 | assert.noFileContent([].concat( 129 | nonExpected 130 | )); 131 | done(); 132 | }); 133 | }); 134 | }); 135 | 136 | 137 | describe('file with service creation and no template (in sub folder)', function() { 138 | var testArguments = 'test-name test-path'; 139 | var expectedContent = [ 140 | ['app/scripts/test-path/test-name/test-name-d.js', /testName/], 141 | ['app/scripts/test-path/test-name/test-name-d.js', /module\('tmp'\)/], 142 | ['app/scripts/test-path/test-name/test-name-s.js', /module\('tmp'\)/], 143 | ['app/scripts/test-path/test-name/test-name-s.js', /TestName/], 144 | ['app/scripts/test-path/test-name/test-name-s.spec.js', /TestName/], 145 | ['app/scripts/test-path/test-name/test-name-d.spec.js', /\('<\/test-name>'\)/], 146 | ]; 147 | var expected = [ 148 | 'app/scripts/test-path/test-name/test-name-d.js', 149 | 'app/scripts/test-path/test-name/test-name-d.spec.js', 150 | 'app/scripts/test-path/test-name/test-name-s.js', 151 | 'app/scripts/test-path/test-name/test-name-s.spec.js' 152 | ]; 153 | 154 | var noFile = [ 155 | 'app/scripts/test-path/test-name/test-name-f.js', 156 | 'app/scripts/test-path/test-name/test-name-f.spec.js', 157 | 'app/scripts/test-name-d.js', 158 | 'app/scripts/test-path/test-name/test-name-d.html', 159 | 'app/scripts/test-path/test-name/_test-name-d.scss' 160 | ]; 161 | 162 | var nonExpected = [ 163 | ['app/scripts/test-path/test-name/test-name-d.js', /templateUrl/] 164 | ]; 165 | 166 | var options = { 167 | 'skipInject': true 168 | }; 169 | 170 | var runGen; 171 | 172 | beforeEach(function() { 173 | runGen = helpers 174 | .run(path.join(__dirname, '../d')) 175 | .inDir(path.join(__dirname, '.tmp')) 176 | 177 | }); 178 | 179 | it('creates expected files', function(done) { 180 | runGen 181 | .withArguments(testArguments) 182 | .withPrompts({ 183 | createService: 'service', 184 | createTemplate: false 185 | }) 186 | .withOptions(options) 187 | .on('end', function() { 188 | assert.file([].concat( 189 | expected 190 | )); 191 | assert.noFile([].concat( 192 | noFile 193 | )); 194 | assert.fileContent([].concat( 195 | expectedContent 196 | )); 197 | assert.noFileContent([].concat( 198 | nonExpected 199 | )); 200 | done(); 201 | }); 202 | }); 203 | }); 204 | }); -------------------------------------------------------------------------------- /test/factory.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var path = require('path'); 3 | var assert = require('assert'); 4 | var helpers = require('yeoman-test'); 5 | var assert = require('yeoman-assert'); 6 | 7 | describe('moda Factory generator', function() { 8 | var generatorPath = '../f'; 9 | 10 | 11 | // not testing the actual run of generators yet 12 | it('can be required without throwing', function() { 13 | this.app = require(generatorPath); 14 | }); 15 | 16 | describe('basic file creation', function() { 17 | var testArguments = 'test-name'; 18 | var expectedContent = [ 19 | ['app/scripts/main/global-services/test-name-f.js', /TestName/], 20 | ['app/scripts/main/global-services/test-name-f.js', /module\('tmp'\)/], 21 | ['app/scripts/main/global-services/test-name-f.spec.js', /TestName/] 22 | ]; 23 | var expected = [ 24 | 'app/scripts/main/global-services/test-name-f.js', 25 | 'app/scripts/main/global-services/test-name-f.spec.js' 26 | ]; 27 | 28 | var noFile = [ 29 | 'app/scripts/test-name/test-name-f.js', 30 | 'app/scripts/test-name-f.js', 31 | 'app/scripts/global-services/test-name-s.js' 32 | ]; 33 | 34 | var nonExpected = [ 35 | ['app/scripts/main/global-services/test-name-f.js', /testName/] 36 | ]; 37 | 38 | var options = { 39 | 'skipInject': true 40 | }; 41 | 42 | var runGen; 43 | 44 | beforeEach(function() { 45 | runGen = helpers 46 | .run(path.join(__dirname, generatorPath)) 47 | .inDir(path.join(__dirname, '.tmp')) 48 | }); 49 | 50 | it('creates expected files', function(done) { 51 | runGen 52 | .withArguments(testArguments) 53 | .withOptions(options) 54 | .on('end', function() { 55 | assert.file([].concat( 56 | expected 57 | )); 58 | assert.noFile([].concat( 59 | noFile 60 | )); 61 | assert.fileContent([].concat( 62 | expectedContent 63 | )); 64 | assert.noFileContent([].concat( 65 | nonExpected 66 | )); 67 | done(); 68 | }); 69 | }); 70 | }); 71 | 72 | 73 | describe('file in sub folder creation', function() { 74 | var testArguments = 'test-name test-path'; 75 | var expectedContent = [ 76 | ['app/scripts/test-path/test-name-f.js', /TestName/], 77 | ['app/scripts/test-path/test-name-f.js', /module\('tmp'\)/], 78 | ['app/scripts/test-path/test-name-f.spec.js', /TestName/] 79 | ]; 80 | var expected = [ 81 | 'app/scripts/test-path/test-name-f.js', 82 | 'app/scripts/test-path/test-name-f.spec.js' 83 | 84 | ]; 85 | var noFile = [ 86 | 'app/scripts/test-path/test-name-s.js', 87 | 'app/scripts/test-name-f.js', 88 | 'app/scripts/test-path/test-name-d.html', 89 | 'app/scripts/test-path/_test-name-d.scss' 90 | ]; 91 | 92 | var nonExpected = [ 93 | ['app/scripts/test-path/test-name-f.js', /testName/] 94 | ]; 95 | 96 | var options = { 97 | 'skipInject': true 98 | }; 99 | 100 | var runGen; 101 | 102 | beforeEach(function() { 103 | runGen = helpers 104 | .run(path.join(__dirname, generatorPath)) 105 | .inDir(path.join(__dirname, '.tmp')) 106 | }); 107 | 108 | it('creates expected files', function(done) { 109 | runGen 110 | .withArguments(testArguments) 111 | .withOptions(options) 112 | .on('end', function() { 113 | assert.file([].concat( 114 | expected 115 | )); 116 | assert.noFile([].concat( 117 | noFile 118 | )); 119 | assert.fileContent([].concat( 120 | expectedContent 121 | )); 122 | assert.noFileContent([].concat( 123 | nonExpected 124 | )); 125 | done(); 126 | }); 127 | }); 128 | }); 129 | 130 | describe('with local config for file extension, global path and name-suffix', function() { 131 | var testArguments = 'test-name'; 132 | var expectedContent = [ 133 | ['app/scripts/factories/test-name-factory.js', /TestNameFactory/], 134 | ['app/scripts/factories/test-name-factory.js', /module\('tmp'\)/], 135 | ['app/scripts/factories/test-name-factory.spec.js', /TestNameFactory/] 136 | ]; 137 | var expected = [ 138 | 'app/scripts/factories/test-name-factory.js', 139 | 'app/scripts/factories/test-name-factory.spec.js' 140 | 141 | ]; 142 | var noFile = [ 143 | 'app/scripts/main/global-services/test-name-f.js', 144 | 'app/scripts/main/global-services/test-name-factory.js', 145 | 'app/scripts/test-name-factory.js', 146 | 'app/scripts/factories/test-name-d.html', 147 | 'app/scripts/factories/_test-name-d.scss' 148 | ]; 149 | 150 | var nonExpected = [ 151 | ['app/scripts/factories/test-name-factory.js', /testNameFactory/] 152 | ]; 153 | 154 | var options = { 155 | 'skipInject': true 156 | }; 157 | 158 | var runGen; 159 | 160 | beforeEach(function() { 161 | runGen = helpers 162 | .run(path.join(__dirname, generatorPath)) 163 | .inDir(path.join(__dirname, '.tmp')) 164 | }); 165 | 166 | it('creates expected files', function(done) { 167 | runGen 168 | .withLocalConfig({ 169 | subGenerators: { 170 | factory: { 171 | nameSuffix: 'Factory', 172 | suffix: '-factory', 173 | globalDir: 'factories' 174 | } 175 | } 176 | }) 177 | .withArguments(testArguments) 178 | .withOptions(options) 179 | .on('end', function() { 180 | assert.file([].concat( 181 | expected 182 | )); 183 | assert.noFile([].concat( 184 | noFile 185 | )); 186 | assert.fileContent([].concat( 187 | expectedContent 188 | )); 189 | assert.noFileContent([].concat( 190 | nonExpected 191 | )); 192 | done(); 193 | }); 194 | }); 195 | }); 196 | }); -------------------------------------------------------------------------------- /test/filter.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var path = require('path'); 3 | var assert = require('assert'); 4 | var helpers = require('yeoman-test'); 5 | var assert = require('yeoman-assert'); 6 | 7 | describe('moda Filter generator', function() { 8 | var generatorPath = '../filter'; 9 | // not testing the actual run of generators yet 10 | it('can be required without throwing', function() { 11 | this.app = require(generatorPath); 12 | }); 13 | 14 | describe('basic file creation', function() { 15 | var testArguments = 'test-name'; 16 | var expectedContent = [ 17 | ['app/scripts/main/global-filters/test-name-filter.js', /testName/], 18 | ['app/scripts/main/global-filters/test-name-filter.js', /module\('tmp'\)/], 19 | ['app/scripts/main/global-filters/test-name-filter.spec.js', /testName/] 20 | ]; 21 | var expected = [ 22 | 'app/scripts/main/global-filters/test-name-filter.js', 23 | 'app/scripts/main/global-filters/test-name-filter.spec.js' 24 | ]; 25 | 26 | var noFile = [ 27 | 'app/scripts/test-name/test-name-filter.js', 28 | 'app/scripts/test-name-filter.js', 29 | 'app/scripts/global-filters/test-name-s.js' 30 | ]; 31 | 32 | var nonExpected = [ 33 | ['app/scripts/main/global-filters/test-name-filter.js', /TestName/] 34 | ]; 35 | 36 | var options = { 37 | 'skipInject': true 38 | }; 39 | 40 | var runGen; 41 | 42 | beforeEach(function() { 43 | runGen = helpers 44 | .run(path.join(__dirname, generatorPath)) 45 | .inDir(path.join(__dirname, '.tmp')) 46 | }); 47 | 48 | it('creates expected files', function(done) { 49 | runGen 50 | .withArguments(testArguments) 51 | .withOptions(options) 52 | .on('end', function() { 53 | assert.file([].concat( 54 | expected 55 | )); 56 | assert.noFile([].concat( 57 | noFile 58 | )); 59 | assert.fileContent([].concat( 60 | expectedContent 61 | )); 62 | assert.noFileContent([].concat( 63 | nonExpected 64 | )); 65 | done(); 66 | }); 67 | }); 68 | }); 69 | 70 | 71 | describe('file in sub folder creation', function() { 72 | var testArguments = 'test-name test-path'; 73 | var expectedContent = [ 74 | ['app/scripts/test-path/test-name-filter.js', /testName/], 75 | ['app/scripts/test-path/test-name-filter.js', /module\('tmp'\)/], 76 | ['app/scripts/test-path/test-name-filter.spec.js', /testName/] 77 | ]; 78 | var expected = [ 79 | 'app/scripts/test-path/test-name-filter.js', 80 | 'app/scripts/test-path/test-name-filter.spec.js' 81 | 82 | ]; 83 | var noFile = [ 84 | 'app/scripts/test-path/test-name-s.js', 85 | 'app/scripts/test-name-filter.js', 86 | 'app/scripts/test-path/test-name-d.html', 87 | 'app/scripts/test-path/test-name-filter.html', 88 | 'app/scripts/test-path/test-name-filter.scss', 89 | 'app/scripts/test-path/_test-name-d.scss' 90 | ]; 91 | 92 | var nonExpected = [ 93 | ['app/scripts/test-path/test-name-filter.js', /TestName/] 94 | ]; 95 | 96 | var options = { 97 | 'skipInject': true 98 | }; 99 | 100 | var runGen; 101 | 102 | beforeEach(function() { 103 | runGen = helpers 104 | .run(path.join(__dirname, generatorPath)) 105 | .inDir(path.join(__dirname, '.tmp')) 106 | }); 107 | 108 | it('creates expected files', function(done) { 109 | runGen 110 | .withArguments(testArguments) 111 | .withOptions(options) 112 | .on('end', function() { 113 | assert.file([].concat( 114 | expected 115 | )); 116 | assert.noFile([].concat( 117 | noFile 118 | )); 119 | assert.fileContent([].concat( 120 | expectedContent 121 | )); 122 | assert.noFileContent([].concat( 123 | nonExpected 124 | )); 125 | done(); 126 | }); 127 | }); 128 | }); 129 | }); -------------------------------------------------------------------------------- /test/helper.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var path = require('path'); 3 | var assert = require('yeoman-assert'); 4 | var helperScripts = require('../helper.js'); 5 | var fs = require('fs'); 6 | 7 | describe('moda Helper-Scripts', function() { 8 | helperScripts.STATE_NEEDLE = '/* NEEEEEEDLE */'; 9 | 10 | describe('addToFile', function() { 11 | var fn = helperScripts.addToFile; 12 | var code = 'alert("asd");'; 13 | var needle = '/* NEEEEEEDLE */'; 14 | var testFile = path.join(__dirname, '.tmp/test-file.js'); 15 | var testFileContent = needle; 16 | 17 | 18 | beforeEach(function(done) { 19 | fs.writeFile(testFile, testFileContent, function(err) { 20 | if (err) { 21 | return console.log(err); 22 | } 23 | done(); 24 | }); 25 | }); 26 | 27 | afterEach(function(done) { 28 | // remove files 29 | fs.unlink(testFile, function() { 30 | done(); 31 | }); 32 | }); 33 | 34 | it('injects code above a needle', function() { 35 | fn(testFile, code, needle); 36 | assert.fileContent([ 37 | [testFile, 'alert("asd");\n/* NEEEEEEDLE */'] 38 | ]); 39 | 40 | // works multiple times 41 | fn(testFile, code, needle); 42 | assert.fileContent([ 43 | [testFile, 'alert("asd");\nalert("asd");\n/* NEEEEEEDLE */'] 44 | ]); 45 | }); 46 | }); 47 | 48 | describe('injectRoute', function() { 49 | var fn = helperScripts.injectRoute; 50 | var needle = '/* NEEEEEEDLE */'; 51 | var routesFile = path.join(__dirname, '.tmp/test-route.js'); 52 | var routesFileContent = needle; 53 | var url = '/some-url'; 54 | var mockGen = { 55 | log: { 56 | writeln: function() { 57 | 58 | } 59 | } 60 | }; 61 | 62 | beforeEach(function(done) { 63 | // create test routes file 64 | fs.writeFile(routesFile, routesFileContent, function(err) { 65 | if (err) { 66 | return console.log(err); 67 | } 68 | done(); 69 | }); 70 | }); 71 | 72 | afterEach(function(done) { 73 | // remove files 74 | fs.unlink(routesFile, function() { 75 | done(); 76 | }); 77 | }); 78 | 79 | it('injects state above a needle', function() { 80 | fn(routesFile, 'test.name', url, false, false, mockGen); 81 | assert.fileContent([ 82 | [routesFile, /test\.name/], 83 | [routesFile, url], 84 | [routesFile, /test\.name/], 85 | [routesFile, /test\.name/], 86 | [routesFile, /\.state\('test\.name', \{\s*url:\s*'\/some-url'\s*}\)\s*\/\* NEEEEEEDLE \*\//] 87 | ]); 88 | }); 89 | 90 | it('injects the controller and template if given', function() { 91 | fn(routesFile, 'test.name', url, 'some.html', 'SomeCtrl', mockGen); 92 | assert.fileContent([ 93 | [routesFile, /test\.name/], 94 | [routesFile, url], 95 | [routesFile, 'SomeCtrl'], 96 | [routesFile, 'some.html'], 97 | [routesFile, /\.state\('test\.name', \{\s*url:\s*'\/some-url',\s*controller:\s*'SomeCtrl',\s*controllerAs:\s*'vm',\s*templateUrl:\s*'some.html'\s+}\)\s*\/\* NEEEEEEDLE \*\//] 98 | ]); 99 | }); 100 | 101 | it('injects the a template if given', function() { 102 | fn(routesFile, 'test.name', url, 'some.html', false, mockGen); 103 | assert.fileContent([ 104 | [routesFile, /test\.name/], 105 | [routesFile, url], 106 | [routesFile, 'some.html'], 107 | [routesFile, /\.state\('test\.name', \{\s*url:\s*'\/some-url',\s*templateUrl:\s*'some.html'\s+}\)\s*\/\* NEEEEEEDLE \*\//] 108 | ]); 109 | }); 110 | }); 111 | }); -------------------------------------------------------------------------------- /test/provider.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var path = require('path'); 3 | var assert = require('assert'); 4 | var helpers = require('yeoman-test'); 5 | var assert = require('yeoman-assert'); 6 | 7 | describe('moda Provider generator', function() { 8 | var generatorPath = '../p'; 9 | // not testing the actual run of generators yet 10 | it('can be required without throwing', function() { 11 | this.app = require(generatorPath); 12 | }); 13 | 14 | describe('basic file creation', function() { 15 | var testArguments = 'test-name'; 16 | var expectedContent = [ 17 | ['app/scripts/main/global-services/test-name-p.js', /TestName/], 18 | ['app/scripts/main/global-services/test-name-p.js', /module\('tmp'\)/], 19 | ['app/scripts/main/global-services/test-name-p.spec.js', /TestName/] 20 | ]; 21 | var expected = [ 22 | 'app/scripts/main/global-services/test-name-p.js', 23 | 'app/scripts/main/global-services/test-name-p.spec.js' 24 | ]; 25 | 26 | var noFile = [ 27 | 'app/scripts/test-name/test-name-p.js', 28 | 'app/scripts/test-name-p.js', 29 | 'app/scripts/global-services/test-name-s.js' 30 | ]; 31 | 32 | var nonExpected = [ 33 | ['app/scripts/main/global-services/test-name-p.js', /testName/] 34 | ]; 35 | 36 | var options = { 37 | 'skipInject': true 38 | }; 39 | 40 | var runGen; 41 | 42 | beforeEach(function() { 43 | runGen = helpers 44 | .run(path.join(__dirname, generatorPath)) 45 | .inDir(path.join(__dirname, '.tmp')) 46 | }); 47 | 48 | it('creates expected files', function(done) { 49 | runGen 50 | .withArguments(testArguments) 51 | .withOptions(options) 52 | .on('end', function() { 53 | assert.file([].concat( 54 | expected 55 | )); 56 | assert.noFile([].concat( 57 | noFile 58 | )); 59 | assert.fileContent([].concat( 60 | expectedContent 61 | )); 62 | assert.noFileContent([].concat( 63 | nonExpected 64 | )); 65 | done(); 66 | }); 67 | }); 68 | }); 69 | 70 | 71 | describe('file in sub folder creation', function() { 72 | var testArguments = 'test-name test-path'; 73 | var expectedContent = [ 74 | ['app/scripts/test-path/test-name-p.js', /TestName/], 75 | ['app/scripts/test-path/test-name-p.js', /module\('tmp'\)/], 76 | ['app/scripts/test-path/test-name-p.spec.js', /TestName/] 77 | ]; 78 | var expected = [ 79 | 'app/scripts/test-path/test-name-p.js', 80 | 'app/scripts/test-path/test-name-p.spec.js' 81 | 82 | ]; 83 | var noFile = [ 84 | 'app/scripts/test-path/test-name-s.js', 85 | 'app/scripts/test-name-p.js', 86 | 'app/scripts/test-path/test-name-d.html', 87 | 'app/scripts/test-path/test-name-p.html', 88 | 'app/scripts/test-path/test-name-p.scss', 89 | 'app/scripts/test-path/_test-name-d.scss' 90 | ]; 91 | 92 | var nonExpected = [ 93 | ['app/scripts/test-path/test-name-p.js', /testName/] 94 | ]; 95 | 96 | var options = { 97 | 'skipInject': true 98 | }; 99 | 100 | var runGen; 101 | 102 | beforeEach(function() { 103 | runGen = helpers 104 | .run(path.join(__dirname, generatorPath)) 105 | .inDir(path.join(__dirname, '.tmp')) 106 | }); 107 | 108 | it('creates expected files', function(done) { 109 | runGen 110 | .withArguments(testArguments) 111 | .withOptions(options) 112 | .on('end', function() { 113 | assert.file([].concat( 114 | expected 115 | )); 116 | assert.noFile([].concat( 117 | noFile 118 | )); 119 | assert.fileContent([].concat( 120 | expectedContent 121 | )); 122 | assert.noFileContent([].concat( 123 | nonExpected 124 | )); 125 | done(); 126 | }); 127 | }); 128 | }); 129 | }); -------------------------------------------------------------------------------- /test/route.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var path = require('path'); 3 | var helpers = require('yeoman-test'); 4 | var assert = require('yeoman-assert'); 5 | var fs = require('fs'); 6 | 7 | 8 | describe('moda Route generator', function() { 9 | var generatorPath = '../r', 10 | routesDir = 'app/scripts/routes/'; 11 | 12 | 13 | // not testing the actual run of generators yet 14 | it('can be required without throwing', function() { 15 | this.app = require(generatorPath); 16 | }); 17 | 18 | describe('basic file creation', function() { 19 | var testArguments = 'test-name'; 20 | var expectedContent = [ 21 | [routesDir + 'test-name/test-name-c.js', /TestNameCtrl/], 22 | [routesDir + 'test-name/test-name-c.js', /module\('tmp'\)/], 23 | [routesDir + 'test-name/test-name-c.spec.js', /TestNameCtrl/], 24 | [routesDir + 'test-name/test-name-c.html', /class="page-test-name"/], 25 | ]; 26 | var expected = [ 27 | routesDir + 'test-name/test-name-c.js', 28 | routesDir + 'test-name/test-name-c.spec.js', 29 | routesDir + 'test-name/test-name-c.html', 30 | routesDir + 'test-name/_test-name-c.scss' 31 | ]; 32 | 33 | var noFile = [ 34 | routesDir + 'test-name/test-name-s.js', 35 | routesDir + 'test-name/test-name-f.js', 36 | routesDir + 'test-name-c.js' 37 | ]; 38 | 39 | var nonExpected = [ 40 | [routesDir + 'test-name/test-name-c.js', /TestNamea/], 41 | [routesDir + 'test-name/test-name-c.js', /testName/], 42 | ]; 43 | 44 | var options = { 45 | 'useDefaults': true, 46 | 'skipInject': true 47 | }; 48 | 49 | var runGen; 50 | 51 | beforeEach(function() { 52 | runGen = helpers 53 | .run(path.join(__dirname, generatorPath)) 54 | .inDir(path.join(__dirname, '.tmp')); 55 | }); 56 | 57 | it('creates expected files', function(done) { 58 | runGen 59 | .withArguments(testArguments) 60 | .withOptions(options) 61 | .on('end', function() { 62 | assert.file([].concat( 63 | expected 64 | )); 65 | assert.noFile([].concat( 66 | noFile 67 | )); 68 | assert.fileContent([].concat( 69 | expectedContent 70 | )); 71 | assert.noFileContent([].concat( 72 | nonExpected 73 | )); 74 | done(); 75 | }); 76 | }); 77 | }); 78 | 79 | 80 | describe('files in sub folder creation', function() { 81 | var testArguments = 'parState.subState'; 82 | var expectedContent = [ 83 | [routesDir + 'par-state/sub-state/sub-state-c.js', /SubStateCtrl/], 84 | [routesDir + 'par-state/sub-state/sub-state-c.js', /module\('tmp'\)/], 85 | [routesDir + 'par-state/sub-state/sub-state-c.spec.js', /SubStateCtrl/], 86 | [routesDir + 'par-state/sub-state/sub-state-c.html', /class="page-sub-state"/], 87 | ]; 88 | var expected = [ 89 | routesDir + 'par-state/sub-state/sub-state-c.js', 90 | routesDir + 'par-state/sub-state/sub-state-c.spec.js', 91 | routesDir + 'par-state/sub-state/sub-state-c.html', 92 | routesDir + 'par-state/sub-state/_sub-state-c.scss' 93 | ]; 94 | 95 | var noFile = [ 96 | routesDir + 'par-state/sub-state/sub-state-s.js', 97 | routesDir + 'par-state/sub-state/sub-state-f.js', 98 | routesDir + 'sub-state-c.js' 99 | ]; 100 | 101 | var nonExpected = [ 102 | // is classified 103 | [routesDir + 'par-state/sub-state/sub-state-c.js', /subStateCtrl/] 104 | ]; 105 | 106 | var options = { 107 | 'useDefaults': true, 108 | 'skipInject': true 109 | }; 110 | 111 | var runGen; 112 | 113 | beforeEach(function() { 114 | runGen = helpers 115 | .run(path.join(__dirname, generatorPath)) 116 | .inDir(path.join(__dirname, '.tmp')); 117 | }); 118 | 119 | it('creates expected files', function(done) { 120 | runGen 121 | .withArguments(testArguments) 122 | .withOptions(options) 123 | .on('end', function() { 124 | assert.file([].concat( 125 | expected 126 | )); 127 | assert.noFile([].concat( 128 | noFile 129 | )); 130 | assert.fileContent([].concat( 131 | expectedContent 132 | )); 133 | assert.noFileContent([].concat( 134 | nonExpected 135 | )); 136 | done(); 137 | }); 138 | }); 139 | }); 140 | 141 | 142 | describe('files with service creation and no template (in sub folder)', function() { 143 | var testArguments = 'parState.subState'; 144 | var expectedContent = [ 145 | [routesDir + 'par-state/sub-state/sub-state-c.js', /SubStateCtrl/], 146 | [routesDir + 'par-state/sub-state/sub-state-c.js', /module\('tmp'\)/], 147 | [routesDir + 'par-state/sub-state/sub-state-s.js', /module\('tmp'\)/], 148 | [routesDir + 'par-state/sub-state/sub-state-s.js', /SubState/], 149 | [routesDir + 'par-state/sub-state/sub-state-s.spec.js', /SubState/] 150 | ]; 151 | var expected = [ 152 | routesDir + 'par-state/sub-state/sub-state-c.js', 153 | routesDir + 'par-state/sub-state/sub-state-c.spec.js', 154 | routesDir + 'par-state/sub-state/sub-state-s.js', 155 | routesDir + 'par-state/sub-state/sub-state-s.spec.js' 156 | ]; 157 | 158 | var noFile = [ 159 | routesDir + 'par-state/sub-state/sub-state-f.js', 160 | routesDir + 'par-state/sub-state/sub-state-f.spec.js', 161 | routesDir + 'sub-state-c.js', 162 | routesDir + 'par-state/sub-state/sub-state-c.html', 163 | routesDir + 'par-state/sub-state/_sub-state-c.scss' 164 | ]; 165 | 166 | var nonExpected = [ 167 | [routesDir + 'par-state/sub-state/sub-state-s.js', /SubStateCtrl/], 168 | [routesDir + 'par-state/sub-state/sub-state-s.spec.js', /SubStateCtrl/], 169 | ]; 170 | 171 | var options = { 172 | 'skipInject': true 173 | }; 174 | 175 | var runGen; 176 | 177 | beforeEach(function() { 178 | runGen = helpers 179 | .run(path.join(__dirname, generatorPath)) 180 | .inDir(path.join(__dirname, '.tmp')); 181 | }); 182 | 183 | it('creates expected files', function(done) { 184 | runGen 185 | .withArguments(testArguments) 186 | .withPrompts({ 187 | createService: 'service', 188 | createTemplate: false 189 | }) 190 | 191 | .withOptions(options) 192 | .on('end', function() { 193 | assert.file([].concat( 194 | expected 195 | )); 196 | assert.noFile([].concat( 197 | noFile 198 | )); 199 | assert.fileContent([].concat( 200 | expectedContent 201 | )); 202 | assert.noFileContent([].concat( 203 | nonExpected 204 | )); 205 | done(); 206 | }); 207 | }); 208 | }); 209 | 210 | // TODO withLocalConfig is not working yet correctly 211 | describe('the routes directory should be configurable', function() { 212 | 213 | var otherRoutesDir = 'app/scripts/other-routes/'; 214 | var testArguments = 'parState.subState'; 215 | var expectedContent = [ 216 | [otherRoutesDir + 'par-state/sub-state/sub-state-c.js', /SubStateCtrl/], 217 | [otherRoutesDir + 'par-state/sub-state/sub-state-c.js', /module\('tmp'\)/], 218 | [otherRoutesDir + 'par-state/sub-state/sub-state-s.js', /module\('tmp'\)/], 219 | [otherRoutesDir + 'par-state/sub-state/sub-state-s.js', /SubState/], 220 | [otherRoutesDir + 'par-state/sub-state/sub-state-s.spec.js', /SubState/] 221 | ]; 222 | var expected = [ 223 | otherRoutesDir + 'par-state/sub-state/sub-state-c.js', 224 | otherRoutesDir + 'par-state/sub-state/sub-state-c.spec.js', 225 | otherRoutesDir + 'par-state/sub-state/sub-state-s.js', 226 | otherRoutesDir + 'par-state/sub-state/sub-state-s.spec.js' 227 | ]; 228 | 229 | var noFile = [ 230 | otherRoutesDir + 'par-state/sub-state/sub-state-f.js', 231 | otherRoutesDir + 'par-state/sub-state/sub-state-f.spec.js', 232 | otherRoutesDir + 'sub-state-c.js', 233 | otherRoutesDir + 'par-state/sub-state/sub-state-c.html', 234 | otherRoutesDir + 'par-state/sub-state/_sub-state-c.scss' 235 | ]; 236 | 237 | var nonExpected = []; 238 | 239 | var options = { 240 | 'skipInject': true 241 | }; 242 | 243 | var runGen; 244 | 245 | beforeEach(function() { 246 | runGen = helpers 247 | .run(path.join(__dirname, generatorPath)) 248 | .inDir(path.join(__dirname, '.tmp')); 249 | }); 250 | 251 | it('creates expected files', function(done) { 252 | runGen 253 | .withArguments(testArguments) 254 | .withPrompts({ 255 | createService: 'service', 256 | createTemplate: false 257 | }) 258 | .withLocalConfig({ 259 | dirs: {routes: 'other-routes'} 260 | }) 261 | .withOptions(options) 262 | .on('end', function() { 263 | assert.file([].concat( 264 | expected 265 | )); 266 | assert.noFile([].concat( 267 | noFile 268 | )); 269 | assert.fileContent([].concat( 270 | expectedContent 271 | )); 272 | assert.noFileContent([].concat( 273 | nonExpected 274 | )); 275 | done(); 276 | }); 277 | }); 278 | }); 279 | 280 | 281 | describe('route injection with ui-router', function() { 282 | var testArguments = 'parState.subState'; 283 | var routesFile = 'app/scripts/routes.js'; 284 | 285 | var expectedContent = [ 286 | [routesDir + 'par-state/sub-state/sub-state-c.js', /SubStateCtrl/], 287 | [routesDir + 'par-state/sub-state/sub-state-c.js', /module\('tmp'\)/], 288 | [routesFile, /subState/] 289 | ]; 290 | var expected = [ 291 | routesDir + 'par-state/sub-state/sub-state-c.js', 292 | routesDir + 'par-state/sub-state/sub-state-c.spec.js', 293 | routesDir + 'par-state/sub-state/sub-state-c.html', 294 | routesDir + 'par-state/sub-state/_sub-state-c.scss', 295 | routesFile 296 | ]; 297 | 298 | var noFile = [ 299 | routesDir + 'par-state/sub-state/sub-state-f.js', 300 | routesDir + 'par-state/sub-state/sub-state-f.spec.js', 301 | routesDir + 'sub-state-c.js' 302 | ]; 303 | 304 | var nonExpected = []; 305 | 306 | var options = { 307 | 'skipInject': true 308 | }; 309 | 310 | var runGen; 311 | 312 | beforeEach(function() { 313 | runGen = helpers 314 | .run(path.join(__dirname, generatorPath)) 315 | .inDir(path.join(__dirname, '.tmp')); 316 | }); 317 | 318 | it('injects routes into the router.js', function(done) { 319 | runGen 320 | .withArguments(testArguments) 321 | .withLocalConfig({ 322 | uiRouter: true, 323 | routesFile: routesFile, 324 | dirs: {routes: 'routes'} 325 | }) 326 | .withPrompts({ 327 | createTemplate: true, 328 | createCtrl: true 329 | }) 330 | .withOptions(options) 331 | .on('end', function() { 332 | assert.file([].concat( 333 | expected 334 | )); 335 | assert.noFile([].concat( 336 | noFile 337 | )); 338 | assert.fileContent([].concat( 339 | expectedContent 340 | )); 341 | assert.noFileContent([].concat( 342 | nonExpected 343 | )); 344 | done(); 345 | }); 346 | }); 347 | }); 348 | }); -------------------------------------------------------------------------------- /test/service.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var path = require('path'); 3 | var assert = require('assert'); 4 | var helpers = require('yeoman-test'); 5 | var assert = require('yeoman-assert'); 6 | 7 | describe('moda Service generator', function() { 8 | // not testing the actual run of generators yet 9 | it('can be required without throwing', function() { 10 | this.app = require('../s'); 11 | }); 12 | 13 | describe('basic file creation', function() { 14 | var testArguments = 'test-name'; 15 | var expectedContent = [ 16 | ['app/scripts/main/global-services/test-name-s.js', /TestName/], 17 | ['app/scripts/main/global-services/test-name-s.js', /module\('tmp'\)/], 18 | ['app/scripts/main/global-services/test-name-s.spec.js', /TestName/] 19 | ]; 20 | var expected = [ 21 | 'app/scripts/main/global-services/test-name-s.js', 22 | 'app/scripts/main/global-services/test-name-s.spec.js' 23 | ]; 24 | 25 | var noFile = [ 26 | 'app/scripts/test-name/test-name-s.js', 27 | 'app/scripts/test-name-s.js', 28 | 'app/scripts/global-services/test-name-f.js' 29 | ]; 30 | 31 | var nonExpected = [ 32 | ['app/scripts/main/global-services/test-name-s.js', /testName/] 33 | ]; 34 | 35 | var options = { 36 | 'skipInject': true 37 | }; 38 | 39 | var runGen; 40 | 41 | beforeEach(function() { 42 | runGen = helpers 43 | .run(path.join(__dirname, '../s')) 44 | .inDir(path.join(__dirname, '.tmp')) 45 | }); 46 | 47 | it('creates expected files', function(done) { 48 | runGen 49 | .withArguments(testArguments) 50 | .withOptions(options) 51 | .on('end', function() { 52 | assert.file([].concat( 53 | expected 54 | )); 55 | assert.noFile([].concat( 56 | noFile 57 | )); 58 | assert.fileContent([].concat( 59 | expectedContent 60 | )); 61 | assert.noFileContent([].concat( 62 | nonExpected 63 | )); 64 | done(); 65 | }); 66 | }); 67 | }); 68 | 69 | 70 | describe('files in sub folder creation', function() { 71 | var testArguments = 'test-name test-path'; 72 | var expectedContent = [ 73 | ['app/scripts/test-path/test-name-s.js', /TestName/], 74 | ['app/scripts/test-path/test-name-s.js', /module\('tmp'\)/], 75 | ['app/scripts/test-path/test-name-s.spec.js', /TestName/] 76 | ]; 77 | var expected = [ 78 | 'app/scripts/test-path/test-name-s.js', 79 | 'app/scripts/test-path/test-name-s.spec.js' 80 | 81 | ]; 82 | var noFile = [ 83 | 'app/scripts/test-path/test-name-f.js', 84 | 'app/scripts/test-name-s.js', 85 | 'app/scripts/test-path/test-name-d.html', 86 | 'app/scripts/test-path/_test-name-d.scss' 87 | ]; 88 | 89 | var nonExpected = [ 90 | ['app/scripts/test-path/test-name-s.js', /testName/] 91 | ]; 92 | 93 | var options = { 94 | 'skipInject': true 95 | }; 96 | 97 | var runGen; 98 | 99 | beforeEach(function() { 100 | runGen = helpers 101 | .run(path.join(__dirname, '../s')) 102 | .inDir(path.join(__dirname, '.tmp')) 103 | }); 104 | 105 | it('creates expected files', function(done) { 106 | runGen 107 | .withArguments(testArguments) 108 | .withOptions(options) 109 | .on('end', function() { 110 | assert.file([].concat( 111 | expected 112 | )); 113 | assert.noFile([].concat( 114 | noFile 115 | )); 116 | assert.fileContent([].concat( 117 | expectedContent 118 | )); 119 | assert.noFileContent([].concat( 120 | nonExpected 121 | )); 122 | done(); 123 | }); 124 | }); 125 | }); 126 | 127 | describe('with local config for file extension, global path and name-suffix', function() { 128 | var testArguments = 'test-name'; 129 | var expectedContent = [ 130 | ['app/scripts/services/test-name-service.js', /TestNameService/], 131 | ['app/scripts/services/test-name-service.js', /module\('tmp'\)/], 132 | ['app/scripts/services/test-name-service.spec.js', /TestNameService/] 133 | ]; 134 | var expected = [ 135 | 'app/scripts/services/test-name-service.js', 136 | 'app/scripts/services/test-name-service.spec.js' 137 | 138 | ]; 139 | var noFile = [ 140 | 'app/scripts/services/test-name-f.js', 141 | 'app/scripts/test-name-service.js', 142 | 'app/scripts/services/test-name-d.html', 143 | 'app/scripts/services/_test-name-d.scss' 144 | ]; 145 | 146 | var nonExpected = [ 147 | ['app/scripts/services/test-name-service.js', /testNameService/] 148 | ]; 149 | 150 | var options = { 151 | 'skipInject': true 152 | }; 153 | 154 | var runGen; 155 | 156 | beforeEach(function() { 157 | runGen = helpers 158 | .run(path.join(__dirname, '../s')) 159 | .inDir(path.join(__dirname, '.tmp')) 160 | }); 161 | 162 | it('creates expected files', function(done) { 163 | runGen 164 | .withLocalConfig({ 165 | subGenerators: { 166 | service: { 167 | nameSuffix: 'Service', 168 | suffix: '-service', 169 | globalDir: 'services' 170 | } 171 | } 172 | }) 173 | .withArguments(testArguments) 174 | .withOptions(options) 175 | .on('end', function() { 176 | assert.file([].concat( 177 | expected 178 | )); 179 | assert.noFile([].concat( 180 | noFile 181 | )); 182 | assert.fileContent([].concat( 183 | expectedContent 184 | )); 185 | assert.noFileContent([].concat( 186 | nonExpected 187 | )); 188 | done(); 189 | }); 190 | }); 191 | }); 192 | }); --------------------------------------------------------------------------------