aboutsummaryrefslogtreecommitdiffstats
path: root/src/scenario/Runner.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/scenario/Runner.js')
-rw-r--r--src/scenario/Runner.js128
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');
+ });
};