From a62efc6e401bc1aa7408e3008ccdaa219b528636 Mon Sep 17 00:00:00 2001 From: Joe Heyming Date: Sun, 5 Nov 2017 22:26:12 -0800 Subject: [PATCH] feat(locators): Add support for regex in cssContainingText (#4532) * feat(locators): Add support for regex in cssContainingText. In order to get this working, I had to serialize the regex before we send it over the wire to the browser. Since there is no standard way to do this, I took guidance from a stackoverflow answer, where they call toString on the regex. Then, on the browser, you use a regex to extract out the text in between /someregex/ The hard part is to also extract out the modifiers, like i for ignore case. --- lib/clientsidescripts.js | 12 ++++++++++-- lib/locators.ts | 5 +++-- spec/basic/locators_spec.js | 20 ++++++++++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/lib/clientsidescripts.js b/lib/clientsidescripts.js index 0ca82744a..ad795ec51 100644 --- a/lib/clientsidescripts.js +++ b/lib/clientsidescripts.js @@ -676,7 +676,7 @@ functions.findByPartialButtonText = function(searchText, using) { * Find elements by css selector and textual content. * * @param {string} cssSelector The css selector to match. - * @param {string} searchText The exact text to match. + * @param {string} searchText The exact text to match or a serialized regex. * @param {Element} using The scope of the search. * * @return {Array.} An array of matching elements. @@ -684,12 +684,20 @@ functions.findByPartialButtonText = function(searchText, using) { functions.findByCssContainingText = function(cssSelector, searchText, using) { using = using || document; + if (searchText.indexOf('__REGEXP__') === 0) { + var match = searchText.split('__REGEXP__')[1].match(/\/(.*)\/(.*)?/); + searchText = new RegExp(match[1], match[2] || ''); + } var elements = using.querySelectorAll(cssSelector); var matches = []; for (var i = 0; i < elements.length; ++i) { var element = elements[i]; var elementText = element.textContent || element.innerText || ''; - if (elementText.indexOf(searchText) > -1) { + var elementMatches = searchText instanceof RegExp ? + searchText.test(elementText) : + elementText.indexOf(searchText) > -1; + + if (elementMatches) { matches.push(element); } } diff --git a/lib/locators.ts b/lib/locators.ts index ae1f538d2..f6852ea02 100644 --- a/lib/locators.ts +++ b/lib/locators.ts @@ -415,10 +415,11 @@ export class ProtractorBy extends WebdriverBy { * var dog = element(by.cssContainingText('.pet', 'Dog')); * * @param {string} cssSelector css selector - * @param {string} searchString text search + * @param {string|RegExp} searchString text search * @returns {ProtractorLocator} location strategy */ - cssContainingText(cssSelector: string, searchText: string): ProtractorLocator { + cssContainingText(cssSelector: string, searchText: string|RegExp): ProtractorLocator { + searchText = (searchText instanceof RegExp) ? '__REGEXP__' + searchText.toString() : searchText; return { findElementsOverride: (driver: WebDriver, using: WebElement, rootSelector: string): wdpromise.Promise => { diff --git a/spec/basic/locators_spec.js b/spec/basic/locators_spec.js index 6d64bb727..0f370b00b 100644 --- a/spec/basic/locators_spec.js +++ b/spec/basic/locators_spec.js @@ -353,6 +353,26 @@ describe('locators', function() { expect(element(by.cssContainingText('#transformedtext div', 'capitalize')) .getAttribute('id')).toBe('textcapitalize'); }); + + it('should find elements with a regex', function() { + element.all(by.cssContainingText('#transformedtext div', /(upper|lower)case/i)) + .then(function(found) { + expect(found.length).toEqual(2); + expect(found[0].getText()).toBe('UPPERCASE'); + expect(found[1].getText()).toBe('lowercase'); + }); + }); + + it('should find elements with a regex with no flags', function() { + // this test matches the non-transformed text. + // the text is actually transformed with css, + // so you can't match the Node innerText or textContent. + element.all(by.cssContainingText('#transformedtext div', /Uppercase/)) + .then(function(found) { + expect(found.length).toEqual(1); + expect(found[0].getText()).toBe('UPPERCASE'); + }); + }); }); describe('by options', function() {