【问题标题】:Get all element attributes using protractor使用量角器获取所有元素属性
【发布时间】:2014-12-29 19:08:34
【问题描述】:

根据文档,要按名称获取单个属性,您可以在 WebElement 上使用 .getAttribute()

var myElement = element(by.id('myId'));
expect(myElement.getAttribute('myAttr')).toEqual('myValue');

但是我怎样才能得到一个元素的所有属性呢?

Protractor API 中没有关于此用例/功能的信息。

【问题讨论】:

  • 看看getOuterHtml()
  • @J0e3gan 谢谢,但这会给我一个元素的 HTML 表示。所需的输出将是一个对象,键:元素所有属性的值。
  • 请注意,像 Angular 这样的框架会添加更多属性,这可能会使您的测试容易受到攻击。
  • @DmitriZaitsev 完全同意,这完全有道理。谢谢。

标签: javascript api protractor end-to-end


【解决方案1】:

可以扩展javascript的Element类型并添加getAttributes()函数:

Element.prototype.getAttributes = function() {
    return (function (node) {
        var attrs = {};
        for (var i=0;i<node.length;i++) {
            attrs[node.item(i).name] = node.item(i).value;
        }
        return attrs;
    })(this.attributes);
};

demo

然后您可以使用与一个属性相同的方法来测试属性的完整性:

var myElement = element(by.id('myId'));
expect(myElement.getAttributes()).toEqual({'attr1': 'value1', 'attr1': 'value1', ... });

【讨论】:

  • 这是一个很棒的想法——现在我可以在整个项目中轻松地重用getAttributes()。谢谢!
  • 在你走得太远之前,请考虑:What's wrong with extending the DOM
  • @RobG 我将引用帖子中的一个 cmets:“从 Javascript 的角度来看,作为一种原型语言,这样做在技术上没有任何问题。扩展原型正是 Javascript 程序员应该做的正在做”。事实是,无论您如何开发代码,总会有缺点和陷阱,但这并不总是意味着您的所作所为是错误的,有时您只需要更加小心,也许需要采取更有力的措施。 tnx 的帖子,它真的很有帮助
  • 有多少库通过原型扩展 DOM?也许作者知道一些事情。甚至 Prototype.js 也不再这样做了。仅仅因为你可以做某事并不意味着它是一个好主意——我编写了一个有趣的库来为 DOM 元素添加迭代器,但绝不会在愤怒中使用它。您可能想研究 Juriy "kangax" Zaytsev,以便在考虑 Marc K 的意见时适当权衡他的意见。
  • 我并没有说你的错误,只是任何想扩展 DOM 对象的人都应该考虑 Juriy 的建议。还有很多其他受人尊敬的 javascript 开发人员也有同样的想法(例如 jQuery、YUI、ext 不扩展 DOM 对象,并且重写了 Prototype.js 以停止这样做),只是 Juriy 写了一篇关于它的优秀文章.在 OP 的上下文中,也许它与某些测​​试框架配合得非常好,我愿意相信。 ;-)
【解决方案2】:

如果您需要的属性以数据为前缀,您应该能够将数据集用于元素,这将稍微缩小您的执行脚本:

browser.executeScript('return arguments[0].dataset;', elm).then(function (attrs) {
    console.log(attrs);
});

【讨论】:

    【解决方案3】:

    使用executeScript() 执行一个脚本,该脚本形成一个从element.attributes 读取它们的属性列表(里面的js 部分取自here):

    var elm = element(by.id('runButton')).getWebElement();
    browser.executeScript(
        'var items = {}; \
         for (index = 0; index < arguments[0].attributes.length; ++index) { \
             items[arguments[0].attributes[index].name] = arguments[0].attributes[index].value \
         }; \
         return items;', elm).then(function (attrs) {
            console.log(attrs);
        });
    

    这里attrs 将包含元素属性的字典/对象,其中键作为属性名称,值作为属性值。

    演示(使用angularjs.org tutorial page,获取header的所有属性):

    $ node node_modules/protractor/bin/elementexplorer.js https://docs.angularjs.org/tutorial
    Getting page at: https://docs.angularjs.org/tutorial
    > var elm = element(by.tagName('header')).getWebElement();
    > browser.executeScript('var items = {}; for (index = 0; index < arguments[0].attributes.length; ++index) { items[arguments[0].attributes[index].name] = arguments[0].attributes[index].value }; return items;', elm).then(function (attrs) {
    ...     console.log(attrs);
    ... });
    { class: 'header header-fixed', 'scroll-y-offset-element': '' }
    

    不是很漂亮和紧凑,但对我有用。很高兴看到更好的选择。


    更新(对上述方法的改进):

    如果我定义一个常规函数并将其传入,它也会起作用:

    function getAllAttributes (arguments) {
        var items = {}; 
        for (index = 0; index < arguments[0].attributes.length; ++index) { 
            items[arguments[0].attributes[index].name] = arguments[0].attributes[index].value; 
        }
        return items;
    }
    
    browser.executeScript(getAllAttributes, elm).then(function (attrs) {
        console.log(attrs);
    });
    

    【讨论】:

    • 仅供参考,要运行 elementexplorer.js,我们需要先启动 selenium 服务器。 java -jar node_modules/protractor/selenium/selenium-server-standalone-2.44.0.jar -Dwebdriver.chrome.driver=node_modules/protractor/selenium/chromedriver
    • @allenhwkim 是的,感谢您的来信。你认为所有元素属性都可以更容易地检索吗?谢谢。
    • @alexe 不,我找不到更好的解决方案。只要executeScript返回所有递归属性的深拷贝,就不容易做到。我认为 WebDriver 应该为此添加一个方法,getAttributes()
    【解决方案4】:

    您必须使用 browser.executeScript() 函数调用而不是量角器 API,因为 Element.attributes 超出量角器 API 实现:

    var elem = element(by.id('runButton'));
    browser.executeScript("return arguments[0].attributes", elem.getWebElement())
        .then(function (attrs) {
            console.log(attrs.length);    // outputs numbers of attributes.
            // access collection of Attr objects
            console.log(attrs[0].isId);   // outputs `true`
            console.log(attrs[0].name);   // outputs `id`
            console.log(attrs[0].value);  // outputs `runButton`
        });
    

    请记住,当说 attributes 时,它的意思是命名映射结构,而不是 DOM 模型上下文中的数组。这意味着您必须使用NamedNodeMap 来访问Attr 对象的集合。

    它的工作方式与@alecxe 的答案相同,但没有迭代部分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-02
      • 2013-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多