使用量角器搜索包含特定文本的转发器中的元素

syl*_*ain 7 protractor

如何从包含特定文本的转发器中搜索元素?

我尝试过这样的事情:

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

我可以自己搜索使用.then,element.all但我想知道它是否存在更简单的东西,cssContainingText但对于中继器:

element(by.repeaterContainingText('item in array','my item title'))
Run Code Online (Sandbox Code Playgroud)

或者像这样链接的元素:

element.all(by.repeater('item in array')).element(by.cssContainingText('.xyz','my item title'));
Run Code Online (Sandbox Code Playgroud)

带过滤器的解决方案(但速度很慢)

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];
})
Run Code Online (Sandbox Code Playgroud)

guy*_*abi 2

Protractor 允许添加定位器。我在一个进行了 20 次左右测试的项目中成功使用了以下实现(纯 javascript)。

这是使用 lodash 和 jquery 的解决方案。下面还有一个纯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();
    });
});
Run Code Online (Sandbox Code Playgroud)

并与它一起使用

return $('table').all(by.text('my text', 'tr')).first().getText().then(function(text){...})
Run Code Online (Sandbox Code Playgroud)

或者

return element(by.text('my text', 'tr')).getText().then(function(text){...})
Run Code Online (Sandbox Code Playgroud)

不要忘记以下有关量角器和定位器的信息

我花了两个小时绞尽脑汁想知道为什么我的定位器不起作用。请记住以下几点:

  • 量角器“忽略”隐藏元素,但是您的定位器默认情况下不会这样做。因此,如果您编写自定义定位器,为了使其按角度预期工作,您必须过滤掉隐藏元素
  • 如果您需要调试,我发现使用它最有用getOuterHtml().then..

纯JavaScript

这就是没有 jquery 和 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();

    });
});
Run Code Online (Sandbox Code Playgroud)

重要说明 - 或者 - 为什么这应该是正确的答案

使用filter你会得到一个承诺。使用这个解决方案你会得到一个元素。因此,getByText(..).then(function(e){ e.click() })您将拥有的不是getByText(...).click()- 亲爱的!

限制和可能的改进

在您的情况下,无法使用中继器定位器,这很糟糕,除非您修改位置而不是text然后textInRepeater'[ng-repeat=' + repeater + ']'某种方式添加到代码中。

您可能想要增强的另一件事非常有用。有时您想要获取一个包含文本的元素,或者可能包含带有文本的子元素,但实际上您想要选择父元素。