Front End

25 jan, 2018

Manipulação de listas com Protractor

Publicidade

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, 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/