mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-16 23:30:23 +00:00
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! :)
This commit is contained in:
parent
a1fa23397f
commit
e7e894a2e3
13 changed files with 648 additions and 256 deletions
|
|
@ -1,58 +1,55 @@
|
|||
describe('widgets', function() {
|
||||
it('should verify that basic widgets work', function(){
|
||||
navigateTo('widgets.html');
|
||||
input('text.basic').enter('Carlos');
|
||||
|
||||
using('#text-basic-box').input('text.basic').enter('Carlos');
|
||||
expect(binding('text.basic')).toEqual('Carlos');
|
||||
pause(2);
|
||||
input('text.basic').enter('Carlos Santana');
|
||||
pause(2);
|
||||
expect(binding('text.basic')).not().toEqual('Carlos Boozer');
|
||||
pause(2);
|
||||
|
||||
input('text.password').enter('secret');
|
||||
expect(binding('text.password')).toEqual('secret');
|
||||
|
||||
expect(binding('text.hidden')).toEqual('hiddenValue');
|
||||
|
||||
expect(binding('gender')).toEqual('male');
|
||||
pause(2);
|
||||
input('gender').select('female');
|
||||
expect(binding('gender')).toEqual('female');
|
||||
pause(2);
|
||||
});
|
||||
describe('do it again', function() {
|
||||
it('should verify that basic widgets work', function(){
|
||||
navigateTo('widgets.html');
|
||||
input('text.basic').enter('Carlos');
|
||||
expect(binding('text.basic')).toEqual('Carlos');
|
||||
pause(2);
|
||||
input('text.basic').enter('Carlos Santana');
|
||||
pause(2);
|
||||
expect(binding('text.basic')).toEqual('Carlos Santana');
|
||||
pause(2);
|
||||
input('text.password').enter('secret');
|
||||
expect(binding('text.password')).toEqual('secret');
|
||||
expect(binding('text.hidden')).toEqual('hiddenValue');
|
||||
expect(binding('gender')).toEqual('male');
|
||||
pause(2);
|
||||
input('gender').select('female');
|
||||
expect(binding('gender')).toEqual('female');
|
||||
pause(2);
|
||||
});
|
||||
});
|
||||
it('should verify that basic widgets work', function(){
|
||||
navigateTo('widgets.html');
|
||||
input('text.basic').enter('Carlos');
|
||||
expect(binding('text.basic')).toEqual('Carlos');
|
||||
pause(2);
|
||||
input('text.basic').enter('Carlos Santana');
|
||||
pause(2);
|
||||
expect(binding('text.basic')).toEqual('Carlos Santana');
|
||||
pause(2);
|
||||
input('text.password').enter('secret');
|
||||
expect(binding('text.password')).toEqual('secret');
|
||||
expect(binding('text.hidden')).toEqual('hiddenValue');
|
||||
expect(binding('gender')).toEqual('male');
|
||||
pause(2);
|
||||
input('gender').select('female');
|
||||
expect(binding('gender')).toEqual('female');
|
||||
pause(2);
|
||||
expect(using('#gender-box').binding('gender')).toEqual('female');
|
||||
|
||||
expect(repeater('#repeater-row ul li').count()).toEqual(2);
|
||||
expect(repeater('#repeater-row ul li').row(1)).toEqual(['adam']);
|
||||
expect(repeater('#repeater-row ul li').column('name')).toEqual(['misko', 'adam']);
|
||||
|
||||
select('select').option('B');
|
||||
expect(binding('select')).toEqual('B');
|
||||
|
||||
select('multiselect').options('A', 'C');
|
||||
expect(binding('multiselect').fromJson()).toEqual(['A', 'C']);
|
||||
|
||||
expect(binding('button').fromJson()).toEqual({'count': 0});
|
||||
element('form a').click();
|
||||
expect(binding('button').fromJson()).toEqual({'count': 1});
|
||||
element('input[value="submit"]').click();
|
||||
expect(binding('button').fromJson()).toEqual({'count': 2});
|
||||
element('input[value="button"]').click();
|
||||
expect(binding('button').fromJson()).toEqual({'count': 3});
|
||||
element('input[type="image"]').click();
|
||||
expect(binding('button').fromJson()).toEqual({'count': 4});
|
||||
|
||||
/**
|
||||
* Custom value parser for futures.
|
||||
*/
|
||||
function checkboxParser(value) {
|
||||
return angular.fromJson(value.substring(value.indexOf('=')+1));
|
||||
}
|
||||
|
||||
input('checkbox.tea').check();
|
||||
expect(binding('checkbox').parsedWith(checkboxParser)).toEqual({coffee: false, tea: false});
|
||||
input('checkbox.coffee').check();
|
||||
expect(binding('checkbox').parsedWith(checkboxParser)).toEqual({coffee: true, tea: false});
|
||||
input('checkbox.tea').check();
|
||||
input('checkbox.tea').check();
|
||||
input('checkbox.tea').check();
|
||||
expect(binding('checkbox').parsedWith(checkboxParser)).toEqual({coffee: true, tea: true});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
<html xmlns:ng="http://angularjs.org">
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="style.css"/>
|
||||
<script type="text/javascript" src="../lib/jquery/jquery-1.4.2.js"></script>
|
||||
<script type="text/javascript" src="../src/angular-bootstrap.js" ng:autobind></script>
|
||||
</head>
|
||||
<body ng:init="$window.$scope = this">
|
||||
|
|
@ -14,7 +15,7 @@
|
|||
<tr><th colspan="3">Input text field</th></tr>
|
||||
<tr>
|
||||
<td>basic</td>
|
||||
<td>
|
||||
<td id="text-basic-box">
|
||||
<input type="text" name="text.basic"/>
|
||||
</td>
|
||||
<td>text.basic={{text.basic}}</td>
|
||||
|
|
@ -30,7 +31,7 @@
|
|||
<td>text.hidden={{text.hidden}}</td>
|
||||
</tr>
|
||||
<tr><th colspan="3">Input selection field</th></tr>
|
||||
<tr>
|
||||
<tr id="gender-box">
|
||||
<td>radio</td>
|
||||
<td>
|
||||
<input type="radio" name="gender" value="female"/> Female <br/>
|
||||
|
|
@ -78,13 +79,13 @@
|
|||
<input type="button" value="button" ng:change="button.count = button.count + 1"/> <br/>
|
||||
<input type="submit" value="submit" ng:change="button.count = button.count + 1"/><br/>
|
||||
<input type="image" src="" ng:change="button.count = button.count + 1"/><br/>
|
||||
<a href="" ng:click="button.count = button.count + 1">action</a>
|
||||
<a href="" ng:click="button.count = button.count + 1">action</a>
|
||||
</form>
|
||||
</td>
|
||||
<td>button={{button}}</td>
|
||||
</tr>
|
||||
<tr><th colspan="3">Repeaters</th></tr>
|
||||
<tr>
|
||||
<tr id="repeater-row">
|
||||
<td>ng:repeat</td>
|
||||
<td>
|
||||
<ul>
|
||||
|
|
|
|||
|
|
@ -119,10 +119,14 @@ JQLite.prototype = {
|
|||
},
|
||||
|
||||
trigger: function(type) {
|
||||
var evnt = document.createEvent('MouseEvents'),
|
||||
element = this[0];
|
||||
evnt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element);
|
||||
element.dispatchEvent(evnt);
|
||||
if (msie) {
|
||||
this[0].fireEvent('on' + type);
|
||||
} else {
|
||||
var evnt = document.createEvent('MouseEvents'),
|
||||
element = this[0];
|
||||
evnt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element);
|
||||
element.dispatchEvent(evnt);
|
||||
}
|
||||
},
|
||||
|
||||
replaceWith: function(replaceNode) {
|
||||
|
|
@ -249,10 +253,6 @@ if (msie) {
|
|||
if (isDefined(value)) e.innerText = value;
|
||||
return e.innerText;
|
||||
}
|
||||
},
|
||||
|
||||
trigger: function(type) {
|
||||
this[0].fireEvent('on' + type);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,5 +47,5 @@ angular.scenario.Application.prototype.navigateTo = function(url, onloadFn) {
|
|||
*/
|
||||
angular.scenario.Application.prototype.executeAction = function(action) {
|
||||
var $window = this.getWindow();
|
||||
return action.call($window, _jQuery($window.document), $window);
|
||||
return action.call(this, $window, _jQuery($window.document));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,134 +0,0 @@
|
|||
/**
|
||||
* Shared DSL statements that are useful to all scenarios.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* pause(seconds) pauses the test for specified number of seconds
|
||||
*/
|
||||
angular.scenario.dsl('pause', function() {
|
||||
return function(time) {
|
||||
return this.addFuture('pause for ' + time + ' seconds', function(done) {
|
||||
this.setTimeout(function() { done(null, time * 1000); }, time * 1000);
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* expect(future).{matcher} where matcher is one of the matchers defined
|
||||
* with angular.scenario.matcher
|
||||
*
|
||||
* ex. expect(binding("name")).toEqual("Elliott")
|
||||
*/
|
||||
angular.scenario.dsl('expect', function() {
|
||||
var chain = angular.extend({}, angular.scenario.matcher);
|
||||
|
||||
chain.not = function() {
|
||||
this.inverse = true;
|
||||
return chain;
|
||||
};
|
||||
|
||||
return function(future) {
|
||||
this.future = future;
|
||||
return chain;
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* navigateTo(future|string) where url a string or future with a value
|
||||
* of a URL to navigate to
|
||||
*/
|
||||
angular.scenario.dsl('navigateTo', function() {
|
||||
return function(url) {
|
||||
var application = this.application;
|
||||
var name = url;
|
||||
if (url.name) {
|
||||
name = ' value of ' + url.name;
|
||||
}
|
||||
return this.addFuture('navigate to ' + name, function(done) {
|
||||
application.navigateTo(url.value || url, function() {
|
||||
application.executeAction(function() {
|
||||
if (this.angular) {
|
||||
var $browser = this.angular.service.$browser();
|
||||
$browser.poll();
|
||||
$browser.notifyWhenNoOutstandingRequests(function() {
|
||||
done(null, url.value || url);
|
||||
});
|
||||
} else {
|
||||
done(null, url.value || url);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* input(name).enter(value) enters value in input with specified name
|
||||
* input(name).check() checks checkbox
|
||||
* input(name).select(value) selects the readio button with specified name/value
|
||||
*/
|
||||
angular.scenario.dsl('input', function() {
|
||||
var chain = {};
|
||||
|
||||
chain.enter = function(value) {
|
||||
var spec = this;
|
||||
return this.addFutureAction("input '" + this.name + "' enter '" + value + "'", function(done) {
|
||||
var input = _jQuery(this.document).find('input[name=' + spec.name + ']');
|
||||
if (!input.length)
|
||||
return done("Input named '" + spec.name + "' does not exist.");
|
||||
input.val(value);
|
||||
this.angular.element(input[0]).trigger('change');
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
||||
chain.check = function() {
|
||||
var spec = this;
|
||||
return this.addFutureAction("checkbox '" + this.name + "' toggle", function(done) {
|
||||
var input = _jQuery(this.document).
|
||||
find('input:checkbox[name=' + spec.name + ']');
|
||||
if (!input.length)
|
||||
return done("Input named '" + spec.name + "' does not exist.");
|
||||
this.angular.element(input[0]).trigger('click');
|
||||
input.attr('checked', !input.attr('checked'));
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
||||
chain.select = function(value) {
|
||||
var spec = this;
|
||||
return this.addFutureAction("radio button '" + this.name + "' toggle '" + value + "'", function(done) {
|
||||
var input = _jQuery(this.document).
|
||||
find('input:radio[name$="@' + spec.name + '"][value="' + value + '"]');
|
||||
if (!input.length)
|
||||
return done("Input named '" + spec.name + "' does not exist.");
|
||||
this.angular.element(input[0]).trigger('click');
|
||||
input.attr('checked', !input.attr('checked'));
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
||||
return function(name) {
|
||||
this.name = name;
|
||||
return chain;
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* binding(name) returns the value of a binding
|
||||
*/
|
||||
angular.scenario.dsl('binding', function() {
|
||||
return function(name) {
|
||||
return this.addFutureAction("select binding '" + name + "'", function(done) {
|
||||
var element = _jQuery(this.document).find('[ng\\:bind="' + name + '"]');
|
||||
if (!element.length)
|
||||
return done("Binding named '" + name + "' does not exist.");
|
||||
done(null, element.text());
|
||||
});
|
||||
};
|
||||
});
|
||||
|
|
@ -6,6 +6,7 @@ angular.scenario.Future = function(name, behavior) {
|
|||
this.behavior = behavior;
|
||||
this.fulfilled = false;
|
||||
this.value = undefined;
|
||||
this.parser = angular.identity;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -16,7 +17,38 @@ angular.scenario.Future = function(name, behavior) {
|
|||
angular.scenario.Future.prototype.execute = function(doneFn) {
|
||||
this.behavior(angular.bind(this, function(error, result) {
|
||||
this.fulfilled = true;
|
||||
if (result) {
|
||||
try {
|
||||
result = this.parser(result);
|
||||
} catch(e) {
|
||||
error = e;
|
||||
}
|
||||
}
|
||||
this.value = error || result;
|
||||
doneFn(error, result);
|
||||
}));
|
||||
};
|
||||
|
||||
/**
|
||||
* Configures the future to convert it's final with a function fn(value)
|
||||
*/
|
||||
angular.scenario.Future.prototype.parsedWith = function(fn) {
|
||||
this.parser = fn;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Configures the future to parse it's final value from JSON
|
||||
* into objects.
|
||||
*/
|
||||
angular.scenario.Future.prototype.fromJson = function() {
|
||||
return this.parsedWith(angular.fromJson);
|
||||
};
|
||||
|
||||
/**
|
||||
* Configures the future to convert it's final value from objects
|
||||
* into JSON.
|
||||
*/
|
||||
angular.scenario.Future.prototype.toJson = function() {
|
||||
return this.parsedWith(angular.toJson);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -82,14 +82,36 @@ angular.scenario.Runner.prototype.run = function(ui, application, specRunnerClas
|
|||
$root.setTimeout = function() {
|
||||
return self.$window.setTimeout.apply(self.$window, arguments);
|
||||
};
|
||||
asyncForEach(specs, angular.bind(this, function(spec, specDone) {
|
||||
asyncForEach(specs, function(spec, specDone) {
|
||||
var dslCache = {};
|
||||
var runner = angular.scope($root);
|
||||
runner.$become(specRunnerClass);
|
||||
angular.foreach(angular.scenario.dsl, angular.bind(this, function(fn, key) {
|
||||
this.$window[key] = function() {
|
||||
return fn.call($root).apply(angular.scope(runner), arguments);
|
||||
angular.foreach(angular.scenario.dsl, function(fn, key) {
|
||||
dslCache[key] = fn.call($root);
|
||||
});
|
||||
angular.foreach(angular.scenario.dsl, function(fn, key) {
|
||||
self.$window[key] = function() {
|
||||
var scope = angular.scope(runner);
|
||||
|
||||
// Make the dsl accessible on the current chain
|
||||
scope.dsl = {};
|
||||
angular.foreach(dslCache, function(fn, key) {
|
||||
scope.dsl[key] = function() {
|
||||
return dslCache[key].apply(scope, arguments);
|
||||
};
|
||||
});
|
||||
|
||||
// Make these methods work on the current chain
|
||||
scope.addFuture = function() {
|
||||
return angular.scenario.SpecRunner.prototype.addFuture.apply(scope, arguments);
|
||||
};
|
||||
scope.addFutureAction = function() {
|
||||
return angular.scenario.SpecRunner.prototype.addFutureAction.apply(scope, arguments);
|
||||
};
|
||||
|
||||
return scope.dsl[key].apply(scope, arguments);
|
||||
};
|
||||
}));
|
||||
});
|
||||
runner.run(ui, spec, specDone);
|
||||
}), specsDone || angular.noop);
|
||||
}, specsDone || angular.noop);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ angular.scenario.SpecRunner.prototype.run = function(ui, spec, specDone) {
|
|||
});
|
||||
} catch (e) {
|
||||
stepUI.error(e);
|
||||
rethrow(e);
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
function(e) {
|
||||
|
|
@ -71,8 +71,56 @@ angular.scenario.SpecRunner.prototype.addFuture = function(name, behavior) {
|
|||
*/
|
||||
angular.scenario.SpecRunner.prototype.addFutureAction = function(name, behavior) {
|
||||
return this.addFuture(name, function(done) {
|
||||
this.application.executeAction(function() {
|
||||
behavior.call(this, done);
|
||||
});
|
||||
this.application.executeAction(angular.bind(this, function($window, $document) {
|
||||
|
||||
$document.elements = angular.bind(this, function(selector) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
if (this.selector) {
|
||||
selector = this.selector + ' ' + (selector || '');
|
||||
}
|
||||
angular.foreach(args, function(value, index) {
|
||||
selector = selector.replace('$' + (index + 1), value);
|
||||
});
|
||||
var result = $document.find(selector);
|
||||
if (!result.length) {
|
||||
throw {
|
||||
type: 'selector',
|
||||
message: 'Selector ' + selector + ' did not match any elements.'
|
||||
};
|
||||
}
|
||||
|
||||
result.trigger = function(type) {
|
||||
result.each(function(index, node) {
|
||||
var element = $window.angular.element(node);
|
||||
//TODO(esprehn): HACK!!! Something is broken in angular event dispatching
|
||||
// and if the real jQuery is used we need to set the attribtue after too
|
||||
if (angular.isDefined(element.selector)) {
|
||||
if (type === 'click' && node.nodeName.toLowerCase() === 'input') {
|
||||
element.attr('checked', !element.attr('checked'));
|
||||
}
|
||||
}
|
||||
//TODO(esprehn): HACK!! See above comment.
|
||||
element.trigger(type);
|
||||
if (angular.isDefined(element.selector)) {
|
||||
if (type === 'click' && node.nodeName.toLowerCase() === 'input') {
|
||||
element.attr('checked', !element.attr('checked'));
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
try {
|
||||
behavior.call(this, $window, $document, done);
|
||||
} catch(e) {
|
||||
if (e.type && e.type === 'selector') {
|
||||
done(e.message);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
|
|
|||
270
src/scenario/dsl.js
Normal file
270
src/scenario/dsl.js
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
/**
|
||||
* Shared DSL statements that are useful to all scenarios.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* pause(seconds) pauses the test for specified number of seconds
|
||||
*/
|
||||
angular.scenario.dsl('pause', function() {
|
||||
return function(time) {
|
||||
return this.addFuture('pause for ' + time + ' seconds', function(done) {
|
||||
this.setTimeout(function() { done(null, time * 1000); }, time * 1000);
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* expect(future).{matcher} where matcher is one of the matchers defined
|
||||
* with angular.scenario.matcher
|
||||
*
|
||||
* ex. expect(binding("name")).toEqual("Elliott")
|
||||
*/
|
||||
angular.scenario.dsl('expect', function() {
|
||||
var chain = angular.extend({}, angular.scenario.matcher);
|
||||
|
||||
chain.not = function() {
|
||||
this.inverse = true;
|
||||
return chain;
|
||||
};
|
||||
|
||||
return function(future) {
|
||||
this.future = future;
|
||||
return chain;
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* navigateTo(future|string) where url a string or future with a value
|
||||
* of a URL to navigate to
|
||||
*/
|
||||
angular.scenario.dsl('navigateTo', function() {
|
||||
return function(url) {
|
||||
var application = this.application;
|
||||
var name = url;
|
||||
if (url.name) {
|
||||
name = ' value of ' + url.name;
|
||||
}
|
||||
return this.addFuture('navigate to ' + name, function(done) {
|
||||
application.navigateTo(url.value || url, function() {
|
||||
application.executeAction(function($window) {
|
||||
if ($window.angular) {
|
||||
var $browser = $window.angular.service.$browser();
|
||||
$browser.poll();
|
||||
$browser.notifyWhenNoOutstandingRequests(function() {
|
||||
done(null, url.value || url);
|
||||
});
|
||||
} else {
|
||||
done(null, url.value || url);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* using(selector) scopes the next DSL element selection
|
||||
*
|
||||
* ex.
|
||||
* using('#foo').input('bar')
|
||||
*/
|
||||
angular.scenario.dsl('using', function() {
|
||||
return function(selector) {
|
||||
this.selector = (this.selector||'') + ' ' + selector;
|
||||
return this.dsl;
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* binding(name) returns the value of a binding
|
||||
*/
|
||||
angular.scenario.dsl('binding', function() {
|
||||
return function(name) {
|
||||
return this.addFutureAction("select binding '" + name + "'", function($window, $document, done) {
|
||||
var element;
|
||||
try {
|
||||
element = $document.elements('[ng\\:bind-template*="{{$1}}"]', name);
|
||||
} catch(e) {
|
||||
if (e.type !== 'selector')
|
||||
throw e;
|
||||
element = $document.elements('[ng\\:bind="$1"]', name);
|
||||
}
|
||||
done(null, element.text());
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* input(name).enter(value) enters value in input with specified name
|
||||
* input(name).check() checks checkbox
|
||||
* input(name).select(value) selects the readio button with specified name/value
|
||||
*/
|
||||
angular.scenario.dsl('input', function() {
|
||||
var chain = {};
|
||||
|
||||
chain.enter = function(value) {
|
||||
return this.addFutureAction("input '" + this.name + "' enter '" + value + "'", function($window, $document, done) {
|
||||
var input = $document.elements('input[name="$1"]', this.name);
|
||||
input.val(value);
|
||||
input.trigger('change');
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
||||
chain.check = function() {
|
||||
return this.addFutureAction("checkbox '" + this.name + "' toggle", function($window, $document, done) {
|
||||
var input = $document.elements('input:checkbox[name="$1"]', this.name);
|
||||
input.trigger('click');
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
||||
chain.select = function(value) {
|
||||
return this.addFutureAction("radio button '" + this.name + "' toggle '" + value + "'", function($window, $document, done) {
|
||||
var input = $document.
|
||||
elements('input:radio[name$="@$1"][value="$2"]', this.name, value);
|
||||
input.trigger('click');
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
||||
return function(name) {
|
||||
this.name = name;
|
||||
return chain;
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* repeater('#products table').count() // number of rows
|
||||
* repeater('#products table').row(1) // all bindings in row as an array
|
||||
* repeater('#products table').column('product.name') // all values across all rows in an array
|
||||
*/
|
||||
angular.scenario.dsl('repeater', function() {
|
||||
var chain = {};
|
||||
|
||||
chain.count = function() {
|
||||
return this.addFutureAction('repeater ' + this.selector + ' count', function($window, $document, done) {
|
||||
done(null, $document.elements().size());
|
||||
});
|
||||
};
|
||||
|
||||
chain.column = function(binding) {
|
||||
return this.addFutureAction('repeater ' + this.selector + ' column ' + binding, function($window, $document, done) {
|
||||
var values = [];
|
||||
$document.elements().each(function() {
|
||||
_jQuery(this).find(':visible').each(function() {
|
||||
var element = _jQuery(this);
|
||||
if (element.attr('ng:bind') === binding) {
|
||||
values.push(element.text());
|
||||
}
|
||||
});
|
||||
});
|
||||
done(null, values);
|
||||
});
|
||||
};
|
||||
|
||||
chain.row = function(index) {
|
||||
return this.addFutureAction('repeater ' + this.selector + ' row ' + index, function($window, $document, done) {
|
||||
var values = [];
|
||||
var matches = $document.elements().slice(index, index + 1);
|
||||
if (!matches.length)
|
||||
return done('row ' + index + ' out of bounds');
|
||||
_jQuery(matches[0]).find(':visible').each(function() {
|
||||
var element = _jQuery(this);
|
||||
if (element.attr('ng:bind')) {
|
||||
values.push(element.text());
|
||||
}
|
||||
});
|
||||
done(null, values);
|
||||
});
|
||||
};
|
||||
|
||||
return function(selector) {
|
||||
this.dsl.using(selector);
|
||||
return chain;
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* select(selector).option('value') // select one option
|
||||
* select(selector).options('value1', 'value2', ...) // select options from a multi select
|
||||
*/
|
||||
angular.scenario.dsl('select', function() {
|
||||
var chain = {};
|
||||
|
||||
chain.option = function(value) {
|
||||
return this.addFutureAction('select ' + this.name + ' option ' + value, function($window, $document, done) {
|
||||
var select = $document.elements('select[name="$1"]', this.name);
|
||||
select.val(value);
|
||||
select.trigger('change');
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
||||
chain.options = function() {
|
||||
var values = arguments;
|
||||
return this.addFutureAction('select ' + this.name + ' options ' + values, function($window, $document, done) {
|
||||
var select = $document.elements('select[multiple][name="$1"]', this.name);
|
||||
select.val(values);
|
||||
select.trigger('change');
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
||||
return function(name) {
|
||||
this.name = name;
|
||||
return chain;
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* element(selector).click() // clicks an element
|
||||
* element(selector).attr(name) // gets the value of an attribute
|
||||
* element(selector).attr(name, value) // sets the value of an attribute
|
||||
* element(selector).val() // gets the value (as defined by jQuery)
|
||||
* element(selector).val(value) // sets the value (as defined by jQuery)
|
||||
*/
|
||||
angular.scenario.dsl('element', function() {
|
||||
var chain = {};
|
||||
|
||||
chain.click = function() {
|
||||
return this.addFutureAction('element ' + this.selector + ' click', function($window, $document, done) {
|
||||
$document.elements().trigger('click');
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
||||
chain.attr = function(name, value) {
|
||||
var futureName = 'element ' + this.selector + ' get attribute ' + name;
|
||||
if (value) {
|
||||
futureName = 'element ' + this.selector + ' set attribute ' + name + ' to ' + value;
|
||||
}
|
||||
return this.addFutureAction(futureName, function($window, $document, done) {
|
||||
done(null, $document.elements().attr(name, value));
|
||||
});
|
||||
};
|
||||
|
||||
chain.val = function(value) {
|
||||
var futureName = 'element ' + this.selector + ' value';
|
||||
if (value) {
|
||||
futureName = 'element ' + this.selector + ' set value to ' + value;
|
||||
}
|
||||
return this.addFutureAction(futureName, function($window, $document, done) {
|
||||
done(null, $document.elements().val(value));
|
||||
});
|
||||
};
|
||||
|
||||
return function(selector) {
|
||||
this.dsl.using(selector);
|
||||
return chain;
|
||||
};
|
||||
});
|
||||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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/);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
Loading…
Reference in a new issue