From 3aab6fb71aeb1265e47a89905bcab0db5589740f Mon Sep 17 00:00:00 2001 From: Jonathan Niles Date: Thu, 26 May 2016 15:32:40 +0100 Subject: [PATCH] feat(test): allow selecting within anchor elements This commit extends the `FormUtils` API to allow an optional anchor element to be passed in. The anchor element will cause the `FormUtils` library to search only within the subtree contained by that element. All end-to-end tests now use `FU.typeahead()` when they require a typeahead. --- client/src/partials/vouchers/complex.html | 3 - .../billingServices/billingServices.spec.js | 12 +- client/test/e2e/shared/FormUtils.js | 167 +++++++++--------- .../shared/components/bhFindDebtorGroup.js | 62 +++---- .../e2e/shared/components/bhFindPatient.js | 16 +- client/test/e2e/vouchers/complex.page.js | 30 +--- client/test/e2e/vouchers/simple.spec.js | 11 +- 7 files changed, 128 insertions(+), 173 deletions(-) diff --git a/client/src/partials/vouchers/complex.html b/client/src/partials/vouchers/complex.html index 3766217bc0..e5e7f6d9b4 100644 --- a/client/src/partials/vouchers/complex.html +++ b/client/src/partials/vouchers/complex.html @@ -129,7 +129,6 @@

{{ 'VOUCHERS.COMPLEX.TITLE' | translate }}

uib-typeahead="account as account.hrlabel for account in ComplexVoucherCtrl.accounts | filter:$viewValue | limitTo:8 " typeahead-editable="false" typeahead-on-select="ComplexVoucherCtrl.checkRowValidity($index)" - data-account-input class="form-control" required> @@ -142,7 +141,6 @@

{{ 'VOUCHERS.COMPLEX.TITLE' | translate }}

ng-change="ComplexVoucherCtrl.checkRowValidity($index)" type="number" class="form-control text-right" - data-debit-input required> @@ -151,7 +149,6 @@

{{ 'VOUCHERS.COMPLEX.TITLE' | translate }}

ng-change="ComplexVoucherCtrl.checkRowValidity($index)" type="number" class="form-control text-right" - data-credit-input required> diff --git a/client/test/e2e/billingServices/billingServices.spec.js b/client/test/e2e/billingServices/billingServices.spec.js index 7665b9eeda..3eeea3c898 100644 --- a/client/test/e2e/billingServices/billingServices.spec.js +++ b/client/test/e2e/billingServices/billingServices.spec.js @@ -26,17 +26,7 @@ describe('Billing Services', function () { // anticipate that the form should come up FU.exists(by.css('[name="BillingServicesForm"]'), true); - var root = element(by.css('[data-component-find-account]')); - - // search for a particular account using the account input - var accountInput = root.element(by.model('BillingServicesFormCtrl.model.account')); - accountInput.sendKeys('410'); - - // click select the proper account - var option = root.all(by.repeater('match in matches track by $index')).first(); - option.click(); - - // fill in the rest of the fields + FU.typeahead('BillingServicesFormCtrl.model.account', '410'); FU.input('BillingServicesFormCtrl.model.label', 'Value Added Tax'); FU.input('BillingServicesFormCtrl.model.description', 'A tax added for people who want value!'); FU.input('BillingServicesFormCtrl.model.value', 25); diff --git a/client/test/e2e/shared/FormUtils.js b/client/test/e2e/shared/FormUtils.js index 1990750839..e9d8081277 100644 --- a/client/test/e2e/shared/FormUtils.js +++ b/client/test/e2e/shared/FormUtils.js @@ -6,83 +6,31 @@ const expect = chai.expect; const helpers = require('./helpers'); helpers.configure(chai); -// Overide the element.all() prototype function provided by protractor to attach custom methods -// @TODO - is there a better way without overriding the prototype function? -var ElementArrayFinder = protractor.ElementArrayFinder; - -/** -* Pick a random element from the ElementArrayFinder. -* -* @alias element.all(locator).random() -* @view -* -* -* @example -* var list = element.all(by.css('.items li)); -* expect(list.random().getText()).to.have.length.above(4); -* -* @todo - make this work. sigh. -ElementArrayFinder.prototype.random = function() { - var self = this; - return self.count() - .then(function (length) { - var n = Math.floor(Math.random() * length); - return self.filter(function (elem, index) { - return index === n; - }) - }); -}; -*/ - -/** -* Filter out disabled elements from the ElementArrayFinder. -* -* @alias element.all(locator).enabled() -* @view -* -* -* @example -* var options = element.all(by.css('select > option')); -* expect(options.enabled()).to.have.length(1); -*/ -ElementArrayFinder.prototype.enabled = function () { - return this.filter(function (elem, index) { - return elem.isEnabled(); - }); -}; - // These buttons depend on custom data tags to indicate actions. This seems // cleaner than using a whole bunch of ids which may potentially collide. // However, this decision can be reviewed var buttons = { - create : function create() { return $('[data-method="create"]').click(); }, - search : function search() { return $('[data-method="search"]').click(); }, - submit : function submit() { return $('[data-method="submit"]').click(); }, - cancel : function cancel() { return $('[data-method="cancel"]').click(); }, - back : function back() { return $('[data-method="back"]').click(); }, - delete : function delet() { return $('[data-method="delete"]').click(); } + create: function create() { return $('[data-method="create"]').click(); }, + search: function search() { return $('[data-method="search"]').click(); }, + submit: function submit() { return $('[data-method="submit"]').click(); }, + cancel: function cancel() { return $('[data-method="cancel"]').click(); }, + back: function back() { return $('[data-method="back"]').click(); }, + delete: function delet() { return $('[data-method="delete"]').click(); } }; // This methods are for easily working with modals. Works with the same custom // data tags used in form buttons. var modal = { - submit : function submit() { return $('[uib-modal-window] [data-method="submit"]').click(); }, - cancel : function cancel() { return $('[uib-modal-window] [data-method="cancel"]').click(); } + submit: function submit() { return $('[uib-modal-window] [data-method="submit"]').click(); }, + cancel: function cancel() { return $('[uib-modal-window] [data-method="cancel"]').click(); } }; // convenience methods to see if the form contains feedback text. Returns locators. var feedback = { - success : function success() { return by.css('[data-role="feedback"] > .text-success'); }, - error : function error() { return by.css('[data-role="feedback"] > .text-danger'); }, - warning : function warning() { return by.css('[data-role="feedback"] > .text-warning'); }, - info : function info() { return by.css('[data-role="feedback"] > .text-info'); } + success: function success() { return by.css('[data-role="feedback"] > .text-success'); }, + error: function error() { return by.css('[data-role="feedback"] > .text-danger'); }, + warning: function warning() { return by.css('[data-role="feedback"] > .text-warning'); }, + info: function info() { return by.css('[data-role="feedback"] > .text-info'); } }; // convenience methods to check form element validation states @@ -103,42 +51,91 @@ var validation = { module.exports = { // get an element by its ng-model - input : function input(model, value) { - return element(by.model(model)).clear().sendKeys(value); + input : function input(model, value, anchor) { + + // get the HTML element + let input = anchor ? + anchor.element(by.model(model)) : + element(by.model(model)); + + return input.clear().sendKeys(value); }, - // get a html element. Accepts the model + * selector, the option text, and an optional anchor element to search within. + * If no anchor is provided, it defaults to the body. + * + * @param {String} model - the ng-model target to select + * @param {String} option - the text of the