Получить все атрибуты элемента с помощью транспортира
В соответствии с документацией, чтобы получить один атрибут по имени, вы можете использовать .getAttribute()
на WebElement
:
var myElement = element(by.id('myId'));
expect(myElement.getAttribute('myAttr')).toEqual('myValue');
Но как я могу получить все атрибуты, которые имеет элемент?
Информация об этом случае/функциях отсутствует в API-интерфейсе протрансформатора.
Ответы
Ответ 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);
};
демо
тогда вы можете проверить целостность атрибутов, используя тот же метод, который вы используете для одного атрибута:
var myElement = element(by.id('myId'));
expect(myElement.getAttributes()).toEqual({'attr1': 'value1', 'attr1': 'value1', ... });
Ответ 2
Используйте executeScript()
для выполнения script, который формирует список атрибутов, читающих их из 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
будет содержать словарь/объект атрибутов элемента с ключами как имена атрибутов и значения как значения атрибута.
Demo (используя страницу обучения 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);
});
Ответ 3
Если ваши атрибуты, которые вам нужны, имеют префикс данных, вы должны иметь возможность использовать набор данных для элемента, который немного сократит ваш выполнение script:
browser.executeScript('return arguments[0].dataset;', elm).then(function (attrs) {
console.log(attrs);
});
Ответ 4
Вы должны использовать вызов функции browser.executeScript()
вместо API-интерфейса protractor, поскольку 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`
});
Помните, что при упоминании атрибутов это означает именованную структуру карты, а не массив в контексте модели DOM. Это означает, что вы должны использовать NamedNodeMap для доступа к коллекции Attr.
Он работает так же, как в ответе @alecxe без итерационной части.