search an element in a repeater containing specific text using protractor

How could I search an element from a repeater containing a specific text ?

I tried things like that :

element(by.repeater('item in array')).all(by.cssContainingText('.xyz','my item title')); // only gets the first element

I could search by myself using .then after element.all but I'm wondering if it exists something simpler like cssContainingText but for repeaters :

element(by.repeaterContainingText('item in array','my item title'))

or a element chaining like that :

element.all(by.repeater('item in array')).element(by.cssContainingText('.xyz','my item title'));

A solution with filter (but very slow)

element.all(by.repeater('item in array')).filter(function(elem){
    return elem.getText().then(function(text){
        return text.indexOf('my item title') > -1;
    });
}).then(function(filteredElements) {
    return filteredElements[0];
})

Protractor allows adding locators.. I am using the following implementation (pure javascript) successfully in a project with 20 tests or so.

Here is a solution using lodash and jquery. Below there is also one in pure javascript.

https://gist.github.com/GuyMograbi/7a5f5e580bcf8d7da58a

by.addLocator('text',

/**
 *
 * @param {string} text - will be lowercased
 * @param {string} selector - to get list of children
 * @param {null|object} parent - protractor will provide this..
 */
function(text, selector, parent) {
    return _.filter($(parent || 'body').find(selector), function(e){
        return $(e).is(':visible') && $(e).text().toLowerCase().trim() === text.toLowerCase().trim();
    });
});

and use it with

return $('table').all(by.text('my text', 'tr')).first().getText().then(function(text){...})

or

return element(by.text('my text', 'tr')).getText().then(function(text){...})

Don't forget the following about protractor and locators

I just spent 2 hours breaking my brains as to why my locator does not work. please remember the following:

  • protractor 'ignores' hidden elements, however your locator does not do so by default.. so if you write a custom locator, in order for it to work as expected in angular you must filter out hidden elements
  • if you need to debug, I found it most useful using getOuterHtml().then..
  • Pure JavaScript

    This is how the same will look without jquery and lodash

    by.addLocator('text',
    
    /**
     *
     * @param text - will be lowercased
     * @param selector - to get list of children
     * @param parent - protractor will provide this..
     */
    function(text, selector, _parent) {
    
        return Array.prototype.filter.call( (_parent || document).querySelectorAll(selector), function(e){
            return e && !!(e.offsetWidth || e.offsetHeight || e.getClientRects().length) && e.textContent && e.textContent.toLowerCase().trim() === text.toLowerCase().trim();
    
        });
    });
    
  • the isVisible part was eventually taken from jquery sources. see answer at: https://stackoverflow.com/a/33456469/1068746
  • Important note - or - why this should be the right answer

    Using filter you get a promise. using this solution you get an element. So instead of having a getByText(..).then(function(e){ e.click() }) you will have getByText(...).click() - sweeet!

    Limitations and possible enhancements

    in your case, the repeater locator cannot be used which is a bummer, unless you modify the location instead of text to be textInRepeater and then have '[ng-repeat=' + repeater + ']' somehow added in the code.

    Another thing you might want to enhance which is very useful. Sometime you want to get an element which CONTAINS text, or possibly contains a child with text, but you actually want to select the parent.


    Yes you can chain elements in Protractor.

    element(locator1).element(locator2);
    

    protractor-Locators.md


    I know you likely don't need the answer anymore but I though I would update in case someone else is having this same issue. You can use

    element(by.linkText('.xyz'));
    
    链接地址: http://www.djcxy.com/p/83576.html

    上一篇: 收听Angular 2中的元素可见性

    下一篇: 使用量角器搜索包含特定文本的中继器中的元素