diff options
Diffstat (limited to 'src/scenario/Runner.js')
| -rw-r--r-- | src/scenario/Runner.js | 128 |
1 files changed, 107 insertions, 21 deletions
diff --git a/src/scenario/Runner.js b/src/scenario/Runner.js index a8b23f83..f628eb04 100644 --- a/src/scenario/Runner.js +++ b/src/scenario/Runner.js @@ -2,13 +2,16 @@ * Runner for scenarios. */ angular.scenario.Runner = function($window) { + this.listeners = []; this.$window = $window; this.rootDescribe = new angular.scenario.Describe(); this.currentDescribe = this.rootDescribe; this.api = { it: this.it, + iit: this.iit, xit: angular.noop, describe: this.describe, + ddescribe: this.ddescribe, xdescribe: angular.noop, beforeEach: this.beforeEach, afterEach: this.afterEach @@ -19,10 +22,41 @@ angular.scenario.Runner = function($window) { }; /** + * Emits an event which notifies listeners and passes extra + * arguments. + * + * @param {string} eventName Name of the event to fire. + */ +angular.scenario.Runner.prototype.emit = function(eventName) { + var self = this; + var args = Array.prototype.slice.call(arguments, 1); + eventName = eventName.toLowerCase(); + if (!this.listeners[eventName]) + return; + angular.foreach(this.listeners[eventName], function(listener) { + listener.apply(self, args); + }); +}; + +/** + * Adds a listener for an event. + * + * @param {string} eventName The name of the event to add a handler for + * @param {string} listener The fn(...) that takes the extra arguments from emit() + */ +angular.scenario.Runner.prototype.on = function(eventName, listener) { + eventName = eventName.toLowerCase(); + this.listeners[eventName] = this.listeners[eventName] || []; + this.listeners[eventName].push(listener); +}; + +/** * Defines a describe block of a spec. * - * @param {String} Name of the block - * @param {Function} Body of the block + * @see Describe.js + * + * @param {string} name Name of the block + * @param {Function} body Body of the block */ angular.scenario.Runner.prototype.describe = function(name, body) { var self = this; @@ -38,19 +72,56 @@ angular.scenario.Runner.prototype.describe = function(name, body) { }; /** + * Same as describe, but makes ddescribe the only blocks to run. + * + * @see Describe.js + * + * @param {string} name Name of the block + * @param {Function} body Body of the block + */ +angular.scenario.Runner.prototype.ddescribe = function(name, body) { + var self = this; + this.currentDescribe.ddescribe(name, function() { + var parentDescribe = self.currentDescribe; + self.currentDescribe = this; + try { + body.call(this); + } finally { + self.currentDescribe = parentDescribe; + } + }); +}; + +/** * Defines a test in a describe block of a spec. * - * @param {String} Name of the block - * @param {Function} Body of the block + * @see Describe.js + * + * @param {string} name Name of the block + * @param {Function} body Body of the block */ angular.scenario.Runner.prototype.it = function(name, body) { this.currentDescribe.it(name, body); }; /** + * Same as it, but makes iit tests the only tests to run. + * + * @see Describe.js + * + * @param {string} name Name of the block + * @param {Function} body Body of the block + */ +angular.scenario.Runner.prototype.iit = function(name, body) { + this.currentDescribe.iit(name, body); +}; + +/** * Defines a function to be called before each it block in the describe * (and before all nested describes). * + * @see Describe.js + * * @param {Function} Callback to execute */ angular.scenario.Runner.prototype.beforeEach = function(body) { @@ -61,6 +132,8 @@ angular.scenario.Runner.prototype.beforeEach = function(body) { * Defines a function to be called after each it block in the describe * (and before all nested describes). * + * @see Describe.js + * * @param {Function} Callback to execute */ angular.scenario.Runner.prototype.afterEach = function(body) { @@ -68,24 +141,29 @@ angular.scenario.Runner.prototype.afterEach = function(body) { }; /** - * Defines a function to be called before each it block in the describe - * (and before all nested describes). + * Creates a new spec runner. * - * @param {Function} Callback to execute + * @private + * @param {Object} scope parent scope + */ +angular.scenario.Runner.prototype.createSpecRunner_ = function(scope) { + return scope.$new(angular.scenario.SpecRunner); +}; + +/** + * Runs all the loaded tests with the specified runner class on the + * provided application. + * + * @param {angular.scenario.Application} application App to remote control. */ -angular.scenario.Runner.prototype.run = function(ui, application, specRunnerClass, specsDone) { - var $root = angular.scope({}, angular.service); +angular.scenario.Runner.prototype.run = function(application) { var self = this; - var specs = this.rootDescribe.getSpecs(); + var $root = angular.scope(this); $root.application = application; - $root.ui = ui; - $root.setTimeout = function() { - return self.$window.setTimeout.apply(self.$window, arguments); - }; - asyncForEach(specs, function(spec, specDone) { + this.emit('RunnerBegin'); + asyncForEach(this.rootDescribe.getSpecs(), function(spec, specDone) { var dslCache = {}; - var runner = angular.scope($root); - runner.$become(specRunnerClass); + var runner = self.createSpecRunner_($root); angular.foreach(angular.scenario.dsl, function(fn, key) { dslCache[key] = fn.call($root); }); @@ -105,16 +183,24 @@ angular.scenario.Runner.prototype.run = function(ui, application, specRunnerClas // Make these methods work on the current chain scope.addFuture = function() { Array.prototype.push.call(arguments, line); - return specRunnerClass.prototype.addFuture.apply(scope, arguments); + return angular.scenario.SpecRunner. + prototype.addFuture.apply(scope, arguments); }; scope.addFutureAction = function() { Array.prototype.push.call(arguments, line); - return specRunnerClass.prototype.addFutureAction.apply(scope, arguments); + return angular.scenario.SpecRunner. + prototype.addFutureAction.apply(scope, arguments); }; return scope.dsl[key].apply(scope, arguments); }; }); - runner.run(ui, spec, specDone); - }, specsDone || angular.noop); + runner.run(spec, specDone); + }, + function(error) { + if (error) { + self.emit('RunnerError', error); + } + self.emit('RunnerEnd'); + }); }; |
