From 65844fbdd2e23063ff52d4033ed8ee89509f8156 Mon Sep 17 00:00:00 2001 From: Hank Duan Date: Fri, 16 May 2014 15:14:49 -0700 Subject: [PATCH] feat(locators): Add By.exactBinding locator --- lib/clientsidescripts.js | 15 ++++++++++++--- lib/locators.js | 22 +++++++++++++++++++++- spec/basic/findelements_spec.js | 12 ++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/lib/clientsidescripts.js b/lib/clientsidescripts.js index 3ba164e29..d7862351d 100644 --- a/lib/clientsidescripts.js +++ b/lib/clientsidescripts.js @@ -37,11 +37,12 @@ clientSideScripts.waitForAngular = function(selector, callback) { * Find a list of elements in the page by their angular binding. * * @param {string} binding The binding, e.g. {{cat.name}}. + * @param {boolean} exactMatch Whether the binding needs to be matched exactly * @param {Element} using The scope of the search. * * @return {Array.} The elements containing the binding. */ -clientSideScripts.findBindings = function(binding, using) { +clientSideScripts.findBindings = function(binding, exactMatch, using) { using = using || document; var bindings = using.getElementsByClassName('ng-binding'); var matches = []; @@ -49,9 +50,17 @@ clientSideScripts.findBindings = function(binding, using) { var dataBinding = angular.element(bindings[i]).data('$binding'); if(dataBinding) { var bindingName = dataBinding.exp || dataBinding[0].exp || dataBinding; - if (bindingName.indexOf(binding) != -1) { - matches.push(bindings[i]); + if (exactMatch) { + var matcher = new RegExp('([^a-zA-Z\d]|$)' + binding + '([^a-zA-Z\d]|^)'); + if (matcher.test(bindingName)) { + matches.push(bindings[i]); + } + } else { + if (bindingName.indexOf(binding) != -1) { + matches.push(bindings[i]); + } } + } } return matches; /* Return the whole array for webdriver.findElements. */ diff --git a/lib/locators.js b/lib/locators.js index 616a83516..3a984150a 100644 --- a/lib/locators.js +++ b/lib/locators.js @@ -93,12 +93,32 @@ ProtractorBy.prototype.binding = function(bindingDescriptor) { findElementsOverride: function(driver, using) { return driver.findElements( webdriver.By.js(clientSideScripts.findBindings, - bindingDescriptor, using)); + bindingDescriptor, false, using)); }, message: 'by.binding("' + bindingDescriptor + '")' }; }; +/** + * Find an element by exact binding. + * + * @alias by.exactBinding() + * Same as by.binding() except this does not allow for partial matches + * + * @param {string} bindingDescriptor + * @return {{findElementsOverride: findElementsOverride, message: string}} + */ +ProtractorBy.prototype.exactBinding = function(bindingDescriptor) { + return { + findElementsOverride: function(driver, using) { + return driver.findElements( + webdriver.By.js(clientSideScripts.findBindings, + bindingDescriptor, true, using)); + }, + message: 'by.exactBinding("' + bindingDescriptor + '")' + }; +}; + /** * @deprecated Use 'model' instead. * diff --git a/spec/basic/findelements_spec.js b/spec/basic/findelements_spec.js index de6c487e3..6eb7d1851 100644 --- a/spec/basic/findelements_spec.js +++ b/spec/basic/findelements_spec.js @@ -18,6 +18,18 @@ describe('locators', function() { expect(greeting.getText()).toEqual('Hiya'); }); + it('should find exact match by exactBinding', function() { + var greeting = element(by.exactBinding('greeting')); + + expect(greeting.getText()).toEqual('Hiya'); + }); + + it('should not find partial match by exactBinding', function() { + var greeting = element(by.exactBinding('greet')); + + expect(greeting.isPresent()).toBe(false); + }); + it('should find an element by binding with ng-bind attribute', function() { var name = element(by.binding('username'));