最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Get all element attributes using protractor - Stack Overflow

programmeradmin3浏览0评论

According to the documentation, to get a single attribute by name you can use .getAttribute() on a WebElement:

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

But how can I get all of the attributes that an element has?

There is no information about this use case/functionality in the Protractor API.

According to the documentation, to get a single attribute by name you can use .getAttribute() on a WebElement:

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

But how can I get all of the attributes that an element has?

There is no information about this use case/functionality in the Protractor API.

Share Improve this question edited Dec 18, 2015 at 9:32 Dr1Ku 2,9103 gold badges48 silver badges57 bronze badges asked Dec 29, 2014 at 19:08 alecxealecxe 474k126 gold badges1.1k silver badges1.2k bronze badges 4
  • Take a look at getOuterHtml(). – J0e3gan Commented Dec 29, 2014 at 19:48
  • @J0e3gan thank you, but this would give me an HTML representation of an element. The desired output would be an object, key:value of all attributes of an element. – alecxe Commented Dec 29, 2014 at 20:22
  • Just beware that frameworks like Angular add more attributes, which might make your tests vulnerable. – Dmitri Zaitsev Commented May 16, 2015 at 13:46
  • @DmitriZaitsev totally agree and it makes perfect sense. Thanks. – alecxe Commented May 16, 2015 at 19:18
Add a comment  | 

4 Answers 4

Reset to default 10 +100

You can expand javascript's Element type and add getAttributes() function:

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

then you can test integrity of attributes using the same method you use for one attribute:

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

If your attributes that you need are prefixed with data you should be able to use the dataset for the element which will shrink your execute script by a bit:

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

Use executeScript() to execute a script that forms a list of attributes reading them from element.attributes (js part inside is taken from 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);
    });

Here attrs would contain a dictionary/object of element attributes with keys as attribute names and values as attribute values.

Demo (using angularjs.org tutorial page, getting all attributes for a 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': '' }

Not really beautiful and compact, but works for me. Would be happy to see better alternatives.


UPDATE (an improvement to the approach above):

It would also work if I would define a regular function and pass it in:

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

You have to use browser.executeScript() function call instead of protractor API since Element.attributes is out of protractor API implementation:

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

Remember that when saying attributes, it means a named map structure instead an array in the context of DOM model. Which means you have to use the NamedNodeMap to access collection of Attr objects.

It works as the same way as that in @alecxe's answer without the iteration part.

发布评论

评论列表(0)

  1. 暂无评论