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

时间:2014-07-30 15:37:20

标签: protractor

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

我尝试过这样的事情:

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

我可以在.then之后使用element.all自行搜索,但我想知道它是否存在像cssContainingText更简单的内容,但是对于中继者来说:

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

或像这样链接的元素:

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

带过滤器的解决方案(但非常慢)

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];
})

3 个答案:

答案 0 :(得分:2)

Protractor允许添加定位器..我在一个项目中成功使用以下实现(纯javascript),大约有20个测试。

这是使用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();
    });
});

并将其与

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

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

不要忘记关于量角器和定位器的以下内容

我花了2个小时打破我的大脑,为什么我的定位器不起作用。请记住以下内容:

  • 量角器'忽略'隐藏的元素,但是默认情况下你的定位器不这样做..所以如果你写一个自定义定位器,为了让它按照预期的角度工作,你必须过滤掉隐藏的元素
  • 如果您需要调试,我发现使用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();

    });
});

重要提示 - 或 - 为什么这应该是正确的答案

使用filter即可获得承诺。使用此解决方案,您将获得一个元素因此,不是拥有getByText(..).then(function(e){ e.click() }),而是getByText(...).click() - sweeet!

限制和可能的增强

在你的情况下,不能使用转发器定位器,这是一个无赖,除非你修改位置而不是texttextInRepeater,然后在代码中以某种方式添加'[ng-repeat=' + repeater + ']'

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

答案 1 :(得分:1)

是的,你可以在Protractor中链接元素。

element(locator1).element(locator2);

protractor-Locators.md

答案 2 :(得分:-1)

我知道你可能不再需要答案,但我会更新以防其他人遇到同样的问题。你可以使用

element(by.linkText('.xyz'));