Manipulação de listas com Protractor
Neste artigo, o autor apresenta os métodos de manipulação de listas do Protractor, suas vantagens e como usa-los.

Você, como profissional de QA, já deve ter trabalhado com listas, certo? Um exemplo clássico desse tipo de trabalho é uma tela de listagem de resultados que precisam ser validados, validação essa que é bastante trabalhosa. Uma das vantagens do Protractor (se você não sabe do que eu estou falando, clique aqui) são seus métodos de manipulação de listas do JavaScript↳JavaScript116 conteúdosJavaScript em 2020: O que esperarDev (Back & Front) · jan 2020Campos públicos e privados em classes JavaScript – O que vem por aí no ESNextDev (Back & Front) · abr 201929 anos de JavaScript!Dev (Back & Front) · jan 2025Ver tudo em Dev (Back & Front) →, que facilitam muito quando temos esse tipo de cenário.
Vamos ver um exemplo? Veja a listagem abaixo:
<tr ng-repeat="item in PokemonsController.pokemons|filter: PokemonsController.filtro">
<td>
<a href="#!/details/{{item.id}}">
<strong>
#{{item.id}}
</strong>
</a>
</td>
<td>
<a href="#!/details/{{item.id}}">
<img ng-src="{{item.image}}" width="60px" alt="">
</a>
</td>
<td>
<a href="#!/details/{{item.id}}">
<span ng-bind="item.name"></span>
</a>
</td>
<td>
<a href="#!/details/{{item.id}}">
<span class="label bg-{{item.type1}}" ng-bind="item.type1"></span>
<span class="label bg-{{item.type2}}" ng-bind="item.type2"></span>
</a>
</td>
</tr>
Obs: Para visualizar essa listagem renderizada é só clicar aqui.
Vamos pegar esses resultados da seguinte forma:
const resultados = element.all(by.repeater('item in PokemonsController.pokemons'));
Com a listagem em mãos, já podemos começar a trabalhar com esses dados. Para isso, vamos ver os principais métodos para manipulação de listas dos Protractor:
Filter
Bem, como o próprio nome sugere, com esse método é possível filtrarmos um resultado. Utilizá-lo é bem simples, veja um exemplo:
resultados.filter(function(elem, index) {
elem.getText().then(function(txt){
console.log(txt)
});
return elem.element(by.binding('item.name')).getText().then(function(txt){
return txt === "Mew";
});
}).first().element(by.css('tr > td > a')).click();
O filter recebe dois parâmetros: o elemento (que nesse nosso exemplo serão as linhas da listagem, ou seja, as TRs da tabela) e o índice. Nesse exemplo ainda tem um detalhe interessante, um encadeamento de elementos, ou seja, fazemos uma “pesquisa” dentro de outro elemento.
A partir do elemento que recebemos como parâmetro (a TR) realizamos uma nova “pesquisa” para encontrarmos um elemento que tenha a diretiva ng-bind (que aprendemos como manipular nesse artigo aqui). Em seguida, pegamos o valor deste elemento e comparamos com um resultado que esperamos. No fim, dentro do elemento encontrado, realizamos a ação de click.
Obs: Para deixar mais claro, deixei propositalmente um console.log do elemento que recebemos como parâmetro para entender o que está acontecendo. Neste caso, o resultado desse log será o seguinte:
- #1 Bulbasaur grama veneno
- #6 Charizard fogo voador
- #38 Ninetales fogo
- #150 Mewtwo psiquico
- #151 Mew psiquico
Get
O Get é um método bem tranquilo de entender e provavelmente você já deve utilizá-lo. O get retorna um elemento pelo índice passado como parâmetro. Por exemplo:
resultados.get(3).element(by.binding('item.name')).getText().then(function(val){
console.log(val);
});
Aqui estamos acessando o elemento na posição de número 4 da nossa listagem e em seguida utilizamos a técnica de encadeamento de elementos para encontrarmos o texto do nome do pokémon.
O resultado será Mewtwo
First
Similar ao Get, mas retorna o primeiro item da lista.
resultados.first().element(by.binding('item.name')).getText().then(function(val){
console.log(val);
});
O resultado será Bulbasaur
Last
Retorna o último item da lista.
resultados.last().element(by.binding('item.name')).getText().then(function(val){
console.log(val);
});
O resultado será Mew
Each
Esse método é utilizado quando queremos iterar em uma lista:
resultados.each(function(elem, index) {
return elem.element(by.binding('item.name')).getText().then(function(txt){
console.log(index, txt)
});
});
O resultado será:
- 0 ‘Bulbasaur’
- 1 ‘Charizard’
- 2 ‘Ninetales’
- 3 ‘Mewtwo’
- 4 ‘Mew’
MAP
Com esse método podemos montar um objeto chave-valor, da seguinte maneira:
consultarPokemons(){
return resultados.map(function(elem, index){
return {
indice : index,
nome : elem.element(by.binding('item.name')).getText()
}
});
}
E poderíamos validar esse resultado em nosso teste, dessa forma:
const lista = listagemPage.consultarPokemons();
expect(lista).toEqual([
{ indice: 0, nome: 'Bulbasaur' },
{ indice: 1, nome: 'Charizard' },
{ indice: 2, nome: 'Ninetales' },
{ indice: 3, nome: 'Mewtwo' },
{ indice: 4, nome: 'Mew' }
Reduce
O reduce é utilizado quando queremos obter um valor acumulado ou fazer algum tipo de operação com todos os elementos, como concatenar os valores da lista. No exemplo, o reduce recebe como parâmetro uma função de callback com o valor acumulado e o elemento (que no nosso caso é a TR):
return this.resultados.reduce(function(valorAcumulado, elemento){
return elemento.element(by.binding('item.name')).getText().then(function(txt){
console.log('acc: '+ valorAcumulado + ' txt ' +txt);
return valorAcumulado + ', ' + txt ;
});
}, 'Todos Pokemons: ');
O resultado do console.log será o seguinte:
- acc: Todos Pokemons: txt: Bulbasaur
- acc: Todos Pokemons: , Bulbasaur txt: Charizard
- acc: Todos Pokemons: , Bulbasaur, Charizard txt: Ninetales
- acc: Todos Pokemons: , Bulbasaur, Charizard, Ninetales txt: Mewtwo
- acc: Todos Pokemons: , Bulbasaur, Charizard, Ninetales, Mewtwo txt: Mew
O Protractor oferece muitas opções para manipular listas, como pudemos observar. Com ele, é possível economizar muito trabalho! Saber em que situação utilizar cada um desses métodos é muito importante e ajuda muito no dia a dia. Portanto, entenda bem quando e como podemos utilizá-lo, isso deve te poupar algumas dores de cabeça.
Até a próxima!
***
Este artigo foi publicado originalmente em: https://www.concrete.com.br/2018/01/04/manipulacao-de-listas-com-protractor/







