├── .gitignore ├── .travis.yml ├── Gruntfile.js ├── LICENSE ├── README.md ├── bower.json ├── dist ├── commangular.js ├── commangular.min.js └── commangular.zip ├── karma.conf.js ├── package.json ├── src ├── commangular-mock │ └── commangular-mock.js └── commangular.js └── test ├── command-aspects ├── after-interception-testing.js ├── afterexecution-interception-testing.js ├── afterthrowing-interception-test.js ├── around-cancelation-test.js ├── around-interception-test.js ├── around-modifying-parameters-test.js ├── around-with-promise-test.js ├── aspect-definition-test.js ├── aspect-execution-test.js ├── before-interception-testing.js ├── multiple-after-execution-test.js ├── multiple-afterthrowing-test.js ├── multiple-around-test.js ├── multiple-around-with-return-test.js ├── multiple-before-cancelation-test.js ├── multiple-before-test.js ├── not-afterthrow-not-onError-on-cancelation-test.js ├── throw-exception-on-afterexecution-interceptor-test.js ├── throw-exception-on-around-interceptor-test.js └── throw-exception-on-before-interceptor-test.js ├── commangular-mock └── test.js ├── domain └── model-service-test.js ├── event-aspects ├── after-event-aspect-test.js ├── before-event-aspect-test.js └── event-aspect-execution-test.js └── groups ├── command-execution-test.js ├── command-flow-test.js ├── command-flow-with-service.js ├── command-injection-test.js ├── command-last-result-test.js ├── command-model-test.js ├── command-parallel-execution-test.js ├── command-sequence-execution-test.js ├── commandgular-provider-test.js ├── context-data-test.js ├── custom-resolver-test.js ├── dispatching-from-scope-test.js ├── flow-to-sequence-test.js ├── flow-with-data-passed.js ├── flow-with-numbers-test.js ├── last-result-from-onresult.js ├── on-error-handler-test.js ├── on-result-handler-test.js ├── passing-data-to-command-test.js ├── preceding-result-injection-test.js ├── promises-resolution-test.js └── resultkey-from-onResult.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | bower_components 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | 5 | before_script: 6 | - export DISPLAY=:99.0 7 | - sh -e /etc/init.d/xvfb start 8 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function(grunt) { 4 | 5 | // Project configuration. 6 | grunt.initConfig({ 7 | pkg: grunt.file.readJSON('package.json'), 8 | meta: { 9 | banner: '/**\n' + 10 | ' * <%= pkg.description %>\n' + 11 | ' * @version v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' + 12 | ' * @link <%= pkg.homepage %>\n' + 13 | ' * @author <%= pkg.author %>\n' + 14 | ' * @license MIT License, http://www.opensource.org/licenses/MIT\n' + 15 | ' */\n' 16 | }, 17 | dirs: { 18 | dest: 'dist' 19 | }, 20 | concat: { 21 | options: { 22 | banner: '<%= meta.banner %>' 23 | }, 24 | dist: { 25 | src: ['src/*.js'], 26 | dest: '<%= dirs.dest %>/<%= pkg.name %>.js' 27 | } 28 | }, 29 | zip: { 30 | '<%= dirs.dest %>/commangular.zip': ['<%= dirs.dest %>/<%= pkg.name %>.js', '<%= dirs.dest %>/<%= pkg.name %>.min.js'] 31 | }, 32 | bower: { 33 | install: { 34 | options: { 35 | targetDir: './bower_components', 36 | install: true, 37 | verbose: false, 38 | cleanTargetDir: false, 39 | cleanBowerDir: false, 40 | bowerOptions: {} 41 | } 42 | } 43 | }, 44 | uglify: { 45 | options: { 46 | banner: '<%= meta.banner %>' 47 | }, 48 | dist: { 49 | src: ['<%= concat.dist.dest %>'], 50 | dest: '<%= dirs.dest %>/<%= pkg.name %>.min.js' 51 | } 52 | }, 53 | jshint: { 54 | files: ['Gruntfile.js', 'src/*.js'], 55 | options: { 56 | curly: false, 57 | browser: true, 58 | eqeqeq: true, 59 | immed: true, 60 | latedef: true, 61 | newcap: true, 62 | noarg: true, 63 | sub: true, 64 | undef: true, 65 | boss: true, 66 | eqnull: true, 67 | expr: true, 68 | node: true, 69 | globals: { 70 | exports: true, 71 | angular: false, 72 | $: false 73 | } 74 | } 75 | }, 76 | karma: { 77 | options: { 78 | configFile: 'karma.conf.js' 79 | }, 80 | build: { 81 | singleRun: true, 82 | autoWatch: false 83 | }, 84 | travis: { 85 | singleRun: true, 86 | browsers: ['Firefox'], 87 | autoWatch: false 88 | }, 89 | dev: { 90 | autoWatch: true 91 | } 92 | }, 93 | 94 | changelog: { 95 | options: { 96 | dest: 'CHANGELOG.md' 97 | } 98 | } 99 | }); 100 | 101 | // Load the plugin that provides the "jshint" task. 102 | grunt.loadNpmTasks('grunt-contrib-jshint'); 103 | 104 | // Load the plugin that provides the "concat" task. 105 | grunt.loadNpmTasks('grunt-contrib-concat'); 106 | 107 | // Load the plugin that provides the "uglify" task. 108 | grunt.loadNpmTasks('grunt-contrib-uglify'); 109 | 110 | grunt.loadNpmTasks('grunt-bower-task'); 111 | 112 | grunt.loadNpmTasks('grunt-karma'); 113 | 114 | grunt.loadNpmTasks('grunt-conventional-changelog'); 115 | 116 | grunt.loadNpmTasks('grunt-zip'); 117 | 118 | 119 | // Default task. 120 | grunt.registerTask('default', ['build']); 121 | 122 | // Build task. 123 | grunt.registerTask('build', ['bower', 'karma:build','concat', 'uglify', 'zip']); 124 | 125 | grunt.registerTask('test', ['karma:build']); 126 | 127 | grunt.registerTask('travis', ['bower','karma:travis']); 128 | 129 | // Provides the "bump" task. 130 | grunt.registerTask('bump', 'Increment version number', function() { 131 | var versionType = grunt.option('type'); 132 | function bumpVersion(version, versionType) { 133 | var type = {patch: 2, minor: 1, major: 0}, 134 | parts = version.split('.'), 135 | idx = type[versionType || 'patch']; 136 | parts[idx] = parseInt(parts[idx], 10) + 1; 137 | while(++idx < parts.length) { parts[idx] = 0; } 138 | return parts.join('.'); 139 | } 140 | var version; 141 | function updateFile(file) { 142 | var json = grunt.file.readJSON(file); 143 | version = json.version = bumpVersion(json.version, versionType || 'patch'); 144 | grunt.file.write(file, JSON.stringify(json, null, ' ')); 145 | } 146 | updateFile('package.json'); 147 | updateFile('bower.json'); 148 | grunt.log.ok('Version bumped to ' + version); 149 | }); 150 | 151 | }; 152 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 yukatan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Commangular 2 | [![Build Status](https://travis-ci.org/yukatan/commangular.svg?branch=master)](https://travis-ci.org/yukatan/commangular) 3 | 4 | Command framework for AngularJS. 5 | 6 | * Website : [http://commangular.tk](http://commangular.org) 7 | * Quick Guide : [http://commangular.org/get-started/](http://commangular.org/get-started) 8 | * Documentation : [http://commangular.org/docs/](http://commangular.org/docs/) 9 | 10 | ## Overview 11 | 12 | Commangular is a concept on top of angularJS that aims at simplifying the creation and organization of operations in a self-contained code units and chain them together with an easy and fluent API.That code units are called 'commands' 13 | 14 | Commands can be easily tested, reused, and developed in isolation. 15 | 16 | It is inspired by [Parsley 3 Framework](https://github.com/spicefactory) and [Jens Halm](https://github.com/jenshalm) command concept. 17 | 18 | 19 | ### Main features : 20 | 21 | * Chaining commands in command groups. 22 | * Command execution in sequence or parallel. 23 | * Nesting commands at any level. 24 | * Dependency injection from angular. 25 | * Preceding result injection. 26 | * Cancelation and pause based on promises 27 | * Command flows with decision points. 28 | * Command aspects (Interception of command execution). 29 | * Custom result resolvers(on the way). 30 | 31 | 32 | ## Installation 33 | 34 | * Using bower : ``` bower install commangular ``` 35 | * Download it and add commangular.js or commangular.min.js to your index.html. 36 | 37 | Remember to add commangular.js after angular.js. Commangular only depends on angularJs, it is not using other libraries. 38 | 39 | 40 | 41 | ## License 42 | 43 | The MIT License 44 | 45 | Copyright (c) 2013 Jesús Barquín Cheda 46 | 47 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 48 | 49 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 50 | 51 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 52 | 53 | [![githalytics.com alpha](https://cruel-carlota.gopagoda.com/4e4c83003a160db1279836eedc98f99a "githalytics.com")](http://githalytics.com/yukatan/commangular) 54 | 55 | [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/yukatan/commangular/trend.png)](https://bitdeli.com/free "Bitdeli Badge") 56 | 57 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "commangular", 3 | "version": "0.9.0", 4 | "main": "./dist/commangular.min.js", 5 | "description": "Command pattern implementation for AngularJS", 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/yukatan/commangular.git" 9 | }, 10 | "dependencies": { 11 | "angular": "*" 12 | }, 13 | "devDependencies": { 14 | "angular-mocks": "*" 15 | }, 16 | "ignore": [ 17 | "node_modules" 18 | ] 19 | } -------------------------------------------------------------------------------- /dist/commangular.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Command pattern implementation for AngularJS 3 | * @version v0.9.0 - 2015-03-15 4 | * @link https://github.com/yukatan/commangular 5 | * @author Jesús Barquín Cheda 6 | * @license MIT License, http://www.opensource.org/licenses/MIT 7 | */ 8 | "use strict"; 9 | 10 | (function(window, angular, undefined) { 11 | 12 | var commangular = window.commangular || (window.commangular = {}); 13 | var commands = {}; 14 | var commandNameString = ""; 15 | var eventNameString = ""; 16 | var aspects = []; 17 | var eventAspects = []; 18 | var descriptors = {}; 19 | var eventInterceptors= {}; 20 | var interceptorExtractor = /\/(.*)\//; 21 | var aspectExtractor = /@([^(]*)\((.*)\)/; 22 | var debugEnabled = false; 23 | 24 | function escapeRegExp(str) { 25 | return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); 26 | } 27 | 28 | commangular.create = function(commandName, commandFunction, commandConfig) { 29 | 30 | commands[commandName] = { 31 | commandFunction: commandFunction, 32 | config: commandConfig, 33 | interceptors:{}, 34 | commandName:commandName 35 | }; 36 | commandNameString = commandNameString.concat("%" + commandName + "%{" + commandName + "}\n"); 37 | } 38 | commangular.command = commangular.create; 39 | 40 | commangular.aspect = function(aspectDescriptor,aspectFunction,order) { 41 | 42 | var result = aspectExtractor.exec(aspectDescriptor); 43 | var poincut = result[1]; 44 | var matcherString = interceptorExtractor.exec(result[2])[1]; 45 | var matcher = new RegExp("^%" + matcherString + "%\{(.*)\}$","mg"); 46 | var aspectOrder = order || (order = 0); 47 | if(!/(\bBefore\b|\bAfterExecution\b|\bAfter\b|\bAfterThrowing\b|\bAround\b)/.test(poincut)) 48 | throw new Error('aspect descriptor ' + aspectDescriptor + ' contains errors'); 49 | aspects.push({poincut:poincut, 50 | matcher:matcher, 51 | aspectFunction:aspectFunction, 52 | order:aspectOrder, 53 | descriptor:aspectDescriptor}); 54 | } 55 | 56 | commangular.eventAspect = function(aspectDescriptor,aspectFunction,order) { 57 | 58 | var result = aspectExtractor.exec(aspectDescriptor); 59 | var poincut = result[1]; 60 | var matcherString = interceptorExtractor.exec(result[2])[1]; 61 | var matcher = new RegExp("^%" + matcherString + "%\{(.*)\}$","mg"); 62 | var aspectOrder = order || (order = 0); 63 | if(!/(\bBefore\b|\bAfter\b|\bAfterThrowing\b)/.test(poincut)) 64 | throw new Error('aspect descriptor ' + aspectDescriptor + ' contains errors'); 65 | eventAspects.push({poincut:poincut, 66 | matcher:matcher, 67 | aspectFunction:aspectFunction, 68 | order:aspectOrder, 69 | descriptor:aspectDescriptor}); 70 | } 71 | 72 | commangular.resolver = function (commandName,resolverFunction) { 73 | 74 | var aspectResolverFunction = ['lastResult','processor','$injector',function(lastResult,processor,$injector) { 75 | return { 76 | execute : function() { 77 | var result = $injector.invoke(resolverFunction,this,{result:lastResult}); 78 | processor.setData('lastResult',result); 79 | if(commands[commandName] && 80 | commands[commandName].config && 81 | commands[commandName].config.resultKey) 82 | processor.setData(commands[commandName].config.resultKey,result); 83 | return result; 84 | } 85 | } 86 | }]; 87 | var aspectDescriptor = "@AfterExecution(/" + escapeRegExp(commandName) + "/)"; 88 | commangular.aspect(aspectDescriptor,aspectResolverFunction,-100); 89 | } 90 | 91 | commangular.reset = function() { 92 | 93 | aspects = eventAspects = []; 94 | commands = eventInterceptors = {}; 95 | commandNameString = eventNameString = ""; 96 | } 97 | 98 | commangular.debug = function(enableDebug){ 99 | 100 | debugEnabled = enableDebug; 101 | } 102 | 103 | 104 | commangular.build = function(){ 105 | 106 | (function processInterceptors(collection,stringList,targets) { 107 | 108 | angular.forEach(collection,function(aspect){ 109 | var result; 110 | while((result = aspect.matcher.exec(stringList)) != null) { 111 | 112 | if(!targets[result[1]].interceptors[aspect.poincut]) 113 | targets[result[1]].interceptors[aspect.poincut] = []; 114 | targets[result[1]].interceptors[aspect.poincut] 115 | .push({func:aspect.aspectFunction,order:aspect.order}); 116 | } 117 | }); 118 | return processInterceptors; 119 | }(aspects,commandNameString,commands)(eventAspects,eventNameString,eventInterceptors)); 120 | 121 | } 122 | 123 | //---------------------------------------------------------------------------------------------------------------------- 124 | 125 | function CommandDescriptor(ctype,command) { 126 | 127 | this.ctype = ctype; 128 | this.command = command; 129 | this.descriptors = []; 130 | } 131 | 132 | CommandDescriptor.prototype.asSequence = function() { 133 | 134 | this.ctype = 'S'; 135 | return this; 136 | }; 137 | 138 | CommandDescriptor.prototype.asParallel = function() { 139 | 140 | this.ctype = 'P'; 141 | return this; 142 | }; 143 | 144 | CommandDescriptor.prototype.asFlow = function() { 145 | 146 | this.ctype = 'F'; 147 | return this; 148 | }; 149 | 150 | CommandDescriptor.prototype.add = function(command) { 151 | 152 | this.descriptors.push((angular.isString(command)) ? new CommandDescriptor('E',commands[command]):command); 153 | return this; 154 | }; 155 | CommandDescriptor.prototype.link = function(expresion, services) { 156 | 157 | this.descriptors.push({expresion:expresion,services:services}); 158 | return this; 159 | }; 160 | CommandDescriptor.prototype.to = function(command) { 161 | 162 | this.descriptors[this.descriptors.length -1].commandDescriptor = (angular.isString(command) ? 163 | new CommandDescriptor('E',commands[command]):command); 164 | return this; 165 | }; 166 | 167 | //---------------------------------------------------------------------------------------------------------------------- 168 | function CommandContext(data,$q,$injector,$parse) { 169 | 170 | this.contextData = data || {}; 171 | this.contextData.commandModel = {}; 172 | this.currentDeferred; 173 | this.currentCommandInstance; 174 | this.canceled = false; 175 | 176 | this.processDescriptor = function(descriptor) { 177 | 178 | switch (descriptor.ctype) { 179 | case 'S': 180 | return this.processSequence(descriptor); 181 | case 'P': 182 | return this.processParallel(descriptor); 183 | case 'E': 184 | return this.processCommand(descriptor); 185 | case 'F': 186 | return this.processFlow(descriptor); 187 | } 188 | } 189 | 190 | this.processSequence = function(descriptor) { 191 | 192 | var defer = $q.defer(); 193 | var index = 0; 194 | var self = this; 195 | (function sequenceChain(){ 196 | self.processDescriptor(descriptor.descriptors[index]).then(function(){ 197 | if(++index === descriptor.descriptors.length){ 198 | defer.resolve(); 199 | return; 200 | } 201 | sequenceChain(); 202 | },function(error){defer.reject(error)}); 203 | }()); 204 | return defer.promise; 205 | } 206 | 207 | this.processParallel = function(descriptor) { 208 | 209 | var self = this; 210 | var defer = $q.defer(); 211 | var index = 0; 212 | angular.forEach(descriptor.descriptors,function(desc){ 213 | self.processDescriptor(desc).then(function(){ 214 | if(++index === descriptor.descriptors.length){ 215 | defer.resolve(); 216 | return; 217 | } 218 | },function(error){defer.reject(error)}); 219 | }); 220 | return defer.promise; 221 | 222 | } 223 | 224 | this.processFlow = function(descriptor) { 225 | 226 | var self = this; 227 | var defer = $q.defer(); 228 | var index = 0; 229 | (function flowChain() { 230 | var locals = {}; 231 | var desc = descriptor.descriptors[index]; 232 | if(desc.services) { 233 | 234 | angular.forEach(desc.services.split(','), function(service, key){ 235 | locals[service] = $injector.get(service); 236 | }); 237 | } 238 | var result = $parse(desc.expresion)(self.contextData,locals); 239 | if(typeof result !== 'boolean') 240 | throw new Error('Result from expresion :' + descriptor.expresion + ' is not boolean'); 241 | if(result){ 242 | self.processDescriptor(desc.commandDescriptor).then(function(){ 243 | if(++index === descriptor.descriptors.length){ 244 | defer.resolve(); 245 | return; 246 | } 247 | flowChain(); 248 | },function(error){defer.reject(error)}); 249 | } 250 | else{ 251 | if(++index === descriptor.descriptors.length){ 252 | defer.resolve(); 253 | return; 254 | } 255 | flowChain(); 256 | } 257 | }()); 258 | return defer.promise; 259 | } 260 | 261 | this.processCommand = function(descriptor) { 262 | 263 | var self = this; 264 | var result; 265 | var deferExecution = $q.defer(); 266 | deferExecution.resolve(); 267 | return deferExecution.promise 268 | .then(function () { 269 | return self.intercept('Before',descriptor.command.interceptors); 270 | }) 271 | .then(function() { 272 | var deferred = $q.defer(); 273 | try{ 274 | if(descriptor.command.interceptors['Around']) 275 | result = self.intercept('Around',descriptor.command.interceptors,descriptor.command.commandFunction); 276 | else { 277 | var command = self.instantiate(descriptor.command.commandFunction,true); 278 | result = self.invoke(command.execute, command); 279 | } 280 | self.processResults(result,descriptor.command.config).then(function(){ 281 | deferred.resolve(); 282 | },function(error){ 283 | deferred.reject(error); 284 | }); 285 | }catch(error){ 286 | deferred.reject(error); 287 | } 288 | return deferred.promise; 289 | }) 290 | .then(function(){ 291 | return self.intercept('AfterExecution',descriptor.command.interceptors); 292 | }) 293 | .then(function(){ 294 | result = self.exeOnResult(self.contextData.lastResult); 295 | return self.processResults(result,descriptor.command.config); 296 | }) 297 | .then(function(){ 298 | return self.intercept('After',descriptor.command.interceptors); 299 | },function(error) { 300 | var deferred = $q.defer(); 301 | if(self.canceled){ 302 | deferred.reject(error); 303 | return deferred.promise; 304 | } 305 | self.exeOnError(error); 306 | self.getContextData().lastError = error; 307 | self.intercept('AfterThrowing',descriptor.command.interceptors).then(function(){ 308 | deferred.reject(error) 309 | },function(){deferred.reject(error)}); 310 | return deferred.promise; 311 | }); 312 | } 313 | 314 | this.intercept = function(poincut,interceptors,command) { 315 | 316 | var self = this; 317 | var deferred = $q.defer(); 318 | if(!interceptors[poincut]){ 319 | deferred.resolve(); 320 | return deferred.promise; 321 | } 322 | interceptors[poincut].sort(function(a,b){ 323 | return b.order - a.order; 324 | }) 325 | switch(poincut) { 326 | case 'Around' : { 327 | var processor = new AroundProcessor(command,null,self,deferred,$q); 328 | angular.forEach(interceptors[poincut],function(value){ 329 | processor = new AroundProcessor(value.func,processor,self,deferred,$q); 330 | }); 331 | $q.when(processor.invoke()).then(function(result){ 332 | deferred.resolve(result); 333 | },function(error){ 334 | deferred.reject(error);}); 335 | break; 336 | } 337 | default : { 338 | var processor = this.contextData.processor = new InterceptorProcessor(self,deferred); 339 | interceptors[poincut].reverse(); 340 | var x = 0; 341 | (function invocationChain(){ 342 | try{ 343 | if(x === interceptors[poincut].length || self.canceled){ 344 | deferred.resolve(); 345 | return; 346 | } 347 | var interceptor = self.instantiate(interceptors[poincut][x++].func,false); 348 | $q.when(self.invoke(interceptor.execute,interceptor)).then(function(){ 349 | invocationChain(); 350 | },function(error){}); 351 | }catch(error){deferred.reject(error)}; 352 | }()); 353 | break; 354 | } 355 | } 356 | return deferred.promise; 357 | } 358 | 359 | 360 | this.instantiate = function(funct,isCommand) { 361 | 362 | var instance = $injector.instantiate(funct,this.contextData); 363 | if(isCommand) this.currentCommandInstance = instance; 364 | return instance; 365 | } 366 | 367 | this.exeOnResult = function(result) { 368 | 369 | if(this.currentCommandInstance && this.currentCommandInstance.hasOwnProperty('onResult')) 370 | return this.currentCommandInstance.onResult(result); 371 | } 372 | 373 | this.exeOnError = function(error) { 374 | 375 | if(this.currentCommandInstance && this.currentCommandInstance.hasOwnProperty('onError')) 376 | this.currentCommandInstance.onError(error); 377 | } 378 | 379 | this.processResults = function(result,config) { 380 | 381 | var self = this; 382 | var defer = $q.defer(); 383 | if (!result) { 384 | defer.resolve(); 385 | return defer.promise; 386 | } 387 | var promise = $q.when(result).then(function(data) { 388 | 389 | self.contextData.lastResult = data; 390 | if (config && config.resultKey) { 391 | self.contextData[config.resultKey] = data; 392 | } 393 | defer.resolve(); 394 | },function(error){defer.reject(error)}); 395 | return defer.promise; 396 | } 397 | 398 | this.invoke = function(func, self) { 399 | 400 | return $injector.invoke(func,self,this.contextData); 401 | } 402 | 403 | this.getContextData = function(resultKey) { 404 | 405 | return this.contextData; 406 | } 407 | } 408 | 409 | //---------------------------------------------------------------------------------------------------------------------- 410 | function InterceptorProcessor(context,deferred) { 411 | 412 | this.deferred = deferred; 413 | this.context = context; 414 | 415 | } 416 | InterceptorProcessor.prototype.cancel = function(reason) { 417 | 418 | this.context.canceled = true; 419 | this.deferred.reject(reason); 420 | } 421 | InterceptorProcessor.prototype.setData = function(key,value) { 422 | 423 | this.context.contextData[key] = value; 424 | } 425 | InterceptorProcessor.prototype.getData = function(key) { 426 | 427 | return this.context.contextData[key]; 428 | } 429 | //---------------------------------------------------------------------------------------------------------------------- 430 | function AroundProcessor(executed,next,context,deferred,$q) { 431 | 432 | InterceptorProcessor.apply(this,[context,deferred]); 433 | this.executed = executed; 434 | this.next = next; 435 | this.$q = $q; 436 | } 437 | AroundProcessor.prototype = new InterceptorProcessor(); 438 | AroundProcessor.prototype.constructor = AroundProcessor; 439 | 440 | AroundProcessor.prototype.invoke = function() { 441 | 442 | this.context.contextData.processor = this.next; 443 | var instance = this.context.instantiate(this.executed,this.next == null); 444 | return this.$q.when(this.context.invoke(instance.execute,instance)) 445 | } 446 | 447 | //---------------------------------------------------------------------------------------------------------------------- 448 | angular.module('commangular', []) 449 | .provider('$commangular', function() { 450 | 451 | return { 452 | $get: ['commandExecutor',function(commandExecutor) { 453 | 454 | return { 455 | dispatch: function(eventName, data) { 456 | 457 | return commandExecutor.execute(eventName, data); 458 | } 459 | } 460 | }], 461 | 462 | mapTo: function(eventName) { 463 | 464 | var interceptorChain = eventInterceptors[eventName] || (eventInterceptors[eventName] = {}); 465 | if(!interceptorChain.interceptors) 466 | interceptorChain.interceptors = {}; 467 | eventNameString = eventNameString.concat("%" + eventName + "%{" + eventName + "}\n"); 468 | descriptors[eventName] = new CommandDescriptor(); 469 | return descriptors[eventName]; 470 | }, 471 | 472 | asSequence : function() { 473 | 474 | return new CommandDescriptor('S'); 475 | }, 476 | asParallel : function() { 477 | 478 | return new CommandDescriptor('P'); 479 | }, 480 | asFlow : function() { 481 | 482 | return new CommandDescriptor('F'); 483 | }, 484 | 485 | findCommand: function(eventName) { 486 | 487 | return descriptors[eventName]; 488 | } 489 | }; 490 | }); 491 | //----------------------------------------------------------------------------------------------------------------- 492 | angular.module('commangular') 493 | .service('commandExecutor',['$q','$injector','$parse','$exceptionHandler', 494 | function($q,$injector,$parse,$exceptionHandler) { 495 | 496 | return { 497 | 498 | execute: function(eventName, data) { 499 | var self = this; 500 | var defer = $q.defer(); 501 | var context = self.createContext(data); 502 | var descriptor = descriptors[eventName]; 503 | var interceptors = eventInterceptors[eventName].interceptors; 504 | defer.resolve(); 505 | return defer.promise.then(function() { 506 | 507 | return context.intercept('Before',interceptors); 508 | }).then(function() { 509 | 510 | return context.processDescriptor(descriptor); 511 | }).then(function(){ 512 | 513 | return context.intercept('After',interceptors); 514 | }).then(function() { 515 | 516 | return self.returnData(context); 517 | },function(error){ 518 | if(debugEnabled) $exceptionHandler(error); 519 | var def = $q.defer(); 520 | context.intercept('AfterThrowing',interceptors).then(function(){ 521 | def.reject(error); 522 | },function(){defer.reject(error)}); 523 | return def.promise; 524 | }); 525 | 526 | }, 527 | createContext: function(data) { 528 | 529 | return new CommandContext(data,$q,$injector,$parse); 530 | }, 531 | returnData : function(context) { 532 | 533 | return context.contextData; 534 | } 535 | }; 536 | } 537 | ]); 538 | //------------------------------------------------------------------------------------------------------------------ 539 | angular.module('commangular') 540 | .run(commangular.build); 541 | //------------------------------------------------------------------------------------------------------------------ 542 | angular.module('commangular') 543 | .config(['$provide',function($provide) { 544 | 545 | $provide.decorator('$rootScope',['$injector','$delegate',function($injector,$delegate){ 546 | 547 | $delegate.dispatch = function(eventName,data) { 548 | return $injector.get('commandExecutor').execute(eventName,data); 549 | } 550 | return $delegate; 551 | }]); 552 | }]); 553 | })(window, window.angular); -------------------------------------------------------------------------------- /dist/commangular.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Command pattern implementation for AngularJS 3 | * @version v0.9.0 - 2015-03-15 4 | * @link https://github.com/yukatan/commangular 5 | * @author Jesús Barquín Cheda 6 | * @license MIT License, http://www.opensource.org/licenses/MIT 7 | */ 8 | "use strict";!function(a,b){function c(a){return a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}function d(a,b){this.ctype=a,this.command=b,this.descriptors=[]}function e(a,c,d,e){this.contextData=a||{},this.contextData.commandModel={},this.currentDeferred,this.currentCommandInstance,this.canceled=!1,this.processDescriptor=function(a){switch(a.ctype){case"S":return this.processSequence(a);case"P":return this.processParallel(a);case"E":return this.processCommand(a);case"F":return this.processFlow(a)}},this.processSequence=function(a){var b=c.defer(),d=0,e=this;return function f(){e.processDescriptor(a.descriptors[d]).then(function(){return++d===a.descriptors.length?void b.resolve():void f()},function(a){b.reject(a)})}(),b.promise},this.processParallel=function(a){var d=this,e=c.defer(),f=0;return b.forEach(a.descriptors,function(b){d.processDescriptor(b).then(function(){return++f===a.descriptors.length?void e.resolve():void 0},function(a){e.reject(a)})}),e.promise},this.processFlow=function(a){var f=this,g=c.defer(),h=0;return function i(){var c={},j=a.descriptors[h];j.services&&b.forEach(j.services.split(","),function(a){c[a]=d.get(a)});var k=e(j.expresion)(f.contextData,c);if("boolean"!=typeof k)throw new Error("Result from expresion :"+a.expresion+" is not boolean");if(k)f.processDescriptor(j.commandDescriptor).then(function(){return++h===a.descriptors.length?void g.resolve():void i()},function(a){g.reject(a)});else{if(++h===a.descriptors.length)return void g.resolve();i()}}(),g.promise},this.processCommand=function(a){var b,d=this,e=c.defer();return e.resolve(),e.promise.then(function(){return d.intercept("Before",a.command.interceptors)}).then(function(){var e=c.defer();try{if(a.command.interceptors.Around)b=d.intercept("Around",a.command.interceptors,a.command.commandFunction);else{var f=d.instantiate(a.command.commandFunction,!0);b=d.invoke(f.execute,f)}d.processResults(b,a.command.config).then(function(){e.resolve()},function(a){e.reject(a)})}catch(g){e.reject(g)}return e.promise}).then(function(){return d.intercept("AfterExecution",a.command.interceptors)}).then(function(){return b=d.exeOnResult(d.contextData.lastResult),d.processResults(b,a.command.config)}).then(function(){return d.intercept("After",a.command.interceptors)},function(b){var e=c.defer();return d.canceled?(e.reject(b),e.promise):(d.exeOnError(b),d.getContextData().lastError=b,d.intercept("AfterThrowing",a.command.interceptors).then(function(){e.reject(b)},function(){e.reject(b)}),e.promise)})},this.intercept=function(a,d,e){var h=this,i=c.defer();if(!d[a])return i.resolve(),i.promise;switch(d[a].sort(function(a,b){return b.order-a.order}),a){case"Around":var j=new g(e,null,h,i,c);b.forEach(d[a],function(a){j=new g(a.func,j,h,i,c)}),c.when(j.invoke()).then(function(a){i.resolve(a)},function(a){i.reject(a)});break;default:var j=this.contextData.processor=new f(h,i);d[a].reverse();var k=0;!function l(){try{if(k===d[a].length||h.canceled)return void i.resolve();var b=h.instantiate(d[a][k++].func,!1);c.when(h.invoke(b.execute,b)).then(function(){l()},function(){})}catch(e){i.reject(e)}}()}return i.promise},this.instantiate=function(a,b){var c=d.instantiate(a,this.contextData);return b&&(this.currentCommandInstance=c),c},this.exeOnResult=function(a){return this.currentCommandInstance&&this.currentCommandInstance.hasOwnProperty("onResult")?this.currentCommandInstance.onResult(a):void 0},this.exeOnError=function(a){this.currentCommandInstance&&this.currentCommandInstance.hasOwnProperty("onError")&&this.currentCommandInstance.onError(a)},this.processResults=function(a,b){var d=this,e=c.defer();if(!a)return e.resolve(),e.promise;c.when(a).then(function(a){d.contextData.lastResult=a,b&&b.resultKey&&(d.contextData[b.resultKey]=a),e.resolve()},function(a){e.reject(a)});return e.promise},this.invoke=function(a,b){return d.invoke(a,b,this.contextData)},this.getContextData=function(){return this.contextData}}function f(a,b){this.deferred=b,this.context=a}function g(a,b,c,d,e){f.apply(this,[c,d]),this.executed=a,this.next=b,this.$q=e}var h=a.commangular||(a.commangular={}),i={},j="",k="",l=[],m=[],n={},o={},p=/\/(.*)\//,q=/@([^(]*)\((.*)\)/,r=!1;h.create=function(a,b,c){i[a]={commandFunction:b,config:c,interceptors:{},commandName:a},j=j.concat("%"+a+"%{"+a+"}\n")},h.command=h.create,h.aspect=function(a,b,c){var d=q.exec(a),e=d[1],f=p.exec(d[2])[1],g=new RegExp("^%"+f+"%{(.*)}$","mg"),h=c||(c=0);if(!/(\bBefore\b|\bAfterExecution\b|\bAfter\b|\bAfterThrowing\b|\bAround\b)/.test(e))throw new Error("aspect descriptor "+a+" contains errors");l.push({poincut:e,matcher:g,aspectFunction:b,order:h,descriptor:a})},h.eventAspect=function(a,b,c){var d=q.exec(a),e=d[1],f=p.exec(d[2])[1],g=new RegExp("^%"+f+"%{(.*)}$","mg"),h=c||(c=0);if(!/(\bBefore\b|\bAfter\b|\bAfterThrowing\b)/.test(e))throw new Error("aspect descriptor "+a+" contains errors");m.push({poincut:e,matcher:g,aspectFunction:b,order:h,descriptor:a})},h.resolver=function(a,b){var d=["lastResult","processor","$injector",function(c,d,e){return{execute:function(){var f=e.invoke(b,this,{result:c});return d.setData("lastResult",f),i[a]&&i[a].config&&i[a].config.resultKey&&d.setData(i[a].config.resultKey,f),f}}}],e="@AfterExecution(/"+c(a)+"/)";h.aspect(e,d,-100)},h.reset=function(){l=m=[],i=o={},j=k=""},h.debug=function(a){r=a},h.build=function(){!function a(c,d,e){return b.forEach(c,function(a){for(var b;null!=(b=a.matcher.exec(d));)e[b[1]].interceptors[a.poincut]||(e[b[1]].interceptors[a.poincut]=[]),e[b[1]].interceptors[a.poincut].push({func:a.aspectFunction,order:a.order})}),a}(l,j,i)(m,k,o)},d.prototype.asSequence=function(){return this.ctype="S",this},d.prototype.asParallel=function(){return this.ctype="P",this},d.prototype.asFlow=function(){return this.ctype="F",this},d.prototype.add=function(a){return this.descriptors.push(b.isString(a)?new d("E",i[a]):a),this},d.prototype.link=function(a,b){return this.descriptors.push({expresion:a,services:b}),this},d.prototype.to=function(a){return this.descriptors[this.descriptors.length-1].commandDescriptor=b.isString(a)?new d("E",i[a]):a,this},f.prototype.cancel=function(a){this.context.canceled=!0,this.deferred.reject(a)},f.prototype.setData=function(a,b){this.context.contextData[a]=b},f.prototype.getData=function(a){return this.context.contextData[a]},g.prototype=new f,g.prototype.constructor=g,g.prototype.invoke=function(){this.context.contextData.processor=this.next;var a=this.context.instantiate(this.executed,null==this.next);return this.$q.when(this.context.invoke(a.execute,a))},b.module("commangular",[]).provider("$commangular",function(){return{$get:["commandExecutor",function(a){return{dispatch:function(b,c){return a.execute(b,c)}}}],mapTo:function(a){var b=o[a]||(o[a]={});return b.interceptors||(b.interceptors={}),k=k.concat("%"+a+"%{"+a+"}\n"),n[a]=new d,n[a]},asSequence:function(){return new d("S")},asParallel:function(){return new d("P")},asFlow:function(){return new d("F")},findCommand:function(a){return n[a]}}}),b.module("commangular").service("commandExecutor",["$q","$injector","$parse","$exceptionHandler",function(a,b,c,d){return{execute:function(b,c){var e=this,f=a.defer(),g=e.createContext(c),h=n[b],i=o[b].interceptors;return f.resolve(),f.promise.then(function(){return g.intercept("Before",i)}).then(function(){return g.processDescriptor(h)}).then(function(){return g.intercept("After",i)}).then(function(){return e.returnData(g)},function(b){r&&d(b);var c=a.defer();return g.intercept("AfterThrowing",i).then(function(){c.reject(b)},function(){f.reject(b)}),c.promise})},createContext:function(d){return new e(d,a,b,c)},returnData:function(a){return a.contextData}}}]),b.module("commangular").run(h.build),b.module("commangular").config(["$provide",function(a){a.decorator("$rootScope",["$injector","$delegate",function(a,b){return b.dispatch=function(b,c){return a.get("commandExecutor").execute(b,c)},b}])}])}(window,window.angular); -------------------------------------------------------------------------------- /dist/commangular.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yukatan/commangular/194787d943ab33420a5bdce331a5eaef101a1585/dist/commangular.zip -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // Generated on Thu Nov 14 2013 18:54:35 GMT+0100 (CET) 3 | 4 | module.exports = function(config) { 5 | config.set({ 6 | 7 | // base path, that will be used to resolve files and exclude 8 | basePath: '', 9 | 10 | 11 | // frameworks to use 12 | frameworks: ['jasmine'], 13 | 14 | 15 | // list of files / patterns to load in the browser 16 | files: [ 17 | 'bower_components/angular/angular.js', 18 | 'bower_components/angular-mocks/angular-mocks.js', 19 | 'src/commangular.js', 20 | 'src/commangular-mock/commangular-mock.js', 21 | 'test/**/*.js' 22 | 23 | ], 24 | 25 | 26 | // list of files to exclude 27 | exclude: [ 28 | 29 | ], 30 | 31 | 32 | // test results reporter to use 33 | // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage' 34 | reporters: ['progress'], 35 | 36 | 37 | // web server port 38 | port: 9876, 39 | 40 | 41 | // enable / disable colors in the output (reporters and logs) 42 | colors: true, 43 | 44 | 45 | // level of logging 46 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 47 | logLevel: config.LOG_INFO, 48 | 49 | 50 | // enable / disable watching file and executing tests whenever any file changes 51 | autoWatch: true, 52 | 53 | 54 | // Start these browsers, currently available: 55 | // - Chrome 56 | // - ChromeCanary 57 | // - Firefox 58 | // - Opera (has to be installed with `npm install karma-opera-launcher`) 59 | // - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`) 60 | // - PhantomJS 61 | // - IE (only Windows; has to be installed with `npm install karma-ie-launcher`) 62 | browsers: ['Chrome'], 63 | 64 | plugins : [ 65 | 66 | 'karma-chrome-launcher', 67 | 'karma-firefox-launcher', 68 | 'karma-jasmine' 69 | ], 70 | 71 | 72 | 73 | 74 | // If browser does not capture in given timeout [ms], kill it 75 | captureTimeout: 60000, 76 | 77 | 78 | // Continuous Integration mode 79 | // if true, it capture browsers, run tests and exit 80 | singleRun: false 81 | }); 82 | }; 83 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "commangular", 3 | "description": "Command pattern implementation for AngularJS", 4 | "version": "0.9.0", 5 | "filename": "commangular.min.js", 6 | "main": "./dist/commangular.min.js", 7 | "homepage": "https://github.com/yukatan/commangular", 8 | "author": "Jesús Barquín Cheda ", 9 | "repository": { 10 | "type": "git", 11 | "url": "git://github.com/yukatan/commangular.git" 12 | }, 13 | "engines": { 14 | "node": ">= 0.9" 15 | }, 16 | "keywords": [ 17 | "angular", 18 | "angularjs", 19 | "command", 20 | "parsley", 21 | "pattern" 22 | ], 23 | "maintainers": [ 24 | { 25 | "name": "Jesús Barquín Cheda", 26 | "website": "http://" 27 | } 28 | ], 29 | "dependencies": {}, 30 | "devDependencies": { 31 | "grunt-cli": ">= 0.1.7", 32 | "grunt-contrib-concat": "*", 33 | "grunt-contrib-jshint": "*", 34 | "grunt-contrib-uglify": "*", 35 | "grunt-bower": "*", 36 | "grunt-bower-task": "*", 37 | "grunt-karma": "latest", 38 | "karma-jasmine": "latest", 39 | "karma-chrome-launcher": "latest", 40 | "karma-firefox-launcher": "latest", 41 | "grunt-conventional-changelog": "0.0.12", 42 | "grunt-zip": "*" 43 | }, 44 | "scripts": { 45 | "test": "grunt travis --verbose" 46 | }, 47 | "license": "MIT" 48 | } -------------------------------------------------------------------------------- /src/commangular-mock/commangular-mock.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | (function(window, angular, undefined) { 4 | 5 | 6 | commangular.mock = {}; 7 | 8 | var currentSpect = null; 9 | var proxy = null; 10 | var commangularProvider = null; 11 | var scope = null; 12 | 13 | 14 | function execute(event,data,callback) { 15 | 16 | return scope.dispatch(event,data || {}).then( 17 | 18 | function(){ 19 | callback.call(currentSpect,createCommandInfo(proxy)); 20 | }, 21 | function(error){ 22 | callback.call(currentSpect,createCommandInfo(proxy)); 23 | }); 24 | }; 25 | 26 | function randomEventName() { 27 | 28 | return Math.floor((1 + Math.random()) * 0x10000).toString(16); 29 | } 30 | 31 | function createCommandInfo(proxy) { 32 | return { 33 | dataPassed: function(key) { 34 | try {return proxy.excInfo.initData[key];} 35 | catch(error){return undefined}; 36 | }, 37 | resultKey : function(key) { 38 | try {return proxy.excInfo.contextData[key];} 39 | catch(error){return undefined}; 40 | }, 41 | canceled : function() { 42 | return proxy.context.canceled; 43 | }, 44 | commandExecuted : function(commandName) { 45 | var found = false; 46 | angular.forEach(proxy.excInfo.exeChain,function(value){ 47 | if(value.name == commandName) 48 | found = true; 49 | }); 50 | return found; 51 | } 52 | } 53 | } 54 | 55 | function ContextProxy(context,excInfo) { 56 | 57 | this.context = context; 58 | this.contextData = context.contextData; 59 | this.excInfo = excInfo; 60 | this.currentDescriptor; 61 | 62 | this.invoke = function(func,self) { 63 | 64 | return context.invoke(func,self); 65 | } 66 | 67 | this.processSequence = function(descriptor) { 68 | 69 | return context.processSequence.call(this,descriptor); 70 | } 71 | 72 | this.processParallel = function(descriptor) { 73 | 74 | return context.processParallel.call(this,descriptor); 75 | } 76 | 77 | this.processFlow = function(descriptor) { 78 | 79 | return context.processFlow.call(this,descriptor); 80 | } 81 | 82 | this.processCommand = function(descriptor) { 83 | 84 | this.excInfo.exeChain = this.excInfo.exeChain || (this.excInfo.exeChain = []); 85 | this.excInfo.exeChain.push({name:descriptor.command.commandName}); 86 | return context.processCommand.call(this,descriptor); 87 | } 88 | 89 | this.processDescriptor = function(descriptor) { 90 | 91 | return context.processDescriptor.call(this,descriptor); 92 | } 93 | 94 | this.instantiate = function(funct,isCommand) { 95 | 96 | return context.instantiate.call(this,funct,isCommand); 97 | } 98 | 99 | this.processResults = function(result,config) { 100 | 101 | return context.processResults.call(this,result,config); 102 | } 103 | 104 | 105 | this.intercept = function(poincut,interceptors,command) { 106 | 107 | return context.intercept.call(this,poincut,interceptors,command); 108 | } 109 | 110 | this.getContextData = function(resultKey) { 111 | 112 | return context.getContextData.call(this,resultKey); 113 | } 114 | 115 | this.exeOnResult = function(result) { 116 | 117 | return context.exeOnResult.call(this,result); 118 | } 119 | 120 | this.exeOnError = function(error) { 121 | 122 | context.exeOnError.call(this,error); 123 | } 124 | } 125 | 126 | 127 | angular.module('commangularMock',['commangular']).config(function($provide,$commangularProvider) { 128 | 129 | commangularProvider = $commangularProvider; 130 | $provide.decorator('commandExecutor',function($delegate){ 131 | 132 | var createContext = $delegate.createContext; 133 | 134 | $delegate.createContext = function(data) { 135 | 136 | proxy = new ContextProxy(createContext(data),{initData:angular.copy(data),contextData:data}); 137 | return proxy; 138 | } 139 | return $delegate; 140 | }); 141 | }); 142 | 143 | 144 | if(window.jasmine || window.mocha) { 145 | 146 | beforeEach(function() { 147 | 148 | currentSpect = this; 149 | var modules = currentSpect.$modules || []; 150 | modules.unshift('commangularMock'); 151 | currentSpect.$modules = modules; 152 | }); 153 | 154 | afterEach(function(){ 155 | 156 | }); 157 | 158 | window.dispatch = commangular.mock.dispatch = function(ec,callback) { 159 | 160 | if(currentSpect && !currentSpect.$injector) 161 | throw new Error('Injector still not ready to execute ' + commandName); 162 | 163 | if(ec.command){ 164 | ec.event = randomEventName(); 165 | commangularProvider.mapTo(ec.event).asSequence().add(ec.command); 166 | } 167 | scope = currentSpect.$injector.get('$rootScope'); 168 | scope.$apply(execute(ec.event,ec.data,callback)); 169 | }; 170 | } 171 | 172 | })(window,window.angular); -------------------------------------------------------------------------------- /src/commangular.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | (function(window, angular, undefined) { 4 | 5 | var commangular = window.commangular || (window.commangular = {}); 6 | var commands = {}; 7 | var commandNameString = ""; 8 | var eventNameString = ""; 9 | var aspects = []; 10 | var eventAspects = []; 11 | var descriptors = {}; 12 | var eventInterceptors= {}; 13 | var interceptorExtractor = /\/(.*)\//; 14 | var aspectExtractor = /@([^(]*)\((.*)\)/; 15 | var debugEnabled = false; 16 | 17 | function escapeRegExp(str) { 18 | return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); 19 | } 20 | 21 | commangular.create = function(commandName, commandFunction, commandConfig) { 22 | 23 | commands[commandName] = { 24 | commandFunction: commandFunction, 25 | config: commandConfig, 26 | interceptors:{}, 27 | commandName:commandName 28 | }; 29 | commandNameString = commandNameString.concat("%" + commandName + "%{" + commandName + "}\n"); 30 | } 31 | commangular.command = commangular.create; 32 | 33 | commangular.aspect = function(aspectDescriptor,aspectFunction,order) { 34 | 35 | var result = aspectExtractor.exec(aspectDescriptor); 36 | var poincut = result[1]; 37 | var matcherString = interceptorExtractor.exec(result[2])[1]; 38 | var matcher = new RegExp("^%" + matcherString + "%\{(.*)\}$","mg"); 39 | var aspectOrder = order || (order = 0); 40 | if(!/(\bBefore\b|\bAfterExecution\b|\bAfter\b|\bAfterThrowing\b|\bAround\b)/.test(poincut)) 41 | throw new Error('aspect descriptor ' + aspectDescriptor + ' contains errors'); 42 | aspects.push({poincut:poincut, 43 | matcher:matcher, 44 | aspectFunction:aspectFunction, 45 | order:aspectOrder, 46 | descriptor:aspectDescriptor}); 47 | } 48 | 49 | commangular.eventAspect = function(aspectDescriptor,aspectFunction,order) { 50 | 51 | var result = aspectExtractor.exec(aspectDescriptor); 52 | var poincut = result[1]; 53 | var matcherString = interceptorExtractor.exec(result[2])[1]; 54 | var matcher = new RegExp("^%" + matcherString + "%\{(.*)\}$","mg"); 55 | var aspectOrder = order || (order = 0); 56 | if(!/(\bBefore\b|\bAfter\b|\bAfterThrowing\b)/.test(poincut)) 57 | throw new Error('aspect descriptor ' + aspectDescriptor + ' contains errors'); 58 | eventAspects.push({poincut:poincut, 59 | matcher:matcher, 60 | aspectFunction:aspectFunction, 61 | order:aspectOrder, 62 | descriptor:aspectDescriptor}); 63 | } 64 | 65 | commangular.resolver = function (commandName,resolverFunction) { 66 | 67 | var aspectResolverFunction = ['lastResult','processor','$injector',function(lastResult,processor,$injector) { 68 | return { 69 | execute : function() { 70 | var result = $injector.invoke(resolverFunction,this,{result:lastResult}); 71 | processor.setData('lastResult',result); 72 | if(commands[commandName] && 73 | commands[commandName].config && 74 | commands[commandName].config.resultKey) 75 | processor.setData(commands[commandName].config.resultKey,result); 76 | return result; 77 | } 78 | } 79 | }]; 80 | var aspectDescriptor = "@AfterExecution(/" + escapeRegExp(commandName) + "/)"; 81 | commangular.aspect(aspectDescriptor,aspectResolverFunction,-100); 82 | } 83 | 84 | commangular.reset = function() { 85 | 86 | aspects = eventAspects = []; 87 | commands = eventInterceptors = {}; 88 | commandNameString = eventNameString = ""; 89 | } 90 | 91 | commangular.debug = function(enableDebug){ 92 | 93 | debugEnabled = enableDebug; 94 | } 95 | 96 | 97 | commangular.build = function(){ 98 | 99 | (function processInterceptors(collection,stringList,targets) { 100 | 101 | angular.forEach(collection,function(aspect){ 102 | var result; 103 | while((result = aspect.matcher.exec(stringList)) != null) { 104 | 105 | if(!targets[result[1]].interceptors[aspect.poincut]) 106 | targets[result[1]].interceptors[aspect.poincut] = []; 107 | targets[result[1]].interceptors[aspect.poincut] 108 | .push({func:aspect.aspectFunction,order:aspect.order}); 109 | } 110 | }); 111 | return processInterceptors; 112 | }(aspects,commandNameString,commands)(eventAspects,eventNameString,eventInterceptors)); 113 | 114 | } 115 | 116 | //---------------------------------------------------------------------------------------------------------------------- 117 | 118 | function CommandDescriptor(ctype,command) { 119 | 120 | this.ctype = ctype; 121 | this.command = command; 122 | this.descriptors = []; 123 | } 124 | 125 | CommandDescriptor.prototype.asSequence = function() { 126 | 127 | this.ctype = 'S'; 128 | return this; 129 | }; 130 | 131 | CommandDescriptor.prototype.asParallel = function() { 132 | 133 | this.ctype = 'P'; 134 | return this; 135 | }; 136 | 137 | CommandDescriptor.prototype.asFlow = function() { 138 | 139 | this.ctype = 'F'; 140 | return this; 141 | }; 142 | 143 | CommandDescriptor.prototype.add = function(command) { 144 | 145 | this.descriptors.push((angular.isString(command)) ? new CommandDescriptor('E',commands[command]):command); 146 | return this; 147 | }; 148 | CommandDescriptor.prototype.link = function(expresion, services) { 149 | 150 | this.descriptors.push({expresion:expresion,services:services}); 151 | return this; 152 | }; 153 | CommandDescriptor.prototype.to = function(command) { 154 | 155 | this.descriptors[this.descriptors.length -1].commandDescriptor = (angular.isString(command) ? 156 | new CommandDescriptor('E',commands[command]):command); 157 | return this; 158 | }; 159 | 160 | //---------------------------------------------------------------------------------------------------------------------- 161 | function CommandContext(data,$q,$injector,$parse) { 162 | 163 | this.contextData = data || {}; 164 | this.contextData.commandModel = {}; 165 | this.currentDeferred; 166 | this.currentCommandInstance; 167 | this.canceled = false; 168 | 169 | this.processDescriptor = function(descriptor) { 170 | 171 | switch (descriptor.ctype) { 172 | case 'S': 173 | return this.processSequence(descriptor); 174 | case 'P': 175 | return this.processParallel(descriptor); 176 | case 'E': 177 | return this.processCommand(descriptor); 178 | case 'F': 179 | return this.processFlow(descriptor); 180 | } 181 | } 182 | 183 | this.processSequence = function(descriptor) { 184 | 185 | var defer = $q.defer(); 186 | var index = 0; 187 | var self = this; 188 | (function sequenceChain(){ 189 | self.processDescriptor(descriptor.descriptors[index]).then(function(){ 190 | if(++index === descriptor.descriptors.length){ 191 | defer.resolve(); 192 | return; 193 | } 194 | sequenceChain(); 195 | },function(error){defer.reject(error)}); 196 | }()); 197 | return defer.promise; 198 | } 199 | 200 | this.processParallel = function(descriptor) { 201 | 202 | var self = this; 203 | var defer = $q.defer(); 204 | var index = 0; 205 | angular.forEach(descriptor.descriptors,function(desc){ 206 | self.processDescriptor(desc).then(function(){ 207 | if(++index === descriptor.descriptors.length){ 208 | defer.resolve(); 209 | return; 210 | } 211 | },function(error){defer.reject(error)}); 212 | }); 213 | return defer.promise; 214 | 215 | } 216 | 217 | this.processFlow = function(descriptor) { 218 | 219 | var self = this; 220 | var defer = $q.defer(); 221 | var index = 0; 222 | (function flowChain() { 223 | var locals = {}; 224 | var desc = descriptor.descriptors[index]; 225 | if(desc.services) { 226 | 227 | angular.forEach(desc.services.split(','), function(service, key){ 228 | locals[service] = $injector.get(service); 229 | }); 230 | } 231 | var result = $parse(desc.expresion)(self.contextData,locals); 232 | if(typeof result !== 'boolean') 233 | throw new Error('Result from expresion :' + descriptor.expresion + ' is not boolean'); 234 | if(result){ 235 | self.processDescriptor(desc.commandDescriptor).then(function(){ 236 | if(++index === descriptor.descriptors.length){ 237 | defer.resolve(); 238 | return; 239 | } 240 | flowChain(); 241 | },function(error){defer.reject(error)}); 242 | } 243 | else{ 244 | if(++index === descriptor.descriptors.length){ 245 | defer.resolve(); 246 | return; 247 | } 248 | flowChain(); 249 | } 250 | }()); 251 | return defer.promise; 252 | } 253 | 254 | this.processCommand = function(descriptor) { 255 | 256 | var self = this; 257 | var result; 258 | var deferExecution = $q.defer(); 259 | deferExecution.resolve(); 260 | return deferExecution.promise 261 | .then(function () { 262 | return self.intercept('Before',descriptor.command.interceptors); 263 | }) 264 | .then(function() { 265 | var deferred = $q.defer(); 266 | try{ 267 | if(descriptor.command.interceptors['Around']) 268 | result = self.intercept('Around',descriptor.command.interceptors,descriptor.command.commandFunction); 269 | else { 270 | var command = self.instantiate(descriptor.command.commandFunction,true); 271 | result = self.invoke(command.execute, command); 272 | } 273 | self.processResults(result,descriptor.command.config).then(function(){ 274 | deferred.resolve(); 275 | },function(error){ 276 | deferred.reject(error); 277 | }); 278 | }catch(error){ 279 | deferred.reject(error); 280 | } 281 | return deferred.promise; 282 | }) 283 | .then(function(){ 284 | return self.intercept('AfterExecution',descriptor.command.interceptors); 285 | }) 286 | .then(function(){ 287 | result = self.exeOnResult(self.contextData.lastResult); 288 | return self.processResults(result,descriptor.command.config); 289 | }) 290 | .then(function(){ 291 | return self.intercept('After',descriptor.command.interceptors); 292 | },function(error) { 293 | var deferred = $q.defer(); 294 | if(self.canceled){ 295 | deferred.reject(error); 296 | return deferred.promise; 297 | } 298 | self.exeOnError(error); 299 | self.getContextData().lastError = error; 300 | self.intercept('AfterThrowing',descriptor.command.interceptors).then(function(){ 301 | deferred.reject(error) 302 | },function(){deferred.reject(error)}); 303 | return deferred.promise; 304 | }); 305 | } 306 | 307 | this.intercept = function(poincut,interceptors,command) { 308 | 309 | var self = this; 310 | var deferred = $q.defer(); 311 | if(!interceptors[poincut]){ 312 | deferred.resolve(); 313 | return deferred.promise; 314 | } 315 | interceptors[poincut].sort(function(a,b){ 316 | return b.order - a.order; 317 | }) 318 | switch(poincut) { 319 | case 'Around' : { 320 | var processor = new AroundProcessor(command,null,self,deferred,$q); 321 | angular.forEach(interceptors[poincut],function(value){ 322 | processor = new AroundProcessor(value.func,processor,self,deferred,$q); 323 | }); 324 | $q.when(processor.invoke()).then(function(result){ 325 | deferred.resolve(result); 326 | },function(error){ 327 | deferred.reject(error);}); 328 | break; 329 | } 330 | default : { 331 | var processor = this.contextData.processor = new InterceptorProcessor(self,deferred); 332 | interceptors[poincut].reverse(); 333 | var x = 0; 334 | (function invocationChain(){ 335 | try{ 336 | if(x === interceptors[poincut].length || self.canceled){ 337 | deferred.resolve(); 338 | return; 339 | } 340 | var interceptor = self.instantiate(interceptors[poincut][x++].func,false); 341 | $q.when(self.invoke(interceptor.execute,interceptor)).then(function(){ 342 | invocationChain(); 343 | },function(error){}); 344 | }catch(error){deferred.reject(error)}; 345 | }()); 346 | break; 347 | } 348 | } 349 | return deferred.promise; 350 | } 351 | 352 | 353 | this.instantiate = function(funct,isCommand) { 354 | 355 | var instance = $injector.instantiate(funct,this.contextData); 356 | if(isCommand) this.currentCommandInstance = instance; 357 | return instance; 358 | } 359 | 360 | this.exeOnResult = function(result) { 361 | 362 | if(this.currentCommandInstance && this.currentCommandInstance.hasOwnProperty('onResult')) 363 | return this.currentCommandInstance.onResult(result); 364 | } 365 | 366 | this.exeOnError = function(error) { 367 | 368 | if(this.currentCommandInstance && this.currentCommandInstance.hasOwnProperty('onError')) 369 | this.currentCommandInstance.onError(error); 370 | } 371 | 372 | this.processResults = function(result,config) { 373 | 374 | var self = this; 375 | var defer = $q.defer(); 376 | if (!result) { 377 | defer.resolve(); 378 | return defer.promise; 379 | } 380 | var promise = $q.when(result).then(function(data) { 381 | 382 | self.contextData.lastResult = data; 383 | if (config && config.resultKey) { 384 | self.contextData[config.resultKey] = data; 385 | } 386 | defer.resolve(); 387 | },function(error){defer.reject(error)}); 388 | return defer.promise; 389 | } 390 | 391 | this.invoke = function(func, self) { 392 | 393 | return $injector.invoke(func,self,this.contextData); 394 | } 395 | 396 | this.getContextData = function(resultKey) { 397 | 398 | return this.contextData; 399 | } 400 | } 401 | 402 | //---------------------------------------------------------------------------------------------------------------------- 403 | function InterceptorProcessor(context,deferred) { 404 | 405 | this.deferred = deferred; 406 | this.context = context; 407 | 408 | } 409 | InterceptorProcessor.prototype.cancel = function(reason) { 410 | 411 | this.context.canceled = true; 412 | this.deferred.reject(reason); 413 | } 414 | InterceptorProcessor.prototype.setData = function(key,value) { 415 | 416 | this.context.contextData[key] = value; 417 | } 418 | InterceptorProcessor.prototype.getData = function(key) { 419 | 420 | return this.context.contextData[key]; 421 | } 422 | //---------------------------------------------------------------------------------------------------------------------- 423 | function AroundProcessor(executed,next,context,deferred,$q) { 424 | 425 | InterceptorProcessor.apply(this,[context,deferred]); 426 | this.executed = executed; 427 | this.next = next; 428 | this.$q = $q; 429 | } 430 | AroundProcessor.prototype = new InterceptorProcessor(); 431 | AroundProcessor.prototype.constructor = AroundProcessor; 432 | 433 | AroundProcessor.prototype.invoke = function() { 434 | 435 | this.context.contextData.processor = this.next; 436 | var instance = this.context.instantiate(this.executed,this.next == null); 437 | return this.$q.when(this.context.invoke(instance.execute,instance)) 438 | } 439 | 440 | //---------------------------------------------------------------------------------------------------------------------- 441 | angular.module('commangular', []) 442 | .provider('$commangular', function() { 443 | 444 | return { 445 | $get: ['commandExecutor',function(commandExecutor) { 446 | 447 | return { 448 | dispatch: function(eventName, data) { 449 | 450 | return commandExecutor.execute(eventName, data); 451 | } 452 | } 453 | }], 454 | 455 | mapTo: function(eventName) { 456 | 457 | var interceptorChain = eventInterceptors[eventName] || (eventInterceptors[eventName] = {}); 458 | if(!interceptorChain.interceptors) 459 | interceptorChain.interceptors = {}; 460 | eventNameString = eventNameString.concat("%" + eventName + "%{" + eventName + "}\n"); 461 | descriptors[eventName] = new CommandDescriptor(); 462 | return descriptors[eventName]; 463 | }, 464 | 465 | asSequence : function() { 466 | 467 | return new CommandDescriptor('S'); 468 | }, 469 | asParallel : function() { 470 | 471 | return new CommandDescriptor('P'); 472 | }, 473 | asFlow : function() { 474 | 475 | return new CommandDescriptor('F'); 476 | }, 477 | 478 | findCommand: function(eventName) { 479 | 480 | return descriptors[eventName]; 481 | } 482 | }; 483 | }); 484 | //----------------------------------------------------------------------------------------------------------------- 485 | angular.module('commangular') 486 | .service('commandExecutor',['$q','$injector','$parse','$exceptionHandler', 487 | function($q,$injector,$parse,$exceptionHandler) { 488 | 489 | return { 490 | 491 | execute: function(eventName, data) { 492 | var self = this; 493 | var defer = $q.defer(); 494 | var context = self.createContext(data); 495 | var descriptor = descriptors[eventName]; 496 | var interceptors = eventInterceptors[eventName].interceptors; 497 | defer.resolve(); 498 | return defer.promise.then(function() { 499 | 500 | return context.intercept('Before',interceptors); 501 | }).then(function() { 502 | 503 | return context.processDescriptor(descriptor); 504 | }).then(function(){ 505 | 506 | return context.intercept('After',interceptors); 507 | }).then(function() { 508 | 509 | return self.returnData(context); 510 | },function(error){ 511 | if(debugEnabled) $exceptionHandler(error); 512 | var def = $q.defer(); 513 | context.intercept('AfterThrowing',interceptors).then(function(){ 514 | def.reject(error); 515 | },function(){defer.reject(error)}); 516 | return def.promise; 517 | }); 518 | 519 | }, 520 | createContext: function(data) { 521 | 522 | return new CommandContext(data,$q,$injector,$parse); 523 | }, 524 | returnData : function(context) { 525 | 526 | return context.contextData; 527 | } 528 | }; 529 | } 530 | ]); 531 | //------------------------------------------------------------------------------------------------------------------ 532 | angular.module('commangular') 533 | .run(commangular.build); 534 | //------------------------------------------------------------------------------------------------------------------ 535 | angular.module('commangular') 536 | .config(['$provide',function($provide) { 537 | 538 | $provide.decorator('$rootScope',['$injector','$delegate',function($injector,$delegate){ 539 | 540 | $delegate.dispatch = function(eventName,data) { 541 | return $injector.get('commandExecutor').execute(eventName,data); 542 | } 543 | return $delegate; 544 | }]); 545 | }]); 546 | })(window, window.angular); -------------------------------------------------------------------------------- /test/command-aspects/after-interception-testing.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Aspect @After execution testing", function() { 4 | 5 | var provider; 6 | var scope; 7 | var interceptorExecutedAfter = false; 8 | var commandExecuted = false; 9 | 10 | beforeEach(function() { 11 | 12 | commangular.reset(); 13 | 14 | commangular.aspect('@After(/com\.test1.*/)', function(){ 15 | 16 | return { 17 | 18 | execute : function (lastResult) { 19 | 20 | expect(lastResult).toBeDefined(); 21 | expect(lastResult).toBe("monkey2"); 22 | interceptorExecutedAfter = true; 23 | } 24 | } 25 | 26 | }); 27 | 28 | commangular.create('com.test1.Command1',function(){ 29 | 30 | return { 31 | 32 | execute : function() { 33 | 34 | commandExecuted = true; 35 | return "monkey"; 36 | 37 | }, 38 | onResult: function(lastResult){ 39 | 40 | expect(lastResult).toBe("monkey"); 41 | return "monkey2"; 42 | } 43 | }; 44 | }); 45 | 46 | }); 47 | 48 | beforeEach(function() { 49 | 50 | module('commangular', function($commangularProvider) { 51 | provider = $commangularProvider; 52 | }); 53 | inject(); 54 | }); 55 | 56 | it("should execute the interceptor after the command", function() { 57 | 58 | var complete = false; 59 | provider.mapTo('AfterTestEvent').asSequence().add('com.test1.Command1'); 60 | dispatch({event:'AfterTestEvent'},function(){ 61 | 62 | expect(interceptorExecutedAfter).toBe(true); 63 | expect(commandExecuted).toBe(true); 64 | }); 65 | }); 66 | }); -------------------------------------------------------------------------------- /test/command-aspects/afterexecution-interception-testing.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Aspect @AfterExecution execution testing", function() { 4 | 5 | var provider; 6 | var scope; 7 | var interceptorExecutedAfter = false; 8 | var commandExecuted = false; 9 | 10 | beforeEach(function() { 11 | 12 | commangular.reset(); 13 | 14 | commangular.aspect('@AfterExecution(/com\.test1.*/)', function(){ 15 | 16 | return { 17 | 18 | execute : function () { 19 | 20 | interceptorExecutedAfter = true; 21 | } 22 | } 23 | 24 | }); 25 | 26 | commangular.aspect('@AfterExecution(/com\.test2.*/)', function(lastResult){ 27 | 28 | return { 29 | 30 | execute : function() { 31 | 32 | expect(lastResult).toBeDefined(); 33 | expect(lastResult).toBe('monkey'); 34 | } 35 | } 36 | 37 | }); 38 | 39 | commangular.create('com.test1.Command1',function(){ 40 | 41 | return { 42 | 43 | execute : function() { 44 | 45 | commandExecuted = true; 46 | } 47 | }; 48 | }); 49 | 50 | commangular.create('com.test2.Command2',function(){ 51 | 52 | return { 53 | 54 | execute : function() { 55 | 56 | return "monkey"; 57 | } 58 | }; 59 | }); 60 | 61 | }); 62 | 63 | beforeEach(function() { 64 | 65 | module('commangular', function($commangularProvider) { 66 | provider = $commangularProvider; 67 | }); 68 | inject(); 69 | }); 70 | 71 | it("should execute the interceptor after the command", function() { 72 | 73 | var complete = false; 74 | provider.mapTo('AfterTestEvent').asSequence().add('com.test1.Command1'); 75 | dispatch({event:'AfterTestEvent'},function(){ 76 | 77 | expect(interceptorExecutedAfter).toBe(true); 78 | expect(commandExecuted).toBe(true); 79 | }); 80 | }); 81 | }); -------------------------------------------------------------------------------- /test/command-aspects/afterthrowing-interception-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("@AfterThrowing interception test", function() { 4 | 5 | var provider; 6 | var interceptorExecuted = false; 7 | var commandExecuted = false; 8 | 9 | beforeEach(function() { 10 | 11 | commangular.reset(); 12 | 13 | commangular.aspect('@AfterThrowing(/com\.test1.*/)', function(processor,lastError){ 14 | 15 | return { 16 | 17 | execute:function() { 18 | 19 | expect(commandExecuted).toBe(false) 20 | expect(lastError.message).toBe('Error from command'); 21 | interceptorExecuted = true; 22 | } 23 | } 24 | 25 | }); 26 | 27 | commangular.create('com.test1.Command1',function(){ 28 | 29 | return { 30 | 31 | execute : function() { 32 | 33 | throw new Error('Error from command'); 34 | commandExecuted = true; 35 | } 36 | }; 37 | }); 38 | 39 | }); 40 | 41 | beforeEach(function() { 42 | 43 | module('commangular', function($commangularProvider) { 44 | provider = $commangularProvider; 45 | }); 46 | inject(); 47 | }); 48 | 49 | it("provider should be defined", function() { 50 | 51 | expect(provider).toBeDefined(); 52 | }); 53 | 54 | it("should execute the interceptor after throw an exception", function() { 55 | 56 | provider.mapTo('AfterThrowingTestEvent').asSequence().add('com.test1.Command1'); 57 | 58 | dispatch({event:'AfterThrowingTestEvent'},function() { 59 | 60 | expect(interceptorExecuted).toBe(true); 61 | expect(commandExecuted).toBe(false); 62 | }); 63 | }); 64 | }); -------------------------------------------------------------------------------- /test/command-aspects/around-cancelation-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("@Around cancelation testing", function() { 4 | 5 | var provider; 6 | var interceptorExecutedBefore = false; 7 | var commandExecuted = false; 8 | 9 | beforeEach(function() { 10 | 11 | commangular.reset(); 12 | 13 | commangular.aspect('@Around(/com\.test1.*/)', function(processor){ 14 | 15 | return { 16 | 17 | execute:function() { 18 | 19 | expect(commandExecuted).toBe(false) 20 | processor.cancel(); 21 | interceptorExecutedBefore = true; 22 | } 23 | } 24 | 25 | }); 26 | 27 | 28 | commangular.create('com.test1.Command1',function(){ 29 | 30 | return { 31 | 32 | execute : function() { 33 | 34 | commandExecuted = true; 35 | } 36 | }; 37 | }); 38 | }); 39 | 40 | beforeEach(function() { 41 | 42 | module('commangular', function($commangularProvider) { 43 | provider = $commangularProvider; 44 | }); 45 | inject(); 46 | }); 47 | 48 | it("provider should be defined", function() { 49 | 50 | expect(provider).toBeDefined(); 51 | }); 52 | 53 | it("should execute the interceptor around the command", function() { 54 | 55 | provider.mapTo('AroundTestEvent').asSequence().add('com.test1.Command1'); 56 | 57 | dispatch({event:'AroundTestEvent'},function() { 58 | 59 | expect(interceptorExecutedBefore).toBe(true); 60 | expect(commandExecuted).toBe(false); 61 | }); 62 | }); 63 | }); -------------------------------------------------------------------------------- /test/command-aspects/around-interception-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("@Around execution testing", function() { 4 | 5 | var provider; 6 | var scope; 7 | var interceptorExecutedBefore = false; 8 | var commandExecuted = false; 9 | 10 | beforeEach(function() { 11 | 12 | commangular.reset(); 13 | 14 | commangular.aspect('@Around(/com\.test1.*/)', function(processor){ 15 | 16 | return { 17 | 18 | execute:function() { 19 | 20 | expect(commandExecuted).toBe(false) 21 | processor.invoke(); 22 | expect(commandExecuted).toBe(true); 23 | interceptorExecutedBefore = true; 24 | } 25 | } 26 | 27 | }); 28 | 29 | commangular.create('com.test1.Command1',function(){ 30 | 31 | return { 32 | 33 | execute : function() { 34 | 35 | commandExecuted = true; 36 | } 37 | }; 38 | }); 39 | 40 | }); 41 | 42 | beforeEach(function() { 43 | 44 | module('commangular', function($commangularProvider) { 45 | provider = $commangularProvider; 46 | }); 47 | inject(); 48 | }); 49 | 50 | it("provider should be defined", function() { 51 | 52 | expect(provider).toBeDefined(); 53 | }); 54 | 55 | it("should execute the interceptor around the command", function() { 56 | 57 | provider.mapTo('AroundTestEvent').asSequence().add('com.test1.Command1'); 58 | 59 | dispatch({event:'AroundTestEvent'},function() { 60 | 61 | expect(interceptorExecutedBefore).toBe(true); 62 | expect(commandExecuted).toBe(true); 63 | }); 64 | }); 65 | }); -------------------------------------------------------------------------------- /test/command-aspects/around-modifying-parameters-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("@Around with promise testing", function() { 4 | 5 | var provider; 6 | var $timeout; 7 | var interceptorExecutedBefore = false; 8 | var commandExecuted = false; 9 | 10 | beforeEach(function() { 11 | 12 | commangular.reset(); 13 | 14 | commangular.aspect('@Around(/com\.test1.*/)', function(processor,data){ 15 | 16 | return { 17 | 18 | execute:function() { 19 | 20 | expect(data).toBe('monkey'); 21 | processor.setData('data','updatedMonkey'); 22 | expect(commandExecuted).toBe(false) 23 | var promise = processor.invoke(); 24 | interceptorExecutedBefore = true; 25 | expect(commandExecuted).toBe(false); 26 | return promise; 27 | } 28 | } 29 | 30 | 31 | }); 32 | 33 | 34 | commangular.create('com.test1.Command1',function($q,$timeout,data){ 35 | 36 | return { 37 | 38 | execute : function() { 39 | 40 | expect(data).toBe('updatedMonkey'); 41 | return $timeout(function(){ 42 | commandExecuted = true; 43 | },2000); 44 | 45 | } 46 | }; 47 | }); 48 | 49 | 50 | 51 | }); 52 | 53 | beforeEach(function() { 54 | 55 | module('commangular', function($commangularProvider) { 56 | provider = $commangularProvider; 57 | }); 58 | inject(function(_$timeout_) { 59 | 60 | $timeout = _$timeout_; 61 | }); 62 | }); 63 | 64 | it("provider should be defined", function() { 65 | 66 | expect(provider).toBeDefined(); 67 | }); 68 | 69 | it("should execute the interceptor around the command and change some data with the processor", function() { 70 | 71 | provider.mapTo('AroundTestEvent').asSequence().add('com.test1.Command1'); 72 | dispatch({event:'AroundTestEvent',data:{data:'monkey'}},function() { 73 | 74 | expect(interceptorExecutedBefore).toBe(true); 75 | expect(commandExecuted).toBe(true); 76 | }); 77 | $timeout.flush(); 78 | }); 79 | 80 | }); -------------------------------------------------------------------------------- /test/command-aspects/around-with-promise-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("@Around with promise testing", function() { 4 | 5 | var provider; 6 | var scope; 7 | var timeout; 8 | var interceptorExecutedBefore = false; 9 | var commandExecuted = false; 10 | 11 | beforeEach(function() { 12 | 13 | commangular.reset(); 14 | 15 | commangular.aspect('@Around(/com\.test1.*/)', function(processor){ 16 | 17 | return { 18 | 19 | execute:function() { 20 | 21 | expect(commandExecuted).toBe(false) 22 | var promise = processor.invoke().then(function(){ 23 | expect(commandExecuted).toBe(true); 24 | interceptorExecutedBefore = true; 25 | }); 26 | expect(commandExecuted).toBe(false); 27 | return promise; 28 | } 29 | } 30 | }); 31 | 32 | 33 | commangular.create('com.test1.Command1',function($q,$timeout){ 34 | 35 | return { 36 | 37 | execute : function() { 38 | 39 | var deferred = $q.defer(); 40 | $timeout(function(){ 41 | commandExecuted = true; 42 | deferred.resolve("Resolved"); 43 | },1000); 44 | return deferred.promise; 45 | } 46 | }; 47 | }); 48 | 49 | 50 | 51 | }); 52 | 53 | beforeEach(function() { 54 | 55 | module('commangular', function($commangularProvider) { 56 | provider = $commangularProvider; 57 | }); 58 | inject(function($timeout) { 59 | timeout = $timeout; 60 | }); 61 | }); 62 | 63 | it("provider should be defined", function() { 64 | 65 | expect(provider).toBeDefined(); 66 | }); 67 | 68 | it("should execute the interceptor around the command and works with promises", function() { 69 | 70 | provider.mapTo('AroundTestEvent').asSequence().add('com.test1.Command1'); 71 | dispatch({event:'AroundTestEvent'},function() { 72 | 73 | expect(interceptorExecutedBefore).toBe(true); 74 | expect(commandExecuted).toBe(true); 75 | }); 76 | timeout.flush(); 77 | }); 78 | }); -------------------------------------------------------------------------------- /test/command-aspects/aspect-definition-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Aspect definition testing", function() { 4 | 5 | var provider; 6 | function aspectTest(){}; 7 | 8 | beforeEach(function() { 9 | 10 | commangular.reset(); 11 | commangular.aspect('@Before(/com\.services.*/)', aspectTest); 12 | commangular.aspect('@AfterExecution(/.*Command3.*/)', aspectTest); 13 | commangular.aspect('@AfterThrowing(/com\.services.*/)', aspectTest); 14 | commangular.aspect('@Around(/.*Command3.*/)', aspectTest); 15 | commangular.create('com.services.Command3',function(){}); 16 | }); 17 | 18 | beforeEach(function() { 19 | 20 | module('commangular', function($commangularProvider) { 21 | 22 | provider = $commangularProvider; 23 | }); 24 | inject(function() {}); 25 | }); 26 | 27 | it("provider should be defined", function() { 28 | 29 | expect(provider).toBeDefined(); 30 | }); 31 | 32 | //TODO: Use commangular mocks 33 | /*it("should create the interceptor Before on com.services.Command3", function() { 34 | 35 | expect(commangular.commands['com.services.Command3'].interceptors).toBeDefined(); 36 | expect(commangular.commands['com.services.Command3'].interceptors['Before']).toBeDefined(); 37 | expect(commangular.commands['com.services.Command3'].interceptors['Before'][0].func).toEqual(aspectTest); 38 | }); 39 | 40 | it("should create the interceptor After on com.services.Command3", function() { 41 | 42 | expect(commangular.commands['com.services.Command3'].interceptors).toBeDefined(); 43 | expect(commangular.commands['com.services.Command3'].interceptors['After']).toBeDefined(); 44 | expect(commangular.commands['com.services.Command3'].interceptors['After'][0].func).toEqual(aspectTest); 45 | }); 46 | 47 | it("should create the interceptor AfterThrowing on com.services.Command3", function() { 48 | 49 | expect(commangular.commands['com.services.Command3'].interceptors).toBeDefined(); 50 | expect(commangular.commands['com.services.Command3'].interceptors['AfterThrowing']).toBeDefined(); 51 | expect(commangular.commands['com.services.Command3'].interceptors['AfterThrowing'][0].func).toEqual(aspectTest); 52 | }); 53 | 54 | it("should create the interceptor Around on com.services.Command3", function() { 55 | 56 | expect(commangular.commands['com.services.Command3'].interceptors).toBeDefined(); 57 | expect(commangular.commands['com.services.Command3'].interceptors['Around']).toBeDefined(); 58 | expect(commangular.commands['com.services.Command3'].interceptors['Around'][0].func).toEqual(aspectTest); 59 | });*/ 60 | 61 | 62 | }); -------------------------------------------------------------------------------- /test/command-aspects/aspect-execution-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Aspect execution testing", function() { 4 | 5 | var provider; 6 | 7 | var interceptorExecutedBefore = false; 8 | var commandExecutedAfter = false; 9 | var afterInterceptorExecutedAfterCommand = false; 10 | var afterInterceptorExecutedAfterOnResult = false; 11 | var afterThrowingInterceptorExecutedAfterCommand = false; 12 | var onResultMethodExecuted = false; 13 | 14 | beforeEach(function() { 15 | 16 | commangular.reset(); 17 | commangular.aspect('@Before(/Command[1-9]/)', function(){ 18 | 19 | return { 20 | 21 | execute:function () { 22 | 23 | interceptorExecutedBefore = true; 24 | } 25 | } 26 | 27 | }); 28 | commangular.aspect('@AfterExecution(/Command[1-9]/)', function(){ 29 | 30 | return { 31 | 32 | execute : function() { 33 | 34 | if(commandExecutedAfter) 35 | afterInterceptorExecutedAfterCommand = true; 36 | } 37 | } 38 | }); 39 | commangular.aspect('@After(/Command[1-9]/)', function(){ 40 | 41 | return { 42 | 43 | execute : function() { 44 | 45 | if(commandExecutedAfter && afterInterceptorExecutedAfterCommand) 46 | afterInterceptorExecutedAfterOnResult = true; 47 | } 48 | } 49 | }); 50 | 51 | commangular.aspect('@AfterThrowing(/Command[1-9]/)', function(){ 52 | 53 | return { 54 | 55 | execute : function() { 56 | 57 | afterThrowingInterceptorExecutedAfterCommand = true; 58 | } 59 | } 60 | }); 61 | 62 | commangular.aspect('@Around(/Command[1-9]/)', function(processor){ 63 | 64 | return { 65 | 66 | execute : function() { 67 | 68 | var result = processor.invoke(); 69 | return "Return from around 1"; 70 | } 71 | } 72 | }); 73 | 74 | commangular.aspect('@Around(/Command[1-9]/)', function(processor){ 75 | 76 | 77 | return { 78 | 79 | execute : function() { 80 | 81 | var result = processor.invoke(); 82 | return result; 83 | } 84 | } 85 | }); 86 | 87 | commangular.create('Command1',function(){ 88 | 89 | return { 90 | 91 | execute : function() { 92 | 93 | if(interceptorExecutedBefore) { 94 | commandExecutedAfter = true; 95 | } 96 | return "return From command1"; 97 | }, 98 | onResult: function(){ 99 | 100 | onResultMethodExecuted = true; 101 | } 102 | }; 103 | }); 104 | 105 | commangular.create('Command2',function(){ 106 | 107 | return { 108 | 109 | execute : function() { 110 | 111 | throw new Error("This is an error"); 112 | } 113 | }; 114 | }); 115 | 116 | commangular.create('Command3',function(){ 117 | 118 | return { 119 | 120 | execute : function() { 121 | 122 | throw new Error("This is an error"); 123 | } 124 | }; 125 | }); 126 | }); 127 | 128 | beforeEach(function() { 129 | 130 | module('commangular', function($commangularProvider) { 131 | 132 | provider = $commangularProvider; 133 | }); 134 | inject(); 135 | }); 136 | 137 | it("provider should be defined", function() { 138 | 139 | expect(provider).toBeDefined(); 140 | }); 141 | 142 | it("should execute the interceptor before the command", function() { 143 | 144 | provider.mapTo('AspectTestEvent').asSequence().add('Command1'); 145 | dispatch({event:'AspectTestEvent'},function() { 146 | 147 | expect(commandExecutedAfter).toBe(true); 148 | expect(interceptorExecutedBefore).toBe(true); 149 | }); 150 | }); 151 | 152 | it("should execute the interceptor afterexecution the command", function() { 153 | 154 | provider.mapTo('AspectTestEvent').asSequence().add('Command1'); 155 | dispatch({event:'AspectTestEvent'},function() { 156 | 157 | expect(commandExecutedAfter).toBe(true); 158 | expect(interceptorExecutedBefore).toBe(true); 159 | expect(afterInterceptorExecutedAfterCommand).toBe(true); 160 | }); 161 | }); 162 | 163 | it("should execute the interceptor after the command", function() { 164 | 165 | provider.mapTo('AspectTestEvent').asSequence().add('Command1'); 166 | dispatch({event:'AspectTestEvent'},function() { 167 | 168 | expect(commandExecutedAfter).toBe(true); 169 | expect(interceptorExecutedBefore).toBe(true); 170 | expect(afterInterceptorExecutedAfterCommand).toBe(true); 171 | expect(onResultMethodExecuted).toBe(true); 172 | expect(afterInterceptorExecutedAfterOnResult).toBe(true); 173 | }); 174 | }); 175 | 176 | it("should execute the interceptor after throwing an exception", function() { 177 | 178 | provider.mapTo('AspectTestEvent').asSequence().add('Command2'); 179 | dispatch({event:'AspectTestEvent'},function() { 180 | 181 | expect(afterThrowingInterceptorExecutedAfterCommand).toBe(true); 182 | }); 183 | }); 184 | 185 | it("should execute the interceptor Around ", function() { 186 | 187 | provider.mapTo('AspectTestEvent').asSequence().add('Command1'); 188 | dispatch({event:'AspectTestEvent'},function() { 189 | 190 | expect(afterThrowingInterceptorExecutedAfterCommand).toBe(true); 191 | }); 192 | }); 193 | 194 | it("should execute the interceptor after rebuild commangular interceptors", function() { 195 | 196 | provider.mapTo('AspectTestEvent').asSequence().add('Command1'); 197 | commangular.build(); 198 | dispatch({event:'AspectTestEvent'},function() { 199 | 200 | expect(commandExecutedAfter).toBe(true); 201 | expect(interceptorExecutedBefore).toBe(true); 202 | }); 203 | }); 204 | }); -------------------------------------------------------------------------------- /test/command-aspects/before-interception-testing.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Before interception testing", function() { 4 | 5 | var provider; 6 | var interceptorExecutedBefore = false; 7 | var commandExecutedAfter = false; 8 | 9 | beforeEach(function() { 10 | 11 | commangular.reset(); 12 | 13 | commangular.aspect('@Before(/com\.test1.*/)', function(){ 14 | 15 | return { 16 | 17 | execute : function() { 18 | 19 | interceptorExecutedBefore = true; 20 | } 21 | } 22 | 23 | }); 24 | 25 | commangular.aspect('@Before(/com\.test2.*/)', function(processor){ 26 | 27 | return { 28 | 29 | execute : function() { 30 | 31 | expect(processor.getData('username')).toBe('userName'); 32 | expect(processor.getData('password')).toBe('fuckingpassword'); 33 | processor.setData('username','monkey'); 34 | processor.setData('password','password'); 35 | } 36 | } 37 | 38 | }); 39 | 40 | commangular.aspect('@Before(/com\.test3.*/)', function(processor){ 41 | 42 | return { 43 | 44 | execute:function() { 45 | 46 | processor.cancel(); 47 | } 48 | } 49 | }); 50 | 51 | commangular.create('com.test1.Command1',function(){ 52 | 53 | return { 54 | 55 | execute : function() { 56 | 57 | if(interceptorExecutedBefore) { 58 | 59 | commandExecutedAfter = true; 60 | } 61 | } 62 | }; 63 | }); 64 | 65 | commangular.create('com.test2.Command2',function(username,password){ 66 | 67 | return { 68 | 69 | execute : function() { 70 | 71 | expect(username).toBe('monkey'); 72 | expect(password).toBe('password'); 73 | } 74 | }; 75 | }); 76 | 77 | commangular.create('com.test3.Command3',function(){ 78 | 79 | return { 80 | 81 | execute : function() { 82 | 83 | expect(false).toBe(true); // this shouldn't be executed 84 | } 85 | }; 86 | }); 87 | 88 | }); 89 | 90 | beforeEach(function() { 91 | 92 | module('commangular', function($commangularProvider) { 93 | provider = $commangularProvider; 94 | }); 95 | inject(); 96 | }); 97 | 98 | it("provider should be defined", function() { 99 | 100 | expect(provider).toBeDefined(); 101 | }); 102 | 103 | it("should execute the interceptor before the command", function() { 104 | 105 | provider.mapTo('BeforeTestEvent').asSequence().add('com.test1.Command1'); 106 | dispatch({event:'BeforeTestEvent'},function(){ 107 | 108 | expect(interceptorExecutedBefore).toBe(true); 109 | expect(commandExecutedAfter).toBe(true); 110 | }); 111 | }); 112 | 113 | it("The interceptor should update the data passed to the command", function() { 114 | 115 | provider.mapTo('BeforeTestEvent').asSequence().add('com.test2.Command2'); 116 | dispatch({event:'BeforeTestEvent',data:{username:'userName',password:'fuckingpassword'}},function(){ 117 | 118 | expect(interceptorExecutedBefore).toBe(true); 119 | expect(commandExecutedAfter).toBe(true); 120 | }); 121 | }); 122 | 123 | it("The command execution has to be canceled", function() { 124 | 125 | var complete = false; 126 | provider.mapTo('BeforeTestEvent').asSequence().add('com.test3.Command3'); 127 | dispatch({event:'BeforeTestEvent'},function(){ 128 | 129 | expect(interceptorExecutedBefore).toBe(true); 130 | expect(commandExecutedAfter).toBe(true); 131 | }); 132 | }); 133 | }); -------------------------------------------------------------------------------- /test/command-aspects/multiple-after-execution-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Multiple AfterExecution execution testing", function() { 4 | 5 | var provider; 6 | var interceptor1Executed = false; 7 | var interceptor2Executed = false; 8 | var commandExecuted = false; 9 | 10 | beforeEach(function() { 11 | 12 | commangular.reset(); 13 | 14 | commangular.aspect('@AfterExecution(/com\.test1.*/)', function(){ 15 | 16 | return { 17 | 18 | execute : function () { 19 | 20 | expect(commandExecuted).toBe(true); 21 | interceptor1Executed = true; 22 | } 23 | } 24 | 25 | },1); 26 | 27 | commangular.aspect('@AfterExecution(/com\.test1.*/)', function(lastResult){ 28 | 29 | return { 30 | 31 | execute : function() { 32 | 33 | expect(interceptor1Executed).toBe(true);; 34 | expect(lastResult).toBe(50); 35 | interceptor2Executed = true; 36 | } 37 | } 38 | 39 | },2); 40 | 41 | commangular.create('com.test1.Command1',function(){ 42 | 43 | return { 44 | 45 | execute : function() { 46 | 47 | commandExecuted = true; 48 | return 50; 49 | } 50 | }; 51 | }); 52 | }); 53 | 54 | beforeEach(function() { 55 | 56 | module('commangular', function($commangularProvider) { 57 | provider = $commangularProvider; 58 | }); 59 | inject(); 60 | }); 61 | 62 | it("provider should be defined", function() { 63 | 64 | expect(provider).toBeDefined(); 65 | }); 66 | 67 | it("should execute the interceptor before the command", function() { 68 | 69 | provider.mapTo('BeforeTestEvent').asSequence().add('com.test1.Command1'); 70 | dispatch({event:'BeforeTestEvent'},function(){ 71 | 72 | expect(interceptor1Executed).toBe(true); 73 | expect(commandExecuted).toBe(true); 74 | }); 75 | }); 76 | }); -------------------------------------------------------------------------------- /test/command-aspects/multiple-afterthrowing-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Multipe @AfterThrowing interception test", function() { 4 | 5 | var provider; 6 | var interceptor1Executed = false; 7 | var interceptor2Executed = false; 8 | var commandExecuted = false; 9 | 10 | beforeEach(function() { 11 | 12 | commangular.reset(); 13 | 14 | commangular.aspect('@AfterThrowing(/com\.test1.*/)', function(processor,lastError){ 15 | 16 | return { 17 | 18 | execute:function() { 19 | 20 | expect(interceptor1Executed).toBe(true); 21 | expect(commandExecuted).toBe(false) 22 | expect(lastError.message).toBe('Error from command'); 23 | interceptor2Executed = true; 24 | } 25 | } 26 | 27 | },2); 28 | 29 | commangular.aspect('@AfterThrowing(/com\.test1.*/)', function(processor,lastError){ 30 | 31 | return { 32 | 33 | execute:function() { 34 | 35 | expect(commandExecuted).toBe(false) 36 | expect(lastError.message).toBe('Error from command'); 37 | interceptor1Executed = true; 38 | } 39 | } 40 | 41 | },1); 42 | 43 | commangular.create('com.test1.Command1',function(){ 44 | 45 | return { 46 | 47 | execute : function() { 48 | 49 | throw new Error('Error from command'); 50 | commandExecuted = true; 51 | } 52 | }; 53 | }); 54 | 55 | }); 56 | 57 | beforeEach(function() { 58 | 59 | module('commangular', function($commangularProvider) { 60 | provider = $commangularProvider; 61 | }); 62 | inject(); 63 | }); 64 | 65 | it("provider should be defined", function() { 66 | 67 | expect(provider).toBeDefined(); 68 | }); 69 | 70 | it("should execute the commands and intercept exceptions", function() { 71 | 72 | provider.mapTo('AroundTestEvent').asSequence().add('com.test1.Command1'); 73 | dispatch({event:'AroundTestEvent'},function(){ 74 | 75 | expect(interceptor1Executed).toBe(true); 76 | expect(interceptor2Executed).toBe(true); 77 | expect(commandExecuted).toBe(false); 78 | }); 79 | }); 80 | }); -------------------------------------------------------------------------------- /test/command-aspects/multiple-around-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Multiple @Around execution testing", function() { 4 | 5 | var provider; 6 | var interceptor1Executed = false; 7 | var interceptor2Executed = false; 8 | var commandExecuted = false; 9 | 10 | beforeEach(function() { 11 | 12 | commangular.reset(); 13 | 14 | commangular.aspect('@Around(/com\.test1.*/)', function(processor){ 15 | 16 | return { 17 | 18 | execute:function() { 19 | 20 | interceptor1Executed = true; 21 | expect(commandExecuted).toBe(false) 22 | expect(interceptor2Executed).toBe(false); 23 | processor.invoke(); 24 | expect(commandExecuted).toBe(true); 25 | expect(interceptor2Executed).toBe(true); 26 | 27 | } 28 | } 29 | 30 | },1); 31 | 32 | commangular.aspect('@Around(/com\.test1.*/)', function(processor){ 33 | 34 | return { 35 | 36 | execute:function() { 37 | 38 | expect(interceptor1Executed).toBe(true); 39 | expect(commandExecuted).toBe(false); 40 | processor.invoke(); 41 | expect(commandExecuted).toBe(true); 42 | interceptor2Executed = true; 43 | } 44 | } 45 | 46 | },2); 47 | 48 | commangular.create('com.test1.Command1',function(){ 49 | 50 | return { 51 | 52 | execute : function() { 53 | 54 | commandExecuted = true; 55 | } 56 | }; 57 | }); 58 | }); 59 | 60 | beforeEach(function() { 61 | 62 | module('commangular', function($commangularProvider) { 63 | provider = $commangularProvider; 64 | }); 65 | inject(); 66 | }); 67 | 68 | it("provider should be defined", function() { 69 | 70 | expect(provider).toBeDefined(); 71 | }); 72 | 73 | it("should execute intercepted around by two interceptors", function() { 74 | 75 | provider.mapTo('AroundTestEvent').asSequence().add('com.test1.Command1'); 76 | dispatch({event:'AroundTestEvent'},function(){ 77 | 78 | expect(interceptor1Executed).toBe(true); 79 | expect(commandExecuted).toBe(true); 80 | expect(interceptor2Executed).toBe(true); 81 | }); 82 | }); 83 | }); -------------------------------------------------------------------------------- /test/command-aspects/multiple-around-with-return-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Multiple @Around with return execution testing", function() { 4 | 5 | var provider; 6 | var timeout; 7 | var interceptor1Executed = false; 8 | var interceptor2Executed = false; 9 | var commandExecuted = false; 10 | 11 | beforeEach(function() { 12 | 13 | commangular.reset(); 14 | 15 | commangular.aspect('@Around(/com\.test1\.Command1/)', function(processor){ 16 | 17 | return { 18 | 19 | execute:function() { 20 | 21 | interceptor1Executed = true; 22 | expect(commandExecuted).toBe(false) 23 | expect(interceptor2Executed).toBe(false); 24 | var promise = processor.invoke().then(function(result){ 25 | expect(result).toBe(25); 26 | expect(commandExecuted).toBe(true); 27 | expect(interceptor2Executed).toBe(true); 28 | return 10; 29 | }); 30 | expect(commandExecuted).toBe(true) 31 | expect(interceptor2Executed).toBe(false); 32 | return promise; 33 | } 34 | } 35 | },1); 36 | 37 | commangular.aspect('@Around(/com\.test1\.Command1/)', function(processor,$timeout){ 38 | 39 | return { 40 | 41 | execute:function() { 42 | 43 | expect(interceptor1Executed).toBe(true); 44 | expect(commandExecuted).toBe(false); 45 | return processor.invoke().then(function(result){ 46 | 47 | expect(result).toBe(50); 48 | expect(commandExecuted).toBe(true); 49 | interceptor2Executed = true; 50 | return 25; 51 | }); 52 | } 53 | } 54 | },2); 55 | 56 | commangular.create('com.test1.Command1',function($timeout){ 57 | 58 | return { 59 | 60 | execute : function() { 61 | 62 | commandExecuted = true; 63 | return 50; 64 | } 65 | }; 66 | },{resultKey:'result1'}); 67 | 68 | commangular.create('com.test1.Command2',function(result1){ 69 | 70 | return { 71 | 72 | execute : function() { 73 | 74 | expect(result1).toBe(10); 75 | } 76 | }; 77 | }); 78 | }); 79 | 80 | beforeEach(function() { 81 | 82 | module('commangular', function($commangularProvider) { 83 | provider = $commangularProvider; 84 | }); 85 | inject(); 86 | }); 87 | 88 | it("provider should be defined", function() { 89 | 90 | expect(provider).toBeDefined(); 91 | }); 92 | 93 | it("should execute the interceptor before the command", function() { 94 | 95 | provider.mapTo('AroundTestEvent').asSequence().add('com.test1.Command1').add('com.test1.Command2'); 96 | dispatch({event:'AroundTestEvent'},function(){ 97 | 98 | expect(interceptor1Executed).toBe(true); 99 | expect(commandExecuted).toBe(true); 100 | expect(interceptor2Executed).toBe(true); 101 | }); 102 | }); 103 | }); -------------------------------------------------------------------------------- /test/command-aspects/multiple-before-cancelation-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Multiple @Before execution testing", function() { 4 | 5 | var provider; 6 | var interceptor1Executed = false; 7 | var interceptor2Executed = false; 8 | var commandExecutedAfter = false; 9 | 10 | beforeEach(function() { 11 | 12 | commangular.reset(); 13 | 14 | commangular.aspect('@Before(/com\.test1.*/)', function(processor){ 15 | 16 | return { 17 | 18 | execute : function() { 19 | 20 | interceptor1Executed = true; 21 | processor.cancel('Cancelation'); 22 | } 23 | } 24 | 25 | },1); 26 | 27 | commangular.aspect('@Before(/com\.test1.*/)', function(processor){ 28 | 29 | return { 30 | 31 | execute : function() { 32 | 33 | expect(false).toBe(true); //Error if this is executed 34 | 35 | } 36 | } 37 | 38 | },2); 39 | 40 | 41 | commangular.create('com.test1.Command1',function(){ 42 | 43 | return { 44 | 45 | execute : function() { 46 | 47 | expect(false).toBe(true); //Error if this is executed 48 | 49 | } 50 | }; 51 | }); 52 | 53 | commangular.create('com.test2.Command2',function(){ 54 | 55 | return { 56 | 57 | execute : function() { 58 | 59 | expect(interceptor1Executed).toBe(true); 60 | expect(interceptor2Executed).toBe(false); 61 | expect(commandExecutedAfter).toBe(false); 62 | 63 | } 64 | }; 65 | }); 66 | 67 | }); 68 | 69 | beforeEach(function() { 70 | 71 | module('commangular', function($commangularProvider) { 72 | provider = $commangularProvider; 73 | }); 74 | inject(); 75 | }); 76 | 77 | it("provider should be defined", function() { 78 | 79 | expect(provider).toBeDefined(); 80 | }); 81 | 82 | it("should execute the interceptor and cancel the command group", function() { 83 | 84 | provider.mapTo('BeforeTestEvent').asSequence().add('com.test1.Command1').add('com.test2.Command2'); 85 | dispatch({event:'BeforeTestEvent'},function(){ 86 | 87 | expect(interceptor1Executed).toBe(true); 88 | expect(interceptor2Executed).toBe(false); 89 | expect(commandExecutedAfter).toBe(false); 90 | }); 91 | }); 92 | }); -------------------------------------------------------------------------------- /test/command-aspects/multiple-before-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Multiple @Before execution testing", function() { 4 | 5 | var provider; 6 | var interceptor1Executed = false; 7 | var interceptor2Executed = false; 8 | var commandExecutedAfter = false; 9 | 10 | beforeEach(function() { 11 | 12 | commangular.reset(); 13 | 14 | commangular.aspect('@Before(/com\.test1.*/)', function(){ 15 | 16 | return { 17 | 18 | execute : function() { 19 | 20 | interceptor1Executed = true; 21 | } 22 | } 23 | 24 | },1); 25 | 26 | commangular.aspect('@Before(/com\.test1.*/)', function(processor){ 27 | 28 | return { 29 | 30 | execute : function() { 31 | 32 | expect(interceptor1Executed).toBe(true); 33 | interceptor2Executed = true; 34 | } 35 | } 36 | 37 | },2); 38 | 39 | 40 | commangular.create('com.test1.Command1',function(){ 41 | 42 | return { 43 | 44 | execute : function() { 45 | 46 | expect(interceptor1Executed).toBe(true); 47 | expect(interceptor2Executed).toBe(true); 48 | commandExecutedAfter = true; 49 | 50 | } 51 | }; 52 | }); 53 | 54 | commangular.create('com.test2.Command2',function(){ 55 | 56 | return { 57 | 58 | execute : function() { 59 | 60 | expect(interceptor1Executed).toBe(true); 61 | expect(interceptor2Executed).toBe(true); 62 | expect(commandExecutedAfter).toBe(true); 63 | 64 | } 65 | }; 66 | }); 67 | 68 | }); 69 | 70 | beforeEach(function() { 71 | 72 | module('commangular', function($commangularProvider) { 73 | provider = $commangularProvider; 74 | }); 75 | inject(); 76 | }); 77 | 78 | it("provider should be defined", function() { 79 | 80 | expect(provider).toBeDefined(); 81 | }); 82 | 83 | it("should execute the interceptor before the command", function() { 84 | 85 | provider.mapTo('BeforeTestEvent').asSequence().add('com.test1.Command1').add('com.test2.Command2'); 86 | dispatch({event:'BeforeTestEvent'},function(){ 87 | 88 | expect(interceptor1Executed).toBe(true); 89 | expect(interceptor2Executed).toBe(true); 90 | expect(commandExecutedAfter).toBe(true); 91 | }); 92 | }); 93 | }); -------------------------------------------------------------------------------- /test/command-aspects/not-afterthrow-not-onError-on-cancelation-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Aspect execution testing", function() { 4 | 5 | var provider; 6 | var interceptorExecuted = false; 7 | var afterThrowingExecuted = false; 8 | var onErrorExecuted = false; 9 | var commandExecuted = false; 10 | 11 | beforeEach(function() { 12 | 13 | commangular.reset(); 14 | 15 | 16 | commangular.aspect('@AfterThrowing(/com\.test1.*/)', function(){ 17 | 18 | return { 19 | 20 | execute : function() { 21 | 22 | afterThrowingExecuted = true; 23 | } 24 | } 25 | 26 | }); 27 | 28 | commangular.aspect('@Before(/com\.test1.*/)', function(processor){ 29 | 30 | return { 31 | 32 | execute : function() { 33 | 34 | processor.cancel('Canceling'); 35 | interceptorExecuted = true; 36 | } 37 | } 38 | 39 | }); 40 | 41 | 42 | commangular.command('com.test1.Command1',function(){ 43 | 44 | return { 45 | 46 | execute : function() { 47 | 48 | commandExecuted = true; 49 | 50 | }, 51 | onError : function() { 52 | 53 | onErrorExecuted = true; 54 | } 55 | }; 56 | }); 57 | 58 | }); 59 | 60 | beforeEach(function() { 61 | 62 | module('commangular', function($commangularProvider) { 63 | provider = $commangularProvider; 64 | }); 65 | inject(); 66 | }); 67 | 68 | it("provider should be defined", function() { 69 | 70 | expect(provider).toBeDefined(); 71 | }); 72 | 73 | it("should cancel execution and AfterThrowing should not be executed", function() { 74 | 75 | provider.mapTo('BeforeTestEvent').asSequence().add('com.test1.Command1'); 76 | dispatch({event:'BeforeTestEvent'},function(){ 77 | 78 | expect(interceptorExecuted).toBe(true); 79 | expect(commandExecuted).toBe(false); 80 | expect(afterThrowingExecuted).toBe(false); 81 | }); 82 | }); 83 | }); -------------------------------------------------------------------------------- /test/command-aspects/throw-exception-on-afterexecution-interceptor-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Throw exception on after interception testing", function() { 4 | 5 | var provider; 6 | var interceptorExecutedBefore = false; 7 | var afterThrowingExecuted = false; 8 | var commandExecutedBefore = false; 9 | 10 | beforeEach(function() { 11 | 12 | commangular.reset(); 13 | 14 | commangular.aspect('@AfterExecution(/com\.test1.*/)', function(){ 15 | 16 | return { 17 | 18 | execute : function() { 19 | 20 | throw new Error('This is an error'); 21 | interceptorExecutedBefore = true; 22 | } 23 | } 24 | 25 | }); 26 | 27 | commangular.aspect('@AfterThrowing(/com\.test1.*/)', function(){ 28 | 29 | return { 30 | 31 | execute : function() { 32 | 33 | afterThrowingExecuted = true; 34 | } 35 | } 36 | 37 | }); 38 | 39 | 40 | commangular.create('com.test1.Command1',function(){ 41 | 42 | return { 43 | 44 | execute : function() { 45 | 46 | commandExecutedBefore = true; 47 | 48 | } 49 | }; 50 | }); 51 | 52 | }); 53 | 54 | beforeEach(function() { 55 | 56 | module('commangular', function($commangularProvider) { 57 | provider = $commangularProvider; 58 | }); 59 | inject(); 60 | }); 61 | 62 | it("provider should be defined", function() { 63 | 64 | expect(provider).toBeDefined(); 65 | }); 66 | 67 | it("should execute the command and AfterThrowing should be executed", function() { 68 | 69 | provider.mapTo('BeforeTestEvent').asSequence().add('com.test1.Command1'); 70 | dispatch({event:'BeforeTestEvent'},function(){ 71 | 72 | expect(interceptorExecutedBefore).toBe(false); 73 | expect(commandExecutedBefore).toBe(true); 74 | expect(afterThrowingExecuted).toBe(true); 75 | }); 76 | }); 77 | }); -------------------------------------------------------------------------------- /test/command-aspects/throw-exception-on-around-interceptor-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Throw exception on around interceptor testing", function() { 4 | 5 | var provider; 6 | var interceptorExecutedBefore = false; 7 | var afterThrowingExecuted = false; 8 | var commandExecutedAfter = false; 9 | 10 | beforeEach(function() { 11 | 12 | commangular.reset(); 13 | 14 | commangular.aspect('@Around(/com\.test1.*/)', function(){ 15 | 16 | return { 17 | 18 | execute : function() { 19 | 20 | throw new Error('This is an error'); 21 | processor.invoke(); 22 | interceptorExecutedBefore = true; 23 | } 24 | } 25 | 26 | }); 27 | 28 | commangular.aspect('@AfterThrowing(/com\.test1.*/)', function(){ 29 | 30 | return { 31 | 32 | execute : function() { 33 | 34 | afterThrowingExecuted = true; 35 | } 36 | } 37 | 38 | }); 39 | 40 | 41 | commangular.create('com.test1.Command1',function(){ 42 | 43 | return { 44 | 45 | execute : function() { 46 | 47 | if(interceptorExecutedBefore) { 48 | 49 | commandExecutedAfter = true; 50 | } 51 | } 52 | }; 53 | }); 54 | 55 | }); 56 | 57 | beforeEach(function() { 58 | 59 | module('commangular', function($commangularProvider) { 60 | provider = $commangularProvider; 61 | }); 62 | inject(); 63 | }); 64 | 65 | it("provider should be defined", function() { 66 | 67 | expect(provider).toBeDefined(); 68 | }); 69 | 70 | it("should execute the interceptor and AfterThrowing should be executed", function() { 71 | 72 | provider.mapTo('BeforeTestEvent').asSequence().add('com.test1.Command1'); 73 | dispatch({event:'BeforeTestEvent'},function(){ 74 | 75 | expect(interceptorExecutedBefore).toBe(false); 76 | expect(commandExecutedAfter).toBe(false); 77 | expect(afterThrowingExecuted).toBe(true); 78 | }); 79 | }); 80 | }); -------------------------------------------------------------------------------- /test/command-aspects/throw-exception-on-before-interceptor-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Throw exception on before interceptor testing", function() { 4 | 5 | var provider; 6 | var interceptorExecutedBefore = false; 7 | var afterThrowingExecuted = false; 8 | var commandExecutedAfter = false; 9 | 10 | beforeEach(function() { 11 | 12 | commangular.reset(); 13 | 14 | commangular.aspect('@Before(/com\.test1.*/)', function(){ 15 | 16 | return { 17 | 18 | execute : function() { 19 | 20 | throw new Error('This is an error'); 21 | interceptorExecutedBefore = true; 22 | } 23 | } 24 | 25 | }); 26 | 27 | commangular.aspect('@AfterThrowing(/com\.test1.*/)', function(){ 28 | 29 | return { 30 | 31 | execute : function() { 32 | 33 | afterThrowingExecuted = true; 34 | } 35 | } 36 | 37 | }); 38 | 39 | 40 | commangular.create('com.test1.Command1',function(){ 41 | 42 | return { 43 | 44 | execute : function() { 45 | 46 | if(interceptorExecutedBefore) { 47 | 48 | commandExecutedAfter = true; 49 | } 50 | } 51 | }; 52 | }); 53 | 54 | }); 55 | 56 | beforeEach(function() { 57 | 58 | module('commangular', function($commangularProvider) { 59 | provider = $commangularProvider; 60 | }); 61 | inject(); 62 | }); 63 | 64 | it("provider should be defined", function() { 65 | 66 | expect(provider).toBeDefined(); 67 | }); 68 | 69 | it("should execute the interceptor and AfterThrowing should be executed", function() { 70 | 71 | provider.mapTo('BeforeTestEvent').asSequence().add('com.test1.Command1'); 72 | dispatch({event:'BeforeTestEvent'},function(){ 73 | 74 | expect(interceptorExecutedBefore).toBe(false); 75 | expect(commandExecutedAfter).toBe(false); 76 | expect(afterThrowingExecuted).toBe(true); 77 | }); 78 | }); 79 | }); -------------------------------------------------------------------------------- /test/commangular-mock/test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Testing decorator", function() { 4 | 5 | var $timeout = null; 6 | var provider; 7 | 8 | beforeEach(function() { 9 | 10 | commangular.reset(); 11 | 12 | commangular.command('Command1',function(lastResult,$timeout){ 13 | 14 | return { 15 | 16 | execute: function() { 17 | 18 | return $timeout(function(){ 19 | 20 | return lastResult; 21 | },2000); 22 | } 23 | }; 24 | 25 | },{resultKey:'mandril'}); 26 | 27 | }); 28 | 29 | 30 | beforeEach(function() { 31 | 32 | module('commangular', function($commangularProvider) { 33 | provider = $commangularProvider; 34 | }); 35 | inject(function(_$timeout_){ 36 | 37 | $timeout = _$timeout_; 38 | }); 39 | 40 | }); 41 | 42 | it("provider should be defined", function() { 43 | 44 | expect(provider).toBeDefined(); 45 | }); 46 | 47 | it("provider should be defined", function() { 48 | 49 | dispatch({command:'Command1',data:{lastResult:35}},function(exc){ 50 | 51 | /*expect(exc.dataPassed('lastResult')).toBe(35); 52 | expect(exc.canceled()).toBeFalsy(); 53 | expect(exc.resultKey('mandril')).toBe(35);*/ 54 | }); 55 | $timeout.flush(); 56 | }); 57 | 58 | }); -------------------------------------------------------------------------------- /test/domain/model-service-test.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | angular.module('commangular') 4 | .service('UserDomainModel',function() { 5 | 6 | return { 7 | 8 | name:'userTest', 9 | surname:'surnameTest', 10 | username:'monkey' 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /test/event-aspects/after-event-aspect-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("After event aspect execution testing", function() { 4 | 5 | var provider; 6 | var afterInterceptorExecuted = false; 7 | var afterInterceptorExecuted2 = false; 8 | var afterInterceptorExecuted3 = false; 9 | var commandExecuted = false; 10 | var commandExecuted2 = false; 11 | 12 | 13 | beforeEach(function() { 14 | 15 | commangular.reset(); 16 | commangular.eventAspect('@After(/TestEvent/)', function(){ 17 | 18 | return { 19 | 20 | execute:function () { 21 | 22 | expect(commandExecuted).toBe(true); 23 | afterInterceptorExecuted = true; 24 | } 25 | } 26 | 27 | }); 28 | commangular.eventAspect('@After(/TestEvent[0-4]/)', function(){ 29 | 30 | return { 31 | 32 | execute : function() { 33 | 34 | afterInterceptorExecuted2 = true; 35 | } 36 | } 37 | },1); 38 | 39 | commangular.eventAspect('@After(/TestEvent2/)', function(){ 40 | 41 | return { 42 | 43 | execute : function() { 44 | 45 | expect(commandExecuted2).toBe(true); 46 | expect(afterInterceptorExecuted2).toBe(true); 47 | afterInterceptorExecuted3 = true; 48 | } 49 | } 50 | },2); 51 | 52 | commangular.create('Command1',function(){ 53 | 54 | return { 55 | 56 | execute : function() { 57 | 58 | commandExecuted = true; 59 | } 60 | }; 61 | }); 62 | 63 | commangular.create('Command2',function(){ 64 | 65 | return { 66 | 67 | execute : function() { 68 | 69 | commandExecuted2 = true; 70 | } 71 | }; 72 | }); 73 | 74 | }); 75 | 76 | beforeEach(function() { 77 | 78 | module('commangular', function($commangularProvider) { 79 | 80 | provider = $commangularProvider; 81 | provider.mapTo('TestEvent').asSequence().add('Command1'); 82 | provider.mapTo('TestEvent2').asSequence().add('Command2'); 83 | }); 84 | inject(); 85 | }); 86 | 87 | it("should execute the interceptor after the command", function() { 88 | 89 | 90 | dispatch({event:'TestEvent'},function() { 91 | 92 | expect(commandExecuted).toBe(true); 93 | expect(afterInterceptorExecuted).toBe(true); 94 | }); 95 | }); 96 | 97 | it("should execute interceptor after the command", function() { 98 | 99 | 100 | dispatch({event:'TestEvent2'},function() { 101 | 102 | expect(commandExecuted2).toBe(true); 103 | expect(afterInterceptorExecuted2).toBe(true); 104 | expect(afterInterceptorExecuted3).toBe(true); 105 | }); 106 | }); 107 | }); -------------------------------------------------------------------------------- /test/event-aspects/before-event-aspect-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Before event aspect execution testing", function() { 4 | 5 | var provider; 6 | var beforeInterceptorExecuted = false; 7 | var beforeInterceptorExecuted2 = false; 8 | var beforeInterceptorExecuted3 = false; 9 | var commandExecuted = false; 10 | 11 | 12 | beforeEach(function() { 13 | 14 | commangular.reset(); 15 | commangular.eventAspect('@Before(/TestEvent/)', function(){ 16 | 17 | return { 18 | 19 | execute:function () { 20 | 21 | beforeInterceptorExecuted = true; 22 | } 23 | } 24 | 25 | }); 26 | commangular.eventAspect('@Before(/TestEvent[0-9]/)', function(){ 27 | 28 | return { 29 | 30 | execute : function() { 31 | 32 | beforeInterceptorExecuted2 = true; 33 | } 34 | } 35 | },1); 36 | 37 | commangular.eventAspect('@Before(/TestEvent2/)', function(){ 38 | 39 | return { 40 | 41 | execute : function() { 42 | 43 | expect(beforeInterceptorExecuted2).toBe(true); 44 | beforeInterceptorExecuted3 = true; 45 | } 46 | } 47 | },2); 48 | 49 | commangular.create('Command1',function(){ 50 | 51 | return { 52 | 53 | execute : function() { 54 | 55 | expect(beforeInterceptorExecuted).toBe(true); 56 | commandExecuted = true; 57 | } 58 | }; 59 | }); 60 | 61 | commangular.create('Command2',function(){ 62 | 63 | return { 64 | 65 | execute : function() { 66 | 67 | expect(beforeInterceptorExecuted2).toBe(true); 68 | expect(beforeInterceptorExecuted3).toBe(true); 69 | commandExecuted = true; 70 | } 71 | }; 72 | }); 73 | 74 | }); 75 | 76 | beforeEach(function() { 77 | 78 | module('commangular', function($commangularProvider) { 79 | 80 | provider = $commangularProvider; 81 | provider.mapTo('TestEvent').asSequence().add('Command1'); 82 | provider.mapTo('TestEvent2').asSequence().add('Command2'); 83 | }); 84 | inject(); 85 | }); 86 | 87 | it("provider should be defined", function() { 88 | 89 | expect(provider).toBeDefined(); 90 | }); 91 | 92 | it("should execute the interceptor before the command", function() { 93 | 94 | dispatch({event:'TestEvent'},function() { 95 | 96 | expect(commandExecuted).toBe(true); 97 | expect(beforeInterceptorExecuted).toBe(true); 98 | }); 99 | 100 | }); 101 | 102 | it("should execute the interceptors before the command", function() { 103 | 104 | dispatch({event:'TestEvent2'},function() { 105 | 106 | expect(commandExecuted).toBe(true); 107 | expect(beforeInterceptorExecuted2).toBe(true); 108 | expect(beforeInterceptorExecuted3).toBe(true); 109 | }); 110 | }); 111 | 112 | }); -------------------------------------------------------------------------------- /test/event-aspects/event-aspect-execution-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("EventAspect execution testing", function() { 4 | 5 | var provider; 6 | 7 | var beforeInterceptorExecuted = false; 8 | var commandExecuted = false; 9 | var afterInterceptorExecuted = false; 10 | var afterThrowingInterceptorExecuted = false; 11 | 12 | beforeEach(function() { 13 | 14 | commangular.reset(); 15 | commangular.eventAspect('@Before(/TestEvent/)', function(){ 16 | 17 | return { 18 | 19 | execute:function () { 20 | 21 | beforeInterceptorExecuted = true; 22 | } 23 | } 24 | 25 | }); 26 | commangular.eventAspect('@After(/TestEvent/)', function(){ 27 | 28 | return { 29 | 30 | execute : function() { 31 | 32 | expect(beforeInterceptorExecuted).toBe(true); 33 | expect(commandExecuted).toBe(true); 34 | afterInterceptorExecuted = true; 35 | } 36 | } 37 | }); 38 | 39 | commangular.eventAspect('@AfterThrowing(/TestEvent2/)', function(){ 40 | 41 | return { 42 | 43 | execute : function() { 44 | 45 | afterThrowingInterceptorExecuted = true; 46 | } 47 | } 48 | }); 49 | 50 | commangular.create('Command1',function(){ 51 | 52 | return { 53 | 54 | execute : function() { 55 | 56 | expect(beforeInterceptorExecuted).toBe(true); 57 | commandExecuted = true; 58 | } 59 | }; 60 | }); 61 | 62 | commangular.create('Command2',function(){ 63 | 64 | return { 65 | 66 | execute : function() { 67 | 68 | throw new Error('Event aspect Error'); 69 | } 70 | }; 71 | }); 72 | 73 | }); 74 | 75 | beforeEach(function() { 76 | 77 | module('commangular', function($commangularProvider) { 78 | 79 | provider = $commangularProvider; 80 | provider.mapTo('TestEvent').asSequence().add('Command1'); 81 | provider.mapTo('TestEvent2').asSequence().add('Command2'); 82 | }); 83 | inject(); 84 | }); 85 | 86 | it("should execute the interceptor before the command", function() { 87 | 88 | dispatch({event:'TestEvent'},function() { 89 | 90 | expect(commandExecuted).toBe(true); 91 | expect(beforeInterceptorExecuted).toBe(true); 92 | expect(afterInterceptorExecuted).toBe(true); 93 | }); 94 | }); 95 | 96 | it("should execute the interceptor before the command", function() { 97 | 98 | dispatch({event:'TestEvent2'},function() { 99 | 100 | expect(afterThrowingInterceptorExecuted).toBe(true); 101 | }); 102 | }); 103 | 104 | }); -------------------------------------------------------------------------------- /test/groups/command-execution-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Command execution testing", function() { 4 | 5 | var provider; 6 | var $injector; 7 | 8 | beforeEach(function() { 9 | 10 | commangular.reset(); 11 | commangular.create('Command1', function() { 12 | 13 | return { 14 | 15 | execute: function($log) { 16 | 17 | $log.log('logging from commandObject'); 18 | } 19 | }; 20 | }); 21 | }); 22 | 23 | beforeEach(function() { 24 | 25 | module('commangular', function($commangularProvider) { 26 | 27 | provider = $commangularProvider; 28 | 29 | }); 30 | inject(function(_$injector_){ 31 | 32 | $injector = _$injector_; 33 | }); 34 | }); 35 | 36 | it('provider should be defined', function() { 37 | 38 | expect(provider).toBeDefined(); 39 | }); 40 | 41 | it('injector should be defined', function() { 42 | 43 | expect($injector).toBeDefined(); 44 | }); 45 | 46 | //TODO: Use commangular mocks 47 | /* 48 | it('command should be executed', function() { 49 | 50 | provider.mapTo('TestEvent').asSequence().add('Command1'); 51 | spyOn($injector, 'instantiate').andCallThrough(); 52 | spyOn($injector, 'invoke').andCallThrough(); 53 | dispatch({event:'TestEvent'},function(){ 54 | 55 | expect($injector.instantiate).toHaveBeenCalled(); 56 | expect($injector.invoke).toHaveBeenCalled(); 57 | }); 58 | }); 59 | 60 | it('command.execute method should be called', function() { 61 | 62 | var command = {execute: function(){}}; 63 | provider.mapTo('TestEvent').asSequence().add('Command1'); 64 | spyOn($injector, 'instantiate').andReturn(command); 65 | spyOn(command, 'execute').andCallThrough(); 66 | dispatch({event:'TestEvent'},function(){ 67 | 68 | expect(command.execute).toHaveBeenCalled(); 69 | }); 70 | });*/ 71 | }); -------------------------------------------------------------------------------- /test/groups/command-flow-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Command Flow execution testing", function() { 4 | 5 | var provider; 6 | var eventName = 'TestEvent'; 7 | var command2Executed = false; 8 | 9 | beforeEach(function() { 10 | 11 | command2Executed = false; 12 | commangular.reset(); 13 | commangular.create('Command2', function() { 14 | 15 | return { 16 | 17 | execute: function() { 18 | 19 | command2Executed = true; 20 | } 21 | }; 22 | }); 23 | }); 24 | 25 | beforeEach(function() { 26 | 27 | module('commangular', function($commangularProvider) { 28 | 29 | provider = $commangularProvider; 30 | 31 | }); 32 | inject(); 33 | }); 34 | 35 | it('provider should be defined', function() { 36 | 37 | expect(provider).toBeDefined(); 38 | }); 39 | 40 | it('command 2 should be executed', function() { 41 | 42 | 43 | commangular.create('Command1', function() { 44 | 45 | return { 46 | 47 | execute: function() { 48 | 49 | return true; 50 | } 51 | }; 52 | },{resultKey:'result1'}); 53 | 54 | 55 | var commandComplete = false; 56 | provider.mapTo(eventName).asSequence() 57 | .add('Command1') 58 | .add(provider.asFlow() 59 | .link('result1 == true').to('Command2')); 60 | 61 | dispatch({event:eventName},function() { 62 | 63 | expect(command2Executed).toBe(true); 64 | }); 65 | }); 66 | 67 | it('command 2 should not be executed', function() { 68 | 69 | 70 | commangular.create('Command1', function() { 71 | 72 | return { 73 | 74 | execute: function() { 75 | 76 | return false; 77 | } 78 | }; 79 | },{resultKey:'result1'}); 80 | 81 | 82 | var commandComplete = false; 83 | provider.mapTo(eventName).asSequence() 84 | .add('Command1') 85 | .add(provider.asFlow() 86 | .link('result1 == true').to('Command2')); 87 | 88 | dispatch({event:eventName},function() { 89 | 90 | expect(command2Executed).toBe(false); 91 | }); 92 | }); 93 | }); -------------------------------------------------------------------------------- /test/groups/command-flow-with-service.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Command Flow link to service execution testing", function() { 4 | 5 | var provider; 6 | var eventName = 'TestEvent'; 7 | var command2Executed = false; 8 | 9 | beforeEach(function() { 10 | 11 | command2Executed = false; 12 | commangular.reset(); 13 | commangular.create('Command2', function() { 14 | 15 | return { 16 | 17 | execute: function() { 18 | 19 | command2Executed = true; 20 | } 21 | }; 22 | }); 23 | }); 24 | 25 | beforeEach(function() { 26 | 27 | module('commangular', function($commangularProvider) { 28 | 29 | provider = $commangularProvider; 30 | 31 | }); 32 | inject(); 33 | }); 34 | 35 | it('provider should be defined', function() { 36 | 37 | expect(provider).toBeDefined(); 38 | }); 39 | 40 | it('command 2 should be executed', function() { 41 | 42 | 43 | commangular.create('Command1', function() { 44 | 45 | return { 46 | 47 | execute: function() { 48 | 49 | return true; 50 | } 51 | }; 52 | },{resultKey:'result1'}); 53 | 54 | var commandComplete = false; 55 | provider.mapTo(eventName).asSequence() 56 | .add('Command1') 57 | .add(provider.asFlow() 58 | .link("UserDomainModel.username == 'monkey'",'UserDomainModel').to('Command2')); 59 | 60 | dispatch({event:eventName},function() { 61 | 62 | expect(command2Executed).toBe(true); 63 | }); 64 | }); 65 | 66 | it('command 2 should not be executed', function() { 67 | 68 | 69 | commangular.create('Command1', function() { 70 | 71 | return { 72 | 73 | execute: function() { 74 | 75 | return false; 76 | } 77 | }; 78 | },{resultKey:'result1'}); 79 | 80 | 81 | var commandComplete = false; 82 | provider.mapTo(eventName) 83 | .asSequence() 84 | .add('Command1') 85 | .add(provider.asFlow() 86 | .link("UserDomainModel.username == 'notMonkey'",'UserDomainModel').to('Command2')); 87 | 88 | dispatch({event:eventName},function() { 89 | 90 | expect(command2Executed).toBe(false); 91 | }) 92 | }); 93 | }); -------------------------------------------------------------------------------- /test/groups/command-injection-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Command execution testing", function() { 4 | 5 | var provider; 6 | var scope; 7 | var injector; 8 | var eventName = 'TestEvent'; 9 | 10 | var injectedScope; 11 | var injectedInjector; 12 | var injectedLog; 13 | 14 | beforeEach(function() { 15 | 16 | commangular.reset(); 17 | commangular.create('Command1', function($log, $rootScope) { 18 | 19 | injectedLog = $log; 20 | injectedScope = $rootScope; 21 | 22 | return { 23 | 24 | execute: function($injector) { 25 | 26 | injectedInjector = $injector; 27 | } 28 | }; 29 | }); 30 | }); 31 | 32 | 33 | beforeEach(function() { 34 | 35 | module('commangular', function($commangularProvider) { 36 | 37 | provider = $commangularProvider; 38 | 39 | }); 40 | inject(function($rootScope, $injector) { 41 | 42 | scope = $rootScope; 43 | injector = $injector; 44 | }); 45 | }); 46 | 47 | it('injection should be working', function() { 48 | 49 | provider.mapTo(eventName).asSequence().add('Command1'); 50 | dispatch({event:eventName},function() { 51 | 52 | expect(injectedInjector).toBeDefined(); 53 | expect(injectedInjector).toEqual(injector); 54 | expect(injectedScope).toBeDefined(); 55 | expect(injectedScope).toEqual(scope); 56 | expect(injectedLog).toBeDefined(); 57 | }); 58 | }); 59 | }); -------------------------------------------------------------------------------- /test/groups/command-last-result-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Injection using lastResult test", function() { 4 | 5 | var provider; 6 | var injector; 7 | var eventName = 'TestEvent'; 8 | var resultInjected; 9 | var timeout; 10 | 11 | beforeEach(function() { 12 | 13 | commangular.reset(); 14 | commangular.create('Command1', function() { 15 | 16 | return { 17 | 18 | execute: function() { 19 | 20 | return 25; 21 | } 22 | }; 23 | }); 24 | 25 | commangular.create('Command2', function() { 26 | 27 | return { 28 | 29 | execute: function(lastResult) { 30 | 31 | resultInjected = lastResult; 32 | } 33 | }; 34 | }); 35 | commangular.create('Command3', function() { 36 | 37 | return { 38 | 39 | execute: function($timeout, $q) { 40 | 41 | var deferred = $q.defer() 42 | $timeout(function() { 43 | deferred.resolve(75); 44 | }, 500); 45 | return deferred.promise; 46 | } 47 | }; 48 | }); 49 | }); 50 | 51 | beforeEach(function() { 52 | 53 | module('commangular', function($commangularProvider) { 54 | 55 | provider = $commangularProvider; 56 | 57 | }); 58 | inject(function($timeout) { 59 | 60 | timeout = $timeout; 61 | }); 62 | }); 63 | 64 | it('command should be executed and result injected has to be 25', function() { 65 | 66 | provider.mapTo(eventName).asSequence().add('Command1').add('Command2'); 67 | 68 | dispatch({event:eventName},function() { 69 | 70 | expect(resultInjected).toBe(25) 71 | }); 72 | }); 73 | 74 | it('command should work with promise resolution as well', function() { 75 | 76 | provider.mapTo(eventName).asSequence().add('Command3').add('Command2'); 77 | 78 | dispatch({event:eventName},function() { 79 | 80 | expect(resultInjected).toBe(75); 81 | }); 82 | timeout.flush(); 83 | }); 84 | 85 | 86 | }); -------------------------------------------------------------------------------- /test/groups/command-model-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Command Sequence execution testing", function() { 4 | 5 | var provider; 6 | var eventName = 'TestEvent'; 7 | var testValue; 8 | 9 | beforeEach(function() { 10 | 11 | commangular.reset(); 12 | commangular.create('Command1', function(commandModel) { 13 | 14 | return { 15 | 16 | execute: function() { 17 | 18 | commandModel.value1 = 25; 19 | } 20 | }; 21 | }); 22 | commangular.create('Command2', function(commandModel) { 23 | 24 | return { 25 | 26 | execute: function() { 27 | 28 | commandModel.value1++; 29 | testValue = commandModel.value1; 30 | } 31 | }; 32 | }); 33 | }); 34 | 35 | beforeEach(function() { 36 | 37 | module('commangular', function($commangularProvider) { 38 | 39 | provider = $commangularProvider; 40 | 41 | }); 42 | inject(); 43 | }); 44 | 45 | it('testValue should be 26', function() { 46 | 47 | provider.mapTo(eventName).asSequence().add('Command1').add('Command2'); 48 | 49 | dispatch({event:eventName},function() { 50 | 51 | expect(testValue).toBe(26); 52 | }); 53 | }); 54 | }); -------------------------------------------------------------------------------- /test/groups/command-parallel-execution-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Command Parallel execution testing", function() { 4 | 5 | var provider; 6 | var eventName = 'TestEvent'; 7 | 8 | beforeEach(function() { 9 | 10 | commangular.reset(); 11 | commangular.create('Command1', function() { 12 | 13 | return { 14 | 15 | execute: function($log) { 16 | 17 | $log.log('logging'); 18 | } 19 | }; 20 | }); 21 | commangular.create('Command2', function() { 22 | 23 | return { 24 | 25 | execute: function($log) { 26 | 27 | $log.log('logging'); 28 | } 29 | }; 30 | }); 31 | }); 32 | 33 | beforeEach(function() { 34 | 35 | module('commangular', function($commangularProvider) { 36 | 37 | provider = $commangularProvider; 38 | 39 | }); 40 | inject(); 41 | }); 42 | 43 | it('command should be executed', function() { 44 | 45 | provider.mapTo(eventName).asParallel().add('Command1').add('Command2'); 46 | 47 | dispatch({event:eventName},function() { 48 | 49 | //TODO:Use commangular mocks to test execution. 50 | 51 | /*expect(injector.instantiate).toHaveBeenCalled(); 52 | expect(injector.invoke).toHaveBeenCalled(); 53 | expect(injector.instantiate.callCount).toBe(2); 54 | expect(injector.invoke.callCount).toBe(2);*/ 55 | }); 56 | }); 57 | 58 | it('command.execute method should be called twice', function() { 59 | 60 | /*var command = {execute: function() {}}; 61 | provider.mapTo(eventName).asParallel().add('Command1').add('Command2'); 62 | 63 | dispatch({event:eventName},function() { 64 | 65 | expect(command.execute).toHaveBeenCalled(); 66 | expect(command.execute.callCount).toBe(2); 67 | });*/ 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /test/groups/command-sequence-execution-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Command Sequence execution testing", function() { 4 | 5 | var provider; 6 | var eventName = 'TestEvent'; 7 | 8 | beforeEach(function() { 9 | 10 | commangular.reset(); 11 | commangular.create('Command1', function() { 12 | 13 | return { 14 | 15 | execute: function($log) { 16 | 17 | $log.log('logging'); 18 | } 19 | }; 20 | }); 21 | commangular.create('Command2', function() { 22 | 23 | return { 24 | 25 | execute: function($log) { 26 | 27 | $log.log('logging'); 28 | } 29 | }; 30 | }); 31 | }); 32 | 33 | beforeEach(function() { 34 | 35 | module('commangular', function($commangularProvider) { 36 | 37 | provider = $commangularProvider; 38 | 39 | }); 40 | inject(); 41 | }); 42 | 43 | //TODO : Use commangular mocks 44 | /* 45 | it('command should be executed', function() { 46 | 47 | provider.mapTo(eventName).asSequence().add('Command1').add('Command2'); 48 | spyOn(injector, 'instantiate').andCallThrough(); 49 | spyOn(injector, 'invoke').andCallThrough(); 50 | 51 | dispatch({event:eventName},function() { 52 | 53 | expect(injector.instantiate).toHaveBeenCalled(); 54 | expect(injector.invoke).toHaveBeenCalled(); 55 | }); 56 | }); 57 | 58 | it('command.execute method should be called twice', function() { 59 | 60 | var command = { 61 | 62 | execute: function() { 63 | 64 | } 65 | }; 66 | provider.mapTo(eventName).asSequence().add('Command1').add('Command2'); 67 | spyOn(injector, 'instantiate').andReturn(command); 68 | spyOn(command, 'execute').andCallThrough(); 69 | 70 | dispatch({event:eventName},function() { 71 | 72 | expect(command.execute).toHaveBeenCalled(); 73 | expect(command.execute.callCount).toBe(2); 74 | }); 75 | });*/ 76 | }); -------------------------------------------------------------------------------- /test/groups/commandgular-provider-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Provider Testing", function() { 4 | 5 | var provider; 6 | function command1() {}; 7 | function command2() {}; 8 | 9 | beforeEach(function() { 10 | 11 | commangular.reset(); 12 | commangular.create('Command1', command1); 13 | commangular.create('Command2', command2); 14 | }); 15 | 16 | beforeEach(function() { 17 | 18 | module('commangular', function($commangularProvider) { 19 | 20 | provider = $commangularProvider; 21 | }); 22 | inject(function() {}); 23 | }); 24 | 25 | it("provider should be defined", function() { 26 | 27 | expect(provider).toBeDefined(); 28 | }); 29 | 30 | it("should create the correct commandType", function() { 31 | 32 | expect(provider).toBeDefined(); 33 | 34 | var sequence = provider.asSequence().add('Command1'); 35 | expect(sequence).toBeDefined(); 36 | expect(sequence.ctype).toBe('S'); 37 | 38 | var parallel = provider.asParallel().add('Command1'); 39 | expect(parallel).toBeDefined(); 40 | expect(parallel.ctype).toBe('P'); 41 | 42 | var command = parallel.descriptors[0]; 43 | expect(command).toBeDefined(); 44 | expect(command.ctype).toBe('E'); 45 | 46 | }); 47 | 48 | it("descriptor should have the correct command function", function() { 49 | 50 | expect(provider).toBeDefined(); 51 | 52 | var sequence = provider.asSequence().add('Command1'); 53 | expect(sequence).toBeDefined(); 54 | expect(sequence.command).toBeUndefined(); 55 | 56 | var parallel = provider.asParallel().add('Command2'); 57 | expect(parallel).toBeDefined(); 58 | expect(parallel.command).toBeUndefined(); 59 | 60 | var com1 = sequence.descriptors[0]; 61 | expect(com1).toBeDefined(); 62 | expect(com1.command.commandFunction).toEqual(command1); 63 | 64 | var com2 = parallel.descriptors[0]; 65 | expect(com2).toBeDefined(); 66 | expect(com2.command.commandFunction).toEqual(command2); 67 | 68 | }); 69 | 70 | it("should map to the correct event string", function() { 71 | 72 | expect(provider).toBeDefined(); 73 | var eventName = 'TestEvent'; 74 | provider.mapTo(eventName).asSequence().add('Command1'); 75 | var commandDescriptor = provider.findCommand(eventName); 76 | expect(commandDescriptor).toBeDefined(); 77 | expect(commandDescriptor.command).toBeUndefined(); 78 | expect(commandDescriptor.descriptors[0].command.commandFunction).toEqual(command1); 79 | 80 | 81 | }); 82 | 83 | it("should map correct sequences", function() { 84 | 85 | expect(provider).toBeDefined(); 86 | var eventName = 'TestEvent'; 87 | provider.mapTo(eventName).asSequence().add('Command1').add('Command2'); 88 | var commandDescriptor = provider.findCommand(eventName); 89 | expect(commandDescriptor.ctype).toBe('S'); 90 | expect(commandDescriptor).toBeDefined(); 91 | expect(commandDescriptor.descriptors[0].command.commandFunction).toEqual(command1); 92 | expect(commandDescriptor.descriptors[1].command.commandFunction).toEqual(command2); 93 | }); 94 | 95 | 96 | it("should map correct parallels", function() { 97 | 98 | expect(provider).toBeDefined(); 99 | var eventName = 'TestEvent'; 100 | provider.mapTo(eventName).asParallel().add('Command1').add('Command2'); 101 | var commandDescriptor = provider.findCommand(eventName); 102 | expect(commandDescriptor.ctype).toBe('P'); 103 | expect(commandDescriptor).toBeDefined(); 104 | expect(commandDescriptor.descriptors[0].command.commandFunction).toEqual(command1); 105 | expect(commandDescriptor.descriptors[1].command.commandFunction).toEqual(command2); 106 | }); 107 | 108 | it("should allow nested commands", function() { 109 | 110 | expect(provider).toBeDefined(); 111 | var eventName = 'TestEvent'; 112 | var sequence = provider.asSequence().add('Command1').add('Command2'); 113 | provider.mapTo(eventName).asParallel().add('Command1').add('Command2').add(sequence); 114 | var commandDescriptor = provider.findCommand(eventName); 115 | expect(commandDescriptor.ctype).toBe('P'); 116 | expect(commandDescriptor).toBeDefined(); 117 | expect(commandDescriptor.descriptors[0].command.commandFunction).toEqual(command1); 118 | expect(commandDescriptor.descriptors[1].command.commandFunction).toEqual(command2); 119 | expect(commandDescriptor.descriptors[2]).toEqual(sequence); 120 | expect(commandDescriptor.descriptors[2].descriptors[0].command.commandFunction).toEqual(command1); 121 | expect(commandDescriptor.descriptors[2].descriptors[1].command.commandFunction).toEqual(command2); 122 | }); 123 | }); -------------------------------------------------------------------------------- /test/groups/context-data-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Command execution testing", function() { 4 | 5 | var provider; 6 | var eventName = 'TestEvent'; 7 | 8 | beforeEach(function() { 9 | 10 | commangular.reset(); 11 | 12 | commangular.create('Command1', function() { 13 | 14 | return { 15 | 16 | execute: function() { 17 | 18 | return 45; 19 | } 20 | }; 21 | },{resultKey:'resultKeyTest'}); 22 | }); 23 | 24 | beforeEach(function() { 25 | 26 | module('commangular', function($commangularProvider) { 27 | 28 | provider = $commangularProvider; 29 | 30 | 31 | }); 32 | inject(); 33 | }); 34 | 35 | it('provider should be defined', function() { 36 | 37 | expect(provider).toBeDefined(); 38 | }); 39 | 40 | 41 | it('Context data has to contain the result key', function() { 42 | 43 | provider.mapTo(eventName).asSequence().add('Command1'); 44 | var commandComplete = false; 45 | 46 | dispatch({event:eventName},function(exc) { 47 | 48 | expect(exc.resultKey('resultKeyTest')).toBe(45); 49 | }); 50 | 51 | }); 52 | 53 | }); -------------------------------------------------------------------------------- /test/groups/custom-resolver-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Custom resolver test", function() { 4 | 5 | var provider; 6 | var commandExecuted = false; 7 | 8 | beforeEach(function() { 9 | 10 | commangular.reset(); 11 | 12 | commangular.resolver('com.exec.Command1', function(result){ 13 | 14 | expect(result).toBe(50); 15 | return 75; 16 | }); 17 | 18 | 19 | commangular.create('com.exec.Command1',function(){ 20 | 21 | return { 22 | 23 | execute : function() { 24 | 25 | commandExecuted = true; 26 | return 50; 27 | } 28 | }; 29 | },{resultKey:'result'}); 30 | 31 | 32 | }); 33 | 34 | beforeEach(function() { 35 | 36 | module('commangular', function($commangularProvider) { 37 | provider = $commangularProvider; 38 | }); 39 | inject(); 40 | }); 41 | //TODO: Add more expectations to test result returned 42 | it("The resolver should be executed", function() { 43 | 44 | provider.mapTo('CustomResolverEvent').asSequence().add('com.exec.Command1'); 45 | 46 | dispatch({event:'CustomResolverEvent'},function() { 47 | 48 | expect(commandExecuted).toBe(true); 49 | }) 50 | }); 51 | }); -------------------------------------------------------------------------------- /test/groups/dispatching-from-scope-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Dispatching from scope test", function() { 4 | 5 | var provider; 6 | var injector; 7 | var eventName = 'TestEvent'; 8 | 9 | beforeEach(function() { 10 | 11 | commangular.reset(); 12 | commangular.create('Command1', function() { 13 | 14 | return { 15 | 16 | execute: function($log) { 17 | 18 | $log.log('logging'); 19 | } 20 | }; 21 | }); 22 | commangular.create('Command2', function() { 23 | 24 | return { 25 | 26 | execute: function($log) { 27 | 28 | $log.log('logging'); 29 | } 30 | }; 31 | }); 32 | }); 33 | 34 | beforeEach(function() { 35 | 36 | module('commangular', function($commangularProvider) { 37 | 38 | provider = $commangularProvider; 39 | 40 | }); 41 | inject(function($injector) { 42 | 43 | injector = $injector; 44 | }); 45 | }); 46 | 47 | it('provider should be defined', function() { 48 | 49 | expect(provider).toBeDefined(); 50 | }); 51 | 52 | it('injector should be defined', function() { 53 | 54 | expect(injector).toBeDefined(); 55 | }); 56 | 57 | //TODO:Use commangular mocks 58 | 59 | /*it('command should be executed', function() { 60 | 61 | provider.mapTo(eventName).asSequence().add('Command1').add('Command2'); 62 | spyOn(injector, 'instantiate').andCallThrough(); 63 | spyOn(injector, 'invoke').andCallThrough(); 64 | 65 | dispatch({event:eventName},function() { 66 | 67 | expect(injector.instantiate).toHaveBeenCalled(); 68 | expect(injector.invoke).toHaveBeenCalled(); 69 | }); 70 | }); 71 | 72 | it('command.execute method should be called twice', function() { 73 | 74 | var command = { 75 | 76 | execute: function() { 77 | 78 | } 79 | }; 80 | provider.mapTo(eventName).asSequence().add('Command1').add('Command2'); 81 | spyOn(injector, 'instantiate').andReturn(command); 82 | spyOn(command, 'execute').andCallThrough(); 83 | 84 | dispatch({event:eventName},function() { 85 | 86 | expect(command.execute).toHaveBeenCalled(); 87 | expect(command.execute.callCount).toBe(2); 88 | }); 89 | });*/ 90 | }); -------------------------------------------------------------------------------- /test/groups/flow-to-sequence-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Flow To Sequence execution testing", function() { 4 | 5 | var provider; 6 | var eventName = 'TestEvent'; 7 | var command2Executed = false; 8 | var command3Executed = false; 9 | 10 | beforeEach(function() { 11 | 12 | command2Executed = false; 13 | commangular.reset(); 14 | commangular.create('Command1', function() { 15 | 16 | return { 17 | 18 | execute: function() { 19 | 20 | return true; 21 | } 22 | }; 23 | },{resultKey:'result1'}); 24 | 25 | commangular.create('Command2', function() { 26 | 27 | return { 28 | 29 | execute: function() { 30 | 31 | command2Executed = true; 32 | } 33 | }; 34 | }); 35 | 36 | commangular.create('Command3', function() { 37 | 38 | return { 39 | 40 | execute: function($log) { 41 | 42 | $log.log('logging'); 43 | command3Executed = true; 44 | } 45 | }; 46 | }); 47 | }); 48 | 49 | beforeEach(function() { 50 | 51 | module('commangular', function($commangularProvider) { 52 | 53 | provider = $commangularProvider; 54 | 55 | }); 56 | inject(); 57 | }); 58 | 59 | it('command 2 and 3 should be executed', function() { 60 | 61 | var commandComplete = false; 62 | var sequence = provider.asSequence().add('Command2'); 63 | provider.mapTo(eventName) 64 | .asSequence() 65 | .add('Command1') 66 | .add(provider.asFlow() 67 | .link('result1 == true').to( 68 | provider.asSequence() 69 | .add('Command2') 70 | .add('Command3'))); 71 | 72 | dispatch({event:eventName},function(){ 73 | 74 | expect(command2Executed).toBe(true); 75 | expect(command3Executed).toBe(true); 76 | }); 77 | }); 78 | }); -------------------------------------------------------------------------------- /test/groups/flow-with-data-passed.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Command Flow With Data passed test", function() { 4 | 5 | var provider; 6 | var eventName = 'TestEvent'; 7 | var endValue = 0; 8 | 9 | beforeEach(function() { 10 | 11 | commangular.reset(); 12 | commangular.create('Command1', function() { 13 | 14 | return { 15 | 16 | execute: function() { 17 | 18 | endValue = 1; 19 | } 20 | }; 21 | }); 22 | 23 | commangular.create('Command2', function() { 24 | 25 | return { 26 | 27 | execute: function() { 28 | 29 | endValue = 2; 30 | } 31 | }; 32 | }); 33 | }); 34 | 35 | beforeEach(function() { 36 | 37 | module('commangular', function($commangularProvider) { 38 | 39 | provider = $commangularProvider; 40 | 41 | }); 42 | inject(); 43 | }); 44 | 45 | it('endValue should be 1', function() { 46 | 47 | provider.mapTo(eventName) 48 | .asFlow() 49 | .link('data1 == 2').to('Command1') 50 | .link('data1 == 3').to('Command2'); 51 | 52 | dispatch({event:eventName,data:{data1:2}},function(){ 53 | 54 | expect(endValue).toBe(1); 55 | }); 56 | }); 57 | 58 | it('endValue should be 3', function() { 59 | 60 | commangular.create('Command1', function() { 61 | 62 | return { 63 | 64 | execute: function($log) { 65 | 66 | $log.log('logging'); 67 | return 3; 68 | } 69 | }; 70 | },{resultKey:'result1'}); 71 | 72 | provider.mapTo(eventName) 73 | .asFlow() 74 | .link('data1 == 2').to('Command1') 75 | .link('data1 == 3').to('Command2'); 76 | 77 | dispatch({event:eventName,data:{data1:3}},function(){ 78 | 79 | expect(endValue).toBe(2); 80 | }); 81 | }); 82 | }); -------------------------------------------------------------------------------- /test/groups/flow-with-numbers-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Command Flow With Numbers execution testing", function() { 4 | 5 | var provider; 6 | var eventName = 'TestEvent'; 7 | var endValue = 0; 8 | 9 | beforeEach(function() { 10 | 11 | commangular.reset(); 12 | commangular.create('Command1', function() { 13 | 14 | return { 15 | 16 | execute: function() { 17 | 18 | return 2; 19 | } 20 | }; 21 | },{resultKey:'result1'}); 22 | 23 | commangular.create('Command2', function() { 24 | 25 | return { 26 | 27 | execute: function() { 28 | 29 | endValue = 2; 30 | } 31 | }; 32 | }); 33 | 34 | commangular.create('Command3', function() { 35 | 36 | return { 37 | 38 | execute: function() { 39 | 40 | endValue = 3; 41 | } 42 | }; 43 | }); 44 | }); 45 | 46 | beforeEach(function() { 47 | 48 | module('commangular', function($commangularProvider) { 49 | 50 | provider = $commangularProvider; 51 | 52 | }); 53 | inject(); 54 | }); 55 | 56 | it('endValue should be 2', function() { 57 | 58 | 59 | commangular.create('Command1', function() { 60 | 61 | return { 62 | 63 | execute: function() { 64 | 65 | return 2; 66 | } 67 | }; 68 | },{resultKey:'result1'}); 69 | 70 | provider.mapTo(eventName) 71 | .asSequence() 72 | .add('Command1') 73 | .add(provider.asFlow() 74 | .link('result1 == 2').to('Command2') 75 | .link('result1 == 3').to('Command3')); 76 | 77 | dispatch({event:eventName},function(){ 78 | 79 | expect(endValue).toBe(2); 80 | }); 81 | }); 82 | 83 | it('endValue should be 3', function() { 84 | 85 | var commandComplete = false; 86 | 87 | commangular.create('Command1', function() { 88 | 89 | return { 90 | 91 | execute: function() { 92 | 93 | return 3; 94 | } 95 | }; 96 | },{resultKey:'result1'}); 97 | 98 | provider.mapTo(eventName) 99 | .asSequence() 100 | .add('Command1') 101 | .add(provider.asFlow() 102 | .link('lastResult == 2').to('Command2') 103 | .link('lastResult == 3').to('Command3')); 104 | 105 | dispatch({event:eventName},function(){ 106 | 107 | expect(endValue).toBe(3); 108 | }); 109 | }); 110 | }); -------------------------------------------------------------------------------- /test/groups/last-result-from-onresult.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("The last result should be the result from onResult method", function() { 4 | 5 | var provider; 6 | var injector; 7 | var eventName = 'TestEvent'; 8 | var resultInjected; 9 | var timeout; 10 | 11 | beforeEach(function() { 12 | 13 | commangular.reset(); 14 | commangular.create('Command1', function() { 15 | 16 | return { 17 | 18 | execute: function() { 19 | 20 | return 25; 21 | }, 22 | onResult: function(result){ 23 | 24 | expect(result).toBe(25); 25 | return 26; 26 | } 27 | }; 28 | }); 29 | 30 | commangular.create('Command2', function() { 31 | 32 | return { 33 | 34 | execute: function(lastResult) { 35 | 36 | resultInjected = lastResult; 37 | } 38 | }; 39 | }); 40 | commangular.create('Command3', function() { 41 | 42 | return { 43 | 44 | execute: function($timeout, $q) { 45 | 46 | var deferred = $q.defer() 47 | $timeout(function() { 48 | deferred.resolve(75); 49 | }, 500); 50 | return deferred.promise; 51 | } 52 | }; 53 | }); 54 | }); 55 | 56 | beforeEach(function() { 57 | 58 | module('commangular', function($commangularProvider) { 59 | 60 | provider = $commangularProvider; 61 | 62 | }); 63 | inject(function($timeout) { 64 | 65 | timeout = $timeout; 66 | }); 67 | }); 68 | 69 | it('command should be executed and result injected has to be 26', function() { 70 | 71 | provider.mapTo(eventName).asSequence().add('Command1').add('Command2'); 72 | 73 | dispatch({event:eventName},function() { 74 | 75 | expect(resultInjected).toBe(26) 76 | }); 77 | }); 78 | 79 | it('command should work with promise resolution as well', function() { 80 | 81 | provider.mapTo(eventName).asSequence().add('Command3').add('Command2'); 82 | 83 | dispatch({event:eventName},function() { 84 | 85 | expect(resultInjected).toBe(75); 86 | }); 87 | timeout.flush(); 88 | }); 89 | 90 | 91 | }); -------------------------------------------------------------------------------- /test/groups/on-error-handler-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("On error handler test", function() { 4 | 5 | var provider; 6 | var eventName = 'TestEvent'; 7 | var executeMethodExecuted = false; 8 | var onErrorMethodExecuted = false; 9 | 10 | beforeEach(function() { 11 | 12 | commangular.reset(); 13 | commangular.create('Command1', function() { 14 | 15 | return { 16 | 17 | execute: function() { 18 | 19 | throw new Error("Test Error"); 20 | executeMethodExecuted = true; 21 | return 25; 22 | }, 23 | onError : function(error) { 24 | 25 | expect(executeMethodExecuted).toBe(false); 26 | expect(error.message).toEqual("Test Error"); 27 | onErrorMethodExecuted = true; 28 | } 29 | }; 30 | }); 31 | 32 | }); 33 | 34 | beforeEach(function() { 35 | 36 | module('commangular', function($commangularProvider) { 37 | 38 | provider = $commangularProvider; 39 | 40 | }); 41 | inject(); 42 | }); 43 | 44 | it('OnError callback should be executed', function() { 45 | 46 | provider.mapTo(eventName).asSequence().add('Command1'); 47 | dispatch({event:eventName},function(){ 48 | 49 | expect(executeMethodExecuted).toBe(false); 50 | expect(onErrorMethodExecuted).toBe(true); 51 | }); 52 | }); 53 | 54 | 55 | }); -------------------------------------------------------------------------------- /test/groups/on-result-handler-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("On result handler test", function() { 4 | 5 | var provider; 6 | var eventName = 'TestEvent'; 7 | var executeMethodExecuted = false; 8 | var onResultMethodExecuted = false; 9 | 10 | beforeEach(function() { 11 | 12 | commangular.reset(); 13 | commangular.create('Command1', function() { 14 | 15 | return { 16 | 17 | execute: function() { 18 | 19 | executeMethodExecuted = true; 20 | return 25; 21 | }, 22 | onResult : function(result) { 23 | 24 | expect(result).toBe(25); 25 | onResultMethodExecuted = true; 26 | 27 | } 28 | }; 29 | }); 30 | 31 | }); 32 | 33 | beforeEach(function() { 34 | 35 | module('commangular', function($commangularProvider) { 36 | 37 | provider = $commangularProvider; 38 | 39 | }); 40 | inject(); 41 | }); 42 | 43 | it('command should be executed', function() { 44 | 45 | 46 | provider.mapTo(eventName).asSequence().add('Command1'); 47 | dispatch({event:eventName},function() { 48 | 49 | expect(executeMethodExecuted).toBe(true); 50 | expect(onResultMethodExecuted).toBe(true); 51 | }); 52 | }); 53 | 54 | 55 | }); -------------------------------------------------------------------------------- /test/groups/passing-data-to-command-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Passing data to commands test", function() { 4 | 5 | var provider; 6 | var eventName = 'TestEvent'; 7 | var plusResultValue; 8 | var minusResultValue 9 | 10 | beforeEach(function() { 11 | 12 | commangular.reset(); 13 | commangular.create('Command1', function(data1,data2) { 14 | 15 | return { 16 | 17 | execute: function() { 18 | 19 | plusResultValue = data1 + data2; 20 | } 21 | }; 22 | }); 23 | commangular.create('Command2', function(data2,data1) { 24 | 25 | return { 26 | 27 | execute: function() { 28 | 29 | minusResultValue = data2 - data1; 30 | } 31 | }; 32 | }); 33 | }); 34 | 35 | beforeEach(function() { 36 | 37 | module('commangular', function($commangularProvider) { 38 | 39 | provider = $commangularProvider; 40 | 41 | }); 42 | inject(); 43 | }); 44 | 45 | it('calculation has to be 12 and 2', function() { 46 | 47 | provider.mapTo(eventName).asSequence().add('Command1').add('Command2'); 48 | dispatch({event:eventName,data:{data1:5,data2:7}},function(){ 49 | 50 | expect(plusResultValue).toBe(12); 51 | expect(minusResultValue).toBe(2); 52 | }); 53 | }); 54 | 55 | 56 | }); -------------------------------------------------------------------------------- /test/groups/preceding-result-injection-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Injection from preceding command result test", function() { 4 | 5 | var provider; 6 | var eventName = 'TestEvent'; 7 | var resultInjected; 8 | 9 | beforeEach(function() { 10 | 11 | commangular.reset(); 12 | commangular.create('Command1', function() { 13 | 14 | return { 15 | 16 | execute: function() { 17 | 18 | return 25; 19 | 20 | } 21 | }; 22 | }, {resultKey: 'commandResult'}); 23 | 24 | commangular.create('Command2', function() { 25 | 26 | return { 27 | 28 | execute: function(commandResult) { 29 | 30 | resultInjected = commandResult; 31 | 32 | 33 | } 34 | }; 35 | }); 36 | }); 37 | 38 | beforeEach(function() { 39 | 40 | module('commangular', function($commangularProvider) { 41 | 42 | provider = $commangularProvider; 43 | 44 | }); 45 | inject(); 46 | }); 47 | 48 | it('command should be executed and resultInjected has to be 25', function() { 49 | 50 | provider.mapTo(eventName).asSequence().add('Command1').add('Command2'); 51 | 52 | dispatch({event:eventName},function(){ 53 | 54 | expect(resultInjected).toBe(25) 55 | }); 56 | }); 57 | 58 | 59 | }); -------------------------------------------------------------------------------- /test/groups/promises-resolution-test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("Injection from preceding command whit promise result test", function() { 4 | 5 | var provider; 6 | var resultInjected = 45; 7 | var $timeout; 8 | 9 | beforeEach(function() { 10 | 11 | commangular.reset(); 12 | commangular.create('Command1', function() { 13 | 14 | return { 15 | 16 | execute: function($timeout, $q) { 17 | 18 | var deferred = $q.defer() 19 | $timeout(function() { 20 | deferred.resolve(25); 21 | }, 500); 22 | return deferred.promise; 23 | } 24 | }; 25 | },{resultKey:'result1'}); 26 | 27 | commangular.create('Command2', function($timeout) { 28 | 29 | return { 30 | 31 | execute: function(result1) { 32 | 33 | resultInjected = result1; 34 | } 35 | }; 36 | }); 37 | }); 38 | 39 | beforeEach(function() { 40 | 41 | module('commangular', function($commangularProvider) { 42 | 43 | provider = $commangularProvider; 44 | 45 | }); 46 | inject(function(_$timeout_) { 47 | 48 | $timeout = _$timeout_; 49 | }); 50 | }); 51 | 52 | it('command should be executed and resultInjected has to be 25', function() { 53 | 54 | provider.mapTo('TestEvent').asSequence().add('Command1').add('Command2'); 55 | 56 | dispatch({event:'TestEvent'},function(exc) { 57 | 58 | expect(resultInjected).toBe(25); 59 | expect(exc.resultKey('result1')).toBe(25); 60 | expect(exc.canceled()).toBe(false); 61 | expect(exc.commandExecuted('Command1')).toBe(true); 62 | expect(exc.commandExecuted('Command2')).toBe(true); 63 | }); 64 | $timeout.flush(); 65 | }); 66 | 67 | 68 | }); -------------------------------------------------------------------------------- /test/groups/resultkey-from-onResult.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | describe("The result key should be the result from onResult method", function() { 4 | 5 | var provider; 6 | var injector; 7 | var eventName = 'TestEvent'; 8 | var resultInjected; 9 | var timeout; 10 | 11 | beforeEach(function() { 12 | 13 | commangular.reset(); 14 | commangular.create('Command1', function() { 15 | 16 | return { 17 | 18 | execute: function() { 19 | 20 | return 25; 21 | }, 22 | onResult: function(result){ 23 | 24 | expect(result).toBe(25); 25 | return 26; 26 | } 27 | }; 28 | },{resultKey:'resultValue'}); 29 | 30 | commangular.create('Command2', function() { 31 | 32 | return { 33 | 34 | execute: function(resultValue) { 35 | 36 | resultInjected = resultValue; 37 | } 38 | }; 39 | }); 40 | 41 | }); 42 | 43 | beforeEach(function() { 44 | 45 | module('commangular', function($commangularProvider) { 46 | 47 | provider = $commangularProvider; 48 | 49 | }); 50 | inject(function($timeout) { 51 | 52 | timeout = $timeout; 53 | }); 54 | }); 55 | 56 | it('command should be executed and result injected has to be 26', function() { 57 | 58 | provider.mapTo(eventName).asSequence().add('Command1').add('Command2'); 59 | 60 | dispatch({event:eventName},function() { 61 | 62 | expect(resultInjected).toBe(26) 63 | }); 64 | }); 65 | 66 | }); --------------------------------------------------------------------------------