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.js161
1 files changed, 161 insertions, 0 deletions
diff --git a/src/scenario/Runner.js b/src/scenario/Runner.js
new file mode 100644
index 00000000..8e0cc909
--- /dev/null
+++ b/src/scenario/Runner.js
@@ -0,0 +1,161 @@
+angular['scenario'] = angular['scenario'] || (angular['scenario'] = {});
+angular.scenario['dsl'] = angular.scenario['dsl'] || (angular.scenario['dsl'] = {});
+
+angular.scenario.Runner = function(scope, jQuery){
+ var self = scope.$scenario = this;
+ this.scope = scope;
+ this.jQuery = jQuery;
+
+ var specs = this.specs = {};
+ var path = [];
+ this.scope.describe = function(name, body){
+ path.push(name);
+ body();
+ path.pop();
+ };
+ var beforeEach = noop;
+ var afterEach = noop;
+ this.scope.beforeEach = function(body) {
+ beforeEach = body;
+ };
+ this.scope.afterEach = function(body) {
+ afterEach = body;
+ };
+ this.scope.it = function(name, body) {
+ var specName = path.join(' ') + ': it ' + name;
+ self.currentSpec = specs[specName] = {
+ name: specName,
+ steps:[]
+ };
+ try {
+ beforeEach();
+ body();
+ } catch(err) {
+ self.addStep(err.message || 'ERROR', function(){
+ throw err;
+ });
+ } finally {
+ afterEach();
+ }
+ self.currentSpec = null;
+ };
+ this.logger = function returnNoop(){
+ return extend(returnNoop, {close:noop, fail:noop});;
+ };
+};
+
+angular.scenario.Runner.prototype = {
+ run: function(body){
+ var jQuery = this.jQuery;
+ body.append(
+ '<div id="runner">' +
+ '<div class="console"></div>' +
+ '</div>' +
+ '<div id="testView">' +
+ '<iframe></iframe>' +
+ '</div>');
+ var console = body.find('#runner .console');
+ console.find('li').live('click', function(){
+ jQuery(this).toggleClass('collapsed');
+ });
+ this.testFrame = body.find('#testView iframe');
+ function logger(parent) {
+ var container;
+ return function(type, text) {
+ if (!container) {
+ container = jQuery('<ul></ul>');
+ parent.append(container);
+ }
+ var element = jQuery('<li class="running '+type+'"><span></span></li>');
+ element.find('span').text(text);
+ container.append(element);
+ return extend(logger(element), {
+ close: function(){
+ element.removeClass('running');
+ if(!element.hasClass('fail'))
+ element.addClass('collapsed');
+ console.scrollTop(console[0].scrollHeight);
+ },
+ fail: function(){
+ element.removeClass('running');
+ var current = element;
+ while (current[0] != console[0]) {
+ if (current.is('li'))
+ current.addClass('fail');
+ current = current.parent();
+ }
+ }
+ });
+ };
+ }
+ this.logger = logger(console);
+ var specNames = [];
+ foreach(this.specs, function(spec, name){
+ specNames.push(name);
+ }, this);
+ specNames.sort();
+ var self = this;
+ function callback(){
+ var next = specNames.shift();
+ if(next) {
+ self.execute(next, callback);
+ }
+ };
+ callback();
+ },
+
+ addStep: function(name, step) {
+ this.currentSpec.steps.push({name:name, fn:step});
+ },
+
+ execute: function(name, callback) {
+ var spec = this.specs[name],
+ self = this,
+ result = {
+ passed: false,
+ failed: false,
+ finished: false,
+ fail: function(error) {
+ result.passed = false;
+ result.failed = true;
+ result.error = error;
+ result.log('fail', isString(error) ? error : toJson(error)).fail();
+ }
+ },
+ specThis = createScope({
+ result: result,
+ testFrame: this.testFrame,
+ testWindow: this.testWindow
+ }, angularService, {});
+ this.self = specThis;
+ var stepLogger = this.logger('spec', name);
+ spec.nextStepIndex = 0;
+ function done() {
+ result.finished = true;
+ stepLogger.close();
+ self.self = null;
+ (callback||noop).call(specThis);
+ }
+ function next(){
+ var step = spec.steps[spec.nextStepIndex];
+ (result.log || {close:noop}).close();
+ result.log = null;
+ if (step) {
+ spec.nextStepIndex ++;
+ result.log = stepLogger('step', step.name);
+ try {
+ step.fn.call(specThis, next);
+ } catch (e) {
+ console.error(e);
+ result.fail(e);
+ done();
+ }
+ } else {
+ result.passed = !result.failed;
+ done();
+ }
+ };
+ next();
+ return specThis;
+ }
+}; \ No newline at end of file