Este conteúdo foi inicialmente publicado na Newsletter da Talking About Testing (e adaptado para o blog TAT).
Se você já está usando o básico do que o Cypress pode te oferecer e está pronto(a) para dar o próximo passo, te apresento o comando .invoke().
Se você ainda não conhece o Cypress, ou só ouviu falar, mas ainda não teve a chance de experimentar, espero atrair sua atenção para esta ferramenta fantástica.
E se você já conhece essa funcionalidade, espero agregar com algo novo, nem que seja com minha forma de comunicar. Fica comigo!
O comando .invoke(), como o nome sugere, invoca uma função no “sujeito” fornecido pelo comando anterior.
Sujeito?
No Cypress, alguns comandos podem ser chamados através do objeto global cy.
Este não é o caso do comando .invoke().
Ou seja, você não pode fazer algo como o seguinte.
cy.invoke('text')
O comando .invoke() precisa de um sujeito, ou seja, de algo retornado por um comando anterior.
Por exemplo.
cy.get('h1').invoke('text')
Ou seja, o comando cy.get('h1') passa adiante o elemento encontrado (caso algum seja encontrado) ao comando .invoke(), o qual consegue então invocar o texto de tal elemento com o uso da função text.
Com isso, podemos, por exemplo, fazer uma verificação de que um certo texto é contido no elemento.
Assim.
cy.get('h1')
.invoke('text')
.should('contain', 'Newsletter da TAT')
Sugestão: Se quiser praticar, teste o código acima na página da newsletter da TAT.
Ok.
Agora que você tem uma idéia do que dá pra fazer com o comando .invoke(), vejamos mais alguns casos de uso.
Links internos que abrem em outra página
Na página de trade-offs da documentação oficial do Cypress (no momento da escrita deste conteúdo), há uma seção que comenta da limitação do Cypress funcionar somente em uma aba do navegador.
Muitos(as) vêem isso como uma limitação e não buscam entender como contornar tal situação.
Porém, dependendo do que você precisa testar, contornar isso talvez não seja tão difícil quanto você pensa.
Com o comando .invoke(), você pode invocar a função removeAttr, e como segundo argumento, passar qual atributo deseja remover, tal como o target, o qual, se tivesse o valor _blank, abriria o link em uma nova aba do navegador (veja um exemplo abaixo).
cy.get('#link-que-abre-em-outra-aba')
.invoke('removeAttr', 'target')
Desta forma, você pode fazer algo assim.
cy.get('#link-que-abre-em-outra-aba')
.invoke('removeAttr', 'target')
.click()
E visto que você removeu o atributo target do link que abriria em outra aba, você continua na mesma aba, podendo continuar a executar outras ações ou verificações.
Algo como o seguinte.
cy.get('#link-que-abre-em-outra-aba')
.invoke('removeAttr', 'target')
.click()
cy.get('h1').should('contain', 'Algun texto qualquer')
Obs.: Vale comentar que, para tal alternativa funcionar, a página que abriria em outra aba deve estar no mesmo domínio (ou sub-domínio) da aplicação em teste (ao menos é assim no momento desta escrita). Caso contrário, você precisaria fazer uso da funcioalidade cy.origin().
Exibindo e escondendo elementos
display com valor none (para esconder o elemento), ou alterando tal valor para block ou inline-block (para exibir o elemento).Com o comando .invoke(), podemos exibir um elemento escondido, mesmo que tal evento não ocorra, passando-o a função show (veja abaixo).cy.get('.error')
.invoke('show')
.should('be.visible')
.and('contain', 'Oops! Ocorreu um erro, tente novamente.')Desta forma, é possível testar tal comportamento de forma isolada e rápida.
Da mesma forma que pode-se exibir um elemento escondido, também pode-se esconder um elemento visível.
Por qual motivo eu faria isso?
Uma situação comum é no uso da técnica de testes de regressão visual, onde precisa-se esconder elementos que exibem dados dinâmicos, para que estes não interfiram no resultado dos testes, ou seja, que estes não gerem resultados falsos negativos (testes que estão falhando, quando deveriam estar passando).
Para esconder um elemento (o qual, por exemplo, exibe dados dinâmicos), basta fazer o seguinte.
cy.get('.date-and-time')
.invoke('hide')
.should('not.be.visible')
No exemplo acima, estou capturando um elemento com a classe date-and-time, o qual, por exemplo, exibe a data e hora (um dado dinâmico), e então, estou escondendo-o e garantindo que tal elemento não está mais visível.
Se eu estivesse realizando testes de regressão visual, logo após esconder tal elemento, eu poderia tirar uma screenshot para fazer a verificação visual, e visto que a data e hora foram escondidas, estas não impactariam na comparação de screenshots. Exatamente o que eu queria!
Preenchendo um input invocando e definindo seu valor
.invoke(), passá-lo a função val, em conjunto com o valor que deseja-se definir.Assim.const longText = 'Texto enorme que parece nunca ter fim, pois você quer simular algo o mais perto de como um(a) usuário real usaria a aplicação sendo testada...'cy.get('textarea')
.invoke('val', longText)Com o código acima, em vez do Cypress digitar uma letra após a outra, tal valor seria definido de uma vez só no campo de área de texto.Para um exemlo mais detalhado, leia o conteúdo Como simular um Ctrl+V com Cypress.É isso aí.Espero que tenha gostado e aprendido algo novo.Obs.: Para mais detalhes e casos de uso do comando .invoke(), consulte a documentação oficial do Cypress.
Quer aprender sobre automação de testes web? Conheça os cursos da Escola TAT.
- Cypress Playground
- Cypress, do Zero à Nuvem
- Cypress intermediário
- Cypress avançado
- Boas práticas em automação de testes com Cypress
- Testes end-to-end com Cypress
👋 Até a próxima e bons testes!
Um comentário em “Explorando a funcionalidade .invoke() do Cypress”