web-dev-qa-db-ja.com

分度器を使用してすべての要素属性を取得します

ドキュメントによると、名前で単一の属性を取得するには、WebElement.getAttribute() を使用できます。

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

しかし、要素が持つすべての属性を取得するにはどうすればよいですか?

Protractor API には、このユースケース/機能に関する情報はありません。

14
alecxe

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

デモ

次に、1つの属性に使用するのと同じ方法を使用して、属性の整合性をテストできます。

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

executeScript() を使用して、element.attributesから属性を読み取る属性のリストを形成するスクリプトを実行します(内部のjs部分は ここ から取得されます):

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チュートリアルページ を使用して、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);
});
1
alecxe

必要な属性の前にデータが付いている場合は、要素のデータセットを使用して、実行スクリプトを少し縮小できるはずです。

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

_Element.attributes_ は分度器APIの実装から外れているため、分度器APIの代わりにbrowser.executeScript()関数呼び出しを使用する必要があります。

_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モデルのコンテキストでは、配列ではなく名前付きマップ構造を意味することに注意してください。つまり、 Attr オブジェクトのコレクションにアクセスするには、 NamedNodeMap を使用する必要があります。

反復部分がない場合は、@ alecxeの回答と同じように機能します。

1
shawmzhu