aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorElliott Sprehn2010-10-18 14:02:18 -0700
committerElliott Sprehn2010-10-19 00:45:38 -0700
commite7e894a2e36e042be6d62af56b0f3126f4e4fc77 (patch)
tree5b9c8b94bf3e3935a3acd6a3c0ecb142c82f4b17 /test
parenta1fa23397f12e0b52838530a993f14491ad50869 (diff)
downloadangular.js-e7e894a2e36e042be6d62af56b0f3126f4e4fc77.tar.bz2
Significantly clean up the way the scenario DSL works and implement many more DSL statements.
- "this" always means the current chain scope inside a DSL - addFutureAction callbacks now take ($window, $document, done) - $document has a special method elements() that uses the currently selected nodes in the document as defined by using() statements. - $document.elements() allows placeholder insertion into selectors to make them more readable. ex. $document.elements('input[name="$1"]', myVar) will substitute the value of myVar for $1 in the selector. Subsequent arguments are $2 and so on. - $document.elements() results have a special method trigger(event) which should be used to events. This method implements some hacks to make sure browser UI controls update and the correct angular events fire. - futures now allow custom formatting. By default any chain that results in a future can use toJson() or fromJson() to convert the future value to and from json. A custom parser can be provided with parsedWith(fn) where fn is a callback(value) that must return the parsed result. Note: The entire widgets.html UI is now able to be controlled and asserted through DSL statements!!! Victory! :)
Diffstat (limited to 'test')
-rw-r--r--test/scenario/ApplicationSpec.js13
-rw-r--r--test/scenario/FutureSpec.js38
-rw-r--r--test/scenario/SpecRunnerSpec.js17
-rw-r--r--test/scenario/dslSpec.js (renamed from test/scenario/DSLSpec.js)196
4 files changed, 210 insertions, 54 deletions
diff --git a/test/scenario/ApplicationSpec.js b/test/scenario/ApplicationSpec.js
index 706fbc36..2fb9881f 100644
--- a/test/scenario/ApplicationSpec.js
+++ b/test/scenario/ApplicationSpec.js
@@ -18,20 +18,21 @@ describe('angular.scenario.Application', function() {
testDocument = $document;
});
app.navigateTo('http://www.google.com/');
- app.executeAction(function($document, $window) {
+ app.executeAction(function($window, $document) {
expect($window).not.toEqual(testWindow);
expect($document).not.toEqual(testDocument);
});
});
- it('should execute callback on $window of frame', function() {
+ it('should execute callback with correct arguments', function() {
var testWindow = {document: {}};
app.getWindow = function() {
return testWindow;
};
- app.executeAction(function($document, $window) {
- expect(this).toEqual($window);
- expect(this).toEqual(testWindow);
+ app.executeAction(function($window, $document) {
+ expect(this).toEqual(app);
+ expect($document).toEqual(_jQuery($window.document));
+ expect($window).toEqual(testWindow);
});
});
@@ -52,7 +53,7 @@ describe('angular.scenario.Application', function() {
it('should call onload handler when frame loads', function() {
var called;
- app.getFrame = function() {
+ app.getFrame = function() {
// Mock a little jQuery
var result = {
remove: function() {
diff --git a/test/scenario/FutureSpec.js b/test/scenario/FutureSpec.js
index ae475779..1e6af7a1 100644
--- a/test/scenario/FutureSpec.js
+++ b/test/scenario/FutureSpec.js
@@ -1,13 +1,14 @@
describe('angular.scenario.Future', function() {
var future;
- it('should set the name and behavior', function() {
+ it('should set the sane defaults', function() {
var behavior = function() {};
var future = new angular.scenario.Future('test name', behavior);
expect(future.name).toEqual('test name');
expect(future.behavior).toEqual(behavior);
expect(future.value).toBeUndefined();
expect(future.fulfilled).toBeFalsy();
+ expect(future.parser).toEqual(angular.identity);
});
it('should be fulfilled after execution and done callback', function() {
@@ -35,4 +36,39 @@ describe('angular.scenario.Future', function() {
future.execute(angular.noop);
expect(future.value).toEqual(10);
});
+
+ it('should parse json with fromJson', function() {
+ var future = new angular.scenario.Future('test name', function(done) {
+ done(null, "{test: 'foo'}");
+ });
+ future.fromJson().execute(angular.noop);
+ expect(future.value).toEqual({test: 'foo'});
+ });
+
+ it('should convert to json with toJson', function() {
+ var future = new angular.scenario.Future('test name', function(done) {
+ done(null, {test: 'foo'});
+ });
+ future.toJson().execute(angular.noop);
+ expect(future.value).toEqual('{"test":"foo"}');
+ });
+
+ it('should convert with custom parser', function() {
+ var future = new angular.scenario.Future('test name', function(done) {
+ done(null, 'foo');
+ });
+ future.parsedWith(function(value) {
+ return value.toUpperCase();
+ }).execute(angular.noop);
+ expect(future.value).toEqual('FOO');
+ });
+
+ it('should pass error if parser fails', function() {
+ var future = new angular.scenario.Future('test name', function(done) {
+ done(null, '{');
+ });
+ future.fromJson().execute(function(error, result) {
+ expect(error).toBeDefined();
+ });
+ });
});
diff --git a/test/scenario/SpecRunnerSpec.js b/test/scenario/SpecRunnerSpec.js
index 0926c3f8..e62bb392 100644
--- a/test/scenario/SpecRunnerSpec.js
+++ b/test/scenario/SpecRunnerSpec.js
@@ -42,7 +42,7 @@ function ApplicationMock($window) {
}
ApplicationMock.prototype = {
executeAction: function(callback) {
- callback.call(this.$window);
+ callback.call(this.$window, _jQuery(this.$window.document), this.$window);
}
};
@@ -59,15 +59,15 @@ describe('angular.scenario.SpecRunner', function() {
it('should bind futures to the spec', function() {
runner.addFuture('test future', function(done) {
- this.application.value = 10;
+ this.value = 10;
done();
});
runner.futures[0].execute(angular.noop);
- expect(runner.application.value).toEqual(10);
+ expect(runner.value).toEqual(10);
});
it('should pass done to future action behavior', function() {
- runner.addFutureAction('test future', function(done) {
+ runner.addFutureAction('test future', function($window, $document, done) {
expect(angular.isFunction(done)).toBeTruthy();
done(10, 20);
});
@@ -77,15 +77,6 @@ describe('angular.scenario.SpecRunner', function() {
});
});
- it('should pass execute future action on the $window', function() {
- runner.addFutureAction('test future', function(done) {
- this.test = 'test value';
- done();
- });
- runner.futures[0].execute(angular.noop);
- expect($window.test).toEqual('test value');
- });
-
it('should execute spec function and notify UI', function() {
var finished = false;
var ui = new UIMock();
diff --git a/test/scenario/DSLSpec.js b/test/scenario/dslSpec.js
index b144a3ce..a30fe165 100644
--- a/test/scenario/DSLSpec.js
+++ b/test/scenario/dslSpec.js
@@ -12,11 +12,20 @@ AngularMock.prototype.reset = function() {
AngularMock.prototype.element = function(node) {
this.log.push('element(' + node.nodeName.toLowerCase() + ')');
- return this;
-};
-
-AngularMock.prototype.trigger = function(value) {
- this.log.push('element().trigger(' + value + ')');
+ var mock = this;
+ return {
+ selector: '',
+ attr: function(name, value) {
+ mock.log.push('attr(' + name + (angular.isDefined(value) ? ',' + value : '') + ')');
+ return _jQuery.fn.attr.apply(_jQuery(node), arguments);
+ },
+ trigger: function(type) {
+ mock.log.push('element().trigger(' + type + ')');
+ //TODO(esprehn): See the HACK!! in the SpecRunner. This avoids
+ // triggering the second part of the hack in tests
+ delete this.selector;
+ }
+ };
};
AngularMock.prototype.$browser = function() {
@@ -53,6 +62,12 @@ describe("angular.scenario.dsl", function() {
$root.futureResult = result;
});
};
+ $root.dsl = {};
+ angular.foreach(angular.scenario.dsl, function(fn, name) {
+ $root.dsl[name] = function() {
+ return fn.call($root).apply($root, arguments);
+ };
+ });
$root.application = new angular.scenario.Application($window.document);
$root.application.getWindow = function() {
return $window;
@@ -75,7 +90,7 @@ describe("angular.scenario.dsl", function() {
});
it('should pause for specified seconds', function() {
- angular.scenario.dsl.pause.call($root).call($root, 10);
+ $root.dsl.pause(10);
expect($root.timerValue).toEqual(10000);
expect($root.futureResult).toEqual(10000);
});
@@ -84,11 +99,11 @@ describe("angular.scenario.dsl", function() {
describe('Expect', function() {
it('should chain and execute matcher', function() {
var future = {value: 10};
- var result = angular.scenario.dsl.expect.call($root).call($root, future);
+ var result = $root.dsl.expect(future);
result.toEqual(10);
expect($root.futureError).toBeUndefined();
expect($root.futureResult).toBeUndefined();
- result = angular.scenario.dsl.expect.call($root).call($root, future);
+ result = $root.dsl.expect(future);
result.toEqual(20);
expect($root.futureError).toBeDefined();
});
@@ -96,27 +111,27 @@ describe("angular.scenario.dsl", function() {
describe('NavigateTo', function() {
it('should allow a string url', function() {
- angular.scenario.dsl.navigateTo.call($root).call($root, 'http://myurl');
+ $root.dsl.navigateTo('http://myurl');
expect($window.location).toEqual('http://myurl');
expect($root.futureResult).toEqual('http://myurl');
});
it('should allow a future url', function() {
var future = {name: 'future name', value: 'http://myurl'};
- angular.scenario.dsl.navigateTo.call($root).call($root, future);
+ $root.dsl.navigateTo(future);
expect($window.location).toEqual('http://myurl');
expect($root.futureResult).toEqual('http://myurl');
});
it('should complete if angular is missing from app frame', function() {
delete $window.angular;
- angular.scenario.dsl.navigateTo.call($root).call($root, 'http://myurl');
+ $root.dsl.navigateTo('http://myurl');
expect($window.location).toEqual('http://myurl');
expect($root.futureResult).toEqual('http://myurl');
});
it('should wait for angular notify when no requests pending', function() {
- angular.scenario.dsl.navigateTo.call($root).call($root, 'url');
+ $root.dsl.navigateTo('url');
expect($window.angular.log).toContain('$brower.poll()');
expect($window.angular.log).
toContain('$brower.notifyWhenNoOutstandingRequests()');
@@ -143,24 +158,141 @@ describe("angular.scenario.dsl", function() {
remove();
});
+ describe('Select', function() {
+ it('should select single option', function() {
+ doc.append(
+ '<select name="test">' +
+ ' <option>A</option>' +
+ ' <option selected>B</option>' +
+ '</select>'
+ );
+ $root.dsl.select('test').option('A');
+ expect(_jQuery('[name="test"]').val()).toEqual('A');
+ });
+
+ it('should select multiple options', function() {
+ doc.append(
+ '<select name="test" multiple>' +
+ ' <option>A</option>' +
+ ' <option selected>B</option>' +
+ ' <option>C</option>' +
+ '</select>'
+ );
+ $root.dsl.select('test').options('A', 'B');
+ expect(_jQuery('[name="test"]').val()).toEqual(['A','B']);
+ });
+
+ it('should fail to select multiple options on non-multiple select', function() {
+ doc.append('<select name="test"></select>');
+ $root.dsl.select('test').options('A', 'B');
+ expect($root.futureError).toMatch(/did not match/);
+ });
+ });
+
+ describe('Element', function() {
+ it('should execute click', function() {
+ var clicked;
+ doc.append('<a href=""></a>');
+ doc.find('a').click(function() {
+ clicked = true;
+ });
+ $root.dsl.element('a').click();
+ });
+
+ it('should get attribute', function() {
+ doc.append('<div id="test" class="foo"></div>');
+ $root.dsl.element('#test').attr('class');
+ expect($root.futureResult).toEqual('foo');
+ });
+
+ it('should set attribute', function() {
+ doc.append('<div id="test" class="foo"></div>');
+ $root.dsl.element('#test').attr('class', 'bam');
+ expect(doc.find('div').attr('class')).toEqual('bam');
+ });
+
+ it('should get val', function() {
+ doc.append('<input value="bar">');
+ $root.dsl.element('input').val();
+ expect($root.futureResult).toEqual('bar');
+ });
+
+ it('should set val', function() {
+ doc.append('<input value="bar">');
+ $root.dsl.element('input').val('baz');
+ expect(doc.find('input').val()).toEqual('baz');
+ });
+
+ });
+
+ describe('Repeater', function() {
+ var chain;
+ beforeEach(function() {
+ doc.append(
+ '<ul>' +
+ ' <li ng:repeat-index="0"><span ng:bind="name">misko</span><span ng:bind="gender">male</span></li>' +
+ ' <li ng:repeat-index="1"><span ng:bind="name">felisa</span><span ng:bind="gender">female</span></li>' +
+ '</ul>'
+ );
+ chain = $root.dsl.repeater('ul li');
+ });
+
+ it('should get the row count', function() {
+ chain.count();
+ expect($root.futureResult).toEqual(2);
+ });
+
+ it('should get a row of bindings', function() {
+ chain.row(1);
+ expect($root.futureResult).toEqual(['felisa', 'female']);
+ });
+
+ it('should get a column of bindings', function() {
+ chain.column('gender');
+ expect($root.futureResult).toEqual(['male', 'female']);
+ });
+ });
+
describe('Binding', function() {
it('should select binding by name', function() {
doc.append('<span ng:bind="foo.bar">some value</span>');
- angular.scenario.dsl.binding.call($root).call($root, 'foo.bar');
+ $root.dsl.binding('foo.bar');
expect($root.futureResult).toEqual('some value');
});
+
+ it('should select binding in template by name', function() {
+ doc.append('<pre ng:bind-template="foo {{bar}} baz">foo some baz</pre>');
+ $root.dsl.binding('bar');
+ expect($root.futureResult).toEqual('foo some baz');
+ });
it('should return error if no binding exists', function() {
- angular.scenario.dsl.binding.call($root).call($root, 'foo.bar');
- expect($root.futureError).toMatch(/does not exist/);
+ $root.dsl.binding('foo.bar');
+ expect($root.futureError).toMatch(/did not match/);
+ });
+ });
+
+ describe('Using', function() {
+ it('should prefix selector in $document.elements()', function() {
+ var chain;
+ doc.append(
+ '<div id="test1"><input name="test.input" value="something"></div>' +
+ '<div id="test2"><input name="test.input" value="something"></div>'
+ );
+ chain = $root.dsl.using('div#test2');
+ chain.input('test.input').enter('foo');
+ expect($window.angular.log).toContain('element(input)');
+ expect($window.angular.log).toContain('element().trigger(change)');
+ var inputs = _jQuery('input[name="test.input"]');
+ expect(inputs.first().val()).toEqual('something');
+ expect(inputs.last().val()).toEqual('foo');
});
});
describe('Input', function() {
it('should change value in text input', function() {
doc.append('<input name="test.input" value="something">');
- var chain = angular.scenario.dsl.input.
- call($root).call($root, 'test.input');
+ var chain = $root.dsl.input('test.input');
chain.enter('foo');
expect($window.angular.log).toContain('element(input)');
expect($window.angular.log).toContain('element().trigger(change)');
@@ -168,18 +300,16 @@ describe("angular.scenario.dsl", function() {
});
it('should return error if no input exists', function() {
- var chain = angular.scenario.dsl.input.
- call($root).call($root, 'test.input');
+ var chain = $root.dsl.input('test.input');
chain.enter('foo');
- expect($root.futureError).toMatch(/does not exist/);
+ expect($root.futureError).toMatch(/did not match/);
});
it('should toggle checkbox state', function() {
doc.append('<input type="checkbox" name="test.input" checked>');
expect(_jQuery('input[name="test.input"]').
attr('checked')).toBeTruthy();
- var chain = angular.scenario.dsl.input.
- call($root).call($root, 'test.input');
+ var chain = $root.dsl.input('test.input');
chain.check();
expect($window.angular.log).toContain('element(input)');
expect($window.angular.log).toContain('element().trigger(click)');
@@ -193,25 +323,24 @@ describe("angular.scenario.dsl", function() {
attr('checked')).toBeTruthy();
});
- it('should return error if checkbox does not exist', function() {
- var chain = angular.scenario.dsl.input.
- call($root).call($root, 'test.input');
+ it('should return error if checkbox did not match', function() {
+ var chain = $root.dsl.input('test.input');
chain.check();
- expect($root.futureError).toMatch(/does not exist/);
+ expect($root.futureError).toMatch(/did not match/);
});
it('should select option from radio group', function() {
doc.append(
'<input type="radio" name="0@test.input" value="foo">' +
- '<input type="radio" name="0@test.input" value="bar" checked="checked">');
+ '<input type="radio" name="0@test.input" value="bar" checked="checked">'
+ );
// HACK! We don't know why this is sometimes false on chrome
_jQuery('input[name="0@test.input"][value="bar"]').attr('checked', true);
expect(_jQuery('input[name="0@test.input"][value="bar"]').
attr('checked')).toBeTruthy();
expect(_jQuery('input[name="0@test.input"][value="foo"]').
attr('checked')).toBeFalsy();
- var chain = angular.scenario.dsl.input.
- call($root).call($root, 'test.input');
+ var chain = $root.dsl.input('test.input');
chain.select('foo');
expect($window.angular.log).toContain('element(input)');
expect($window.angular.log).toContain('element().trigger(click)');
@@ -221,13 +350,12 @@ describe("angular.scenario.dsl", function() {
attr('checked')).toBeTruthy();
});
- it('should return error if radio button does not exist', function() {
- var chain = angular.scenario.dsl.input.
- call($root).call($root, 'test.input');
+ it('should return error if radio button did not match', function() {
+ var chain = $root.dsl.input('test.input');
chain.select('foo');
- expect($root.futureError).toMatch(/does not exist/);
+ expect($root.futureError).toMatch(/did not match/);
});
});
+
});
-
});