Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 8d635cf

Browse files
committed
Merge branch 'master' of github.com:angular/angular.js
2 parents 7673b2a + 86c2ef8 commit 8d635cf

File tree

9 files changed

+345
-166
lines changed

9 files changed

+345
-166
lines changed

Rakefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,10 @@ task :compile_scenario do
4545
src/apis.js \
4646
src/services.js \
4747
src/AngularPublic.js \
48-
src/scenario/Runner.js \
4948
src/scenario/DSL.js \
49+
src/scenario/Future.js \
50+
src/scenario/Matcher.js \
51+
src/scenario/Runner.js \
5052
src/scenario/angular.suffix \
5153
)
5254
css = %x(cat css/angular-scenario.css)

src/scenario/DSL.js

Lines changed: 62 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
angular.scenario.dsl.browser = {
22
navigateTo: function(url){
3-
$scenario.addStep('Navigate to: ' + url, function(done){
3+
return $scenario.addFuture('Navigate to: ' + url, function(done){
44
var self = this;
55
this.testFrame.load(function(){
66
self.testFrame.unbind();
77
self.testWindow = self.testFrame[0].contentWindow;
8-
self.testDocument = jQuery(self.testWindow.document);
8+
self.testDocument = self.jQuery(self.testWindow.document);
99
self.$browser = self.testWindow.angular.service.$browser();
10-
self.notifyWhenNoOutstandingRequests = bind(self.$browser, self.$browser.notifyWhenNoOutstandingRequests);
10+
self.notifyWhenNoOutstandingRequests =
11+
bind(self.$browser, self.$browser.notifyWhenNoOutstandingRequests);
1112
self.notifyWhenNoOutstandingRequests(done);
1213
});
1314
if (this.testFrame.attr('src') == url) {
@@ -20,19 +21,18 @@ angular.scenario.dsl.browser = {
2021
};
2122

2223
angular.scenario.dsl.input = function(selector) {
24+
var namePrefix = "input '" + selector + "'";
2325
return {
24-
enter: function(value){
25-
$scenario.addStep("Set input text of '" + selector + "' to '" +
26-
value + "'", function(done){
27-
var input = this.testDocument.find('input[name=' + selector + ']');
28-
input.val(value);
29-
this.testWindow.angular.element(input[0]).trigger('change');
30-
done();
26+
enter: function(value) {
27+
return $scenario.addFuture(namePrefix + " enter '" + value + "'", function(done) {
28+
var input = this.testDocument.find('input[name=' + selector + ']');
29+
input.val(value);
30+
this.testWindow.angular.element(input[0]).trigger('change');
31+
done();
3132
});
3233
},
33-
select: function(value){
34-
$scenario.addStep("Select radio '" + selector + "' to '" +
35-
value + "'", function(done){
34+
select: function(value) {
35+
return $scenario.addFuture(namePrefix + " select '" + value + "'", function(done) {
3636
var input = this.testDocument.
3737
find(':radio[name$=@' + selector + '][value=' + value + ']');
3838
jqLiteWrap(input[0]).trigger('click');
@@ -41,22 +41,56 @@ angular.scenario.dsl.input = function(selector) {
4141
});
4242
}
4343
};
44-
};
44+
},
4545

46-
angular.scenario.dsl.expect = {
47-
repeater: function(selector) {
48-
return {
49-
count: {
50-
toEqual: function(number) {
51-
$scenario.addStep("Expect that there are " + number + " items in Repeater with selector '" + selector + "'", function(done) {
52-
var items = this.testDocument.find(selector);
53-
if (items.length != number) {
54-
this.result.fail("Expected " + number + " but was " + items.length);
55-
}
56-
done();
46+
angular.scenario.dsl.repeater = function(selector) {
47+
var namePrefix = "repeater '" + selector + "'";
48+
return {
49+
count: function() {
50+
return $scenario.addFuture(namePrefix + ' count', function(done) {
51+
done(this.testDocument.find(selector).size());
52+
});
53+
},
54+
collect: function() {
55+
return $scenario.addFuture(namePrefix + ' collect', function(done) {
56+
var self = this;
57+
var doCollect = bind(this, function() {
58+
var repeaterArray = [];
59+
this.testDocument.find(selector).each(function(index) {
60+
var element = angular.extend(self.jQuery(this),
61+
{bindings: [],
62+
boundTo: function(name) { return this.bindings[name]; }}
63+
);
64+
element.find('*').each(function(index) {
65+
var bindName = self.jQuery(this).attr('ng:bind');
66+
if (bindName) {
67+
element.bindings[bindName] = self.jQuery(this).text();
68+
}
69+
});
70+
repeaterArray[index] = element;
5771
});
58-
}
72+
return repeaterArray;
73+
});
74+
done(doCollect());
75+
});
76+
}
77+
};
78+
};
79+
80+
angular.scenario.dsl.element = function(selector) {
81+
var nameSuffix = "element '" + selector + "'";
82+
return $scenario.addFuture('Find ' + nameSuffix, function(done) {
83+
var self = this;
84+
var element = angular.extend(this.testDocument.find(selector), {
85+
bindings: [],
86+
boundTo: function(name) { return this.bindings[name]; }
87+
});
88+
element.find('*').each(function(index) {
89+
var bindName = self.jQuery(this).attr('ng:bind');
90+
if (bindName) {
91+
element.bindings[bindName] = self.jQuery(this).text();
5992
}
60-
};
61-
}
93+
});
94+
done(element);
95+
});
6296
};

src/scenario/Future.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
function Future(name, behavior) {
2+
this.name = name;
3+
this.behavior = behavior;
4+
this.fulfilled = false;
5+
this.value = undefined;
6+
}
7+
8+
Future.prototype = {
9+
fulfill: function(value) {
10+
this.fulfilled = true;
11+
this.value = value;
12+
}
13+
};

src/scenario/Matcher.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
function Matcher(scope, future, logger) {
2+
var self = scope.$scenario = this;
3+
this.logger = logger;
4+
this.future = future;
5+
}
6+
7+
Matcher.addMatcher = function(name, matcher) {
8+
Matcher.prototype[name] = function(expected) {
9+
var future = this.future;
10+
$scenario.addFuture(
11+
'expect ' + future.name + ' ' + name + ' ' + expected,
12+
function(done){
13+
if (!matcher(future.value, expected))
14+
throw "Expected " + expected + ' but was ' + future.value;
15+
done();
16+
}
17+
);
18+
};
19+
};
20+
21+
Matcher.addMatcher('toEqual', function(a,b) { return a == b; });

src/scenario/Runner.js

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ angular.scenario.Runner = function(scope, jQuery){
88
this.scope.$testrun = {done: false, results: []};
99

1010
var specs = this.specs = {};
11+
this.currentSpec = {name: '', futures: []};
1112
var path = [];
1213
this.scope.describe = function(name, body){
1314
path.push(name);
@@ -22,17 +23,20 @@ angular.scenario.Runner = function(scope, jQuery){
2223
this.scope.afterEach = function(body) {
2324
afterEach = body;
2425
};
26+
this.scope.expect = function(future) {
27+
return new Matcher(self, future, self.logger);
28+
};
2529
this.scope.it = function(name, body) {
2630
var specName = path.join(' ') + ': it ' + name;
2731
self.currentSpec = specs[specName] = {
2832
name: specName,
29-
steps:[]
33+
futures: []
3034
};
3135
try {
3236
beforeEach();
3337
body();
3438
} catch(err) {
35-
self.addStep(err.message || 'ERROR', function(){
39+
self.addFuture(err.message || 'ERROR', function(){
3640
throw err;
3741
});
3842
} finally {
@@ -107,14 +111,16 @@ angular.scenario.Runner.prototype = {
107111
callback();
108112
},
109113

110-
addStep: function(name, step) {
111-
this.currentSpec.steps.push({name:name, fn:step});
114+
addFuture: function(name, behavior) {
115+
var future = new Future(name, behavior);
116+
this.currentSpec.futures.push(future);
117+
return future;
112118
},
113119

114120
execute: function(name, callback) {
115121
var spec = this.specs[name],
116122
self = this,
117-
stepsDone = [],
123+
futuresFulfilled = [],
118124
result = {
119125
passed: false,
120126
failed: false,
@@ -128,33 +134,37 @@ angular.scenario.Runner.prototype = {
128134
},
129135
specThis = createScope({
130136
result: result,
137+
jQuery: this.jQuery,
131138
testFrame: this.testFrame,
132139
testWindow: this.testWindow
133140
}, angularService, {});
134141
this.self = specThis;
135-
var stepLogger = this.logger('spec', name);
136-
spec.nextStepIndex = 0;
142+
var futureLogger = this.logger('spec', name);
143+
spec.nextFutureIndex = 0;
137144
function done() {
138145
result.finished = true;
139-
stepLogger.close();
146+
futureLogger.close();
140147
self.self = null;
141148
(callback||noop).call(specThis);
142149
}
143-
function next(){
144-
var step = spec.steps[spec.nextStepIndex];
150+
function next(value){
151+
if (spec.nextFutureIndex > 0) {
152+
spec.futures[spec.nextFutureIndex - 1].fulfill(value);
153+
}
154+
var future = spec.futures[spec.nextFutureIndex];
145155
(result.log || {close:noop}).close();
146156
result.log = null;
147-
if (step) {
148-
spec.nextStepIndex ++;
149-
result.log = stepLogger('step', step.name);
150-
stepsDone.push(step.name);
157+
if (future) {
158+
spec.nextFutureIndex ++;
159+
result.log = futureLogger('future', future.name);
160+
futuresFulfilled.push(future.name);
151161
try {
152-
step.fn.call(specThis, next);
162+
future.behavior.call(specThis, next);
153163
} catch (e) {
154164
console.error(e);
155165
result.fail(e);
156166
self.scope.$testrun.results.push(
157-
{name: name, passed: false, error: e, steps: stepsDone});
167+
{name: name, passed: false, error: e, steps: futuresFulfilled});
158168
done();
159169
}
160170
} else {
@@ -163,7 +173,7 @@ angular.scenario.Runner.prototype = {
163173
name: name,
164174
passed: !result.failed,
165175
error: result.error,
166-
steps: stepsDone});
176+
steps: futuresFulfilled});
167177
done();
168178
}
169179
};

0 commit comments

Comments
 (0)