diff options
Diffstat (limited to 'src/scenario/dsl.js')
| -rw-r--r-- | src/scenario/dsl.js | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/src/scenario/dsl.js b/src/scenario/dsl.js new file mode 100644 index 00000000..69af39db --- /dev/null +++ b/src/scenario/dsl.js @@ -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; + }; +}); |
