Testes de unidade JavaScript fáceis no WordPress com Jest
O WordPress tem um longo histórico de testes unitários de seu código PHP. No entanto, escrever testes de unidade JavaScript e testes de integração para o código em temas e plugins não tem o mesmo status. Vamos ver como testar o JavaScript em nossos plugins e temas do WordPress usando Jest.
Estes são os conteúdos que abordaremos neste artigo:
Testes Unitários JavaScript no WordPress
Então, por que escrever testes de unidade e testes de integração? Eles são ótimos para garantir que uma função, método de classe ou até mesmo um componente React faça o que deveria fazer. Ele ajuda a detectar erros no código e também ajuda a preservar a integridade quando as alterações são introduzidas posteriormente no código, verificando se ainda está funcionando conforme o esperado após a atualização.
Os plugins e temas do WordPress são escritos principalmente em PHP e podem usar a suíte PHPUnit para executar testes, fazer declarações, simular funções e muito mais. O manual ainda tem uma seção explicando como configurar rapidamente o teste de unidade com o WP-CLI .
Para JavaScript, há uma página sobre a execução de testes QUnit no Handbook, embora seja mais sobre testar o código JavaScript no núcleo do WordPress.
Embora nada disso seja padronizado para JavaScript no WordPress, podemos escrever ótimos testes de unidade usando o conjunto de testes Jest. Neste artigo vamos aprender como escrever testes de unidade JavaScript para um plugin de exemplo que carrega 5 posts através da WP REST API usando a fetch
função do JavaScript e os renderiza em um determinado elemento DOM na página.
Benefícios de usar Jest para testes de unidade JavaScript no WordPress
No passado, escrever testes de unidade JavaScript envolvia configurar Mocha para executar testes, Chai para fazer asserções e Sinon para simular funções e espioná-las. Embora ofereçam grande flexibilidade, é muito mais complexo trabalhar com três pacotes do que com um. O Jest fornece tudo isso em um único pacote:
- você pode executar testes declarando-os com
describe
eit
outest
- você pode fazer afirmações com
expect
etoBe
,toHaveLength
e muito mais - você pode simular funções e espioná-las, e existem várias maneiras de fazer isso
Antes de seguir em frente
Para manter este artigo focado em testes com Jest, há uma configuração adicional externa ao processo de teste como Babel ou Webpack que não será abordada aqui. Tudo isso pode ser encontrado no repositório WP Jest Tests que acompanha este artigo. Para manter as coisas contextuais, cada seção será vinculada a um dos arquivos relevantes que escreveremos.
Visão geral do lado do PHP
O PHP para o plugin de exemplo que usaremos para aprender a escrever os testes de unidade JavaScript é bastante padrão. As únicas linhas interessantes são aquelas quando enfileiramos nosso arquivo JavaScript e adicionamos um script embutido para passar variáveis para ele:
Depois de enfileirar nosso arquivo JavaScript, adicionamos uma variável global wpJestTests
com wp_add_inline_script()
. Essa variável é particularmente interessante e complicada de lidar porque é externa ao nosso arquivo JavaScript e teremos que zombar dela em nossos testes.
Configurar testes do Jest
Primeiro teremos que inicializar npm
em nosso projeto de plugin para poder instalar o Jest com ele. Navegue na linha de comando até a pasta do seu plugin e execute:
npm init
e percorra a série de prompts aqui
Edite o arquivo package.json que foi criado e adicione uma nova entrada para executar nossos testes na scripts
seção:
"test": "jest"
Este será o comando que usaremos para dizer ao Jest para executar nossos testes de unidade JavaScript. Esta é uma execução única, mas o Jest também suporta a visualização de arquivos, para que você possa inserir uma adicional:
"test-watch": "jest --watch"
Agora instale o Jest como uma dependência de desenvolvimento executando
npm install -D jest
Durante a instalação, crie um arquivo chamado jest.config.js
. Isso manterá toda a configuração necessária. Adicione o seguinte:
module.exports = {
verbose: true,
setupFiles: [
'/__mocks__/globals.js'
],
moduleNameMapper: {
'.(css|less|sass|scss)$': '/__mocks__/styleMock.js'
}
};
Vamos passar por cada um:
verbose
: indica se cada teste individual deve ser relatado durante a execução. Todos os erros também serão mostrados na parte inferior após a execução. Observe que, se houver apenas um arquivo de teste sendo executado, o padrão serátrue
.setupFiles
: uma lista de caminhos para módulos que executam algum código para configurar ou configurar o ambiente de teste. Cada setupFile será executado uma vez por arquivo de teste. Como cada teste é executado em seu próprio ambiente, esses scripts serão executados no ambiente de teste imediatamente antes de executar o próprio código de teste. Usaremos isso para declarar variáveis globais renderizadas por PHP e WordPress com comandos comowp_add_inline_script
ouwp_localize_script
.moduleNameMapper
: este é um mapa de expressões regulares para nomes de módulos (ou arrays de nomes de módulos) que permitem stub out recursos estáticos, como imagens ou estilos com um único módulo.
Você certamente notou a referência: este é um token especial que é substituído pelo Jest com a raiz do seu projeto, que geralmente é a localização do seu arquivo package.json
.
Vamos nos aprofundar nas próximas duas seções, mas primeiro, crie a pasta e esses dois arquivos mencionados acima:
- crie uma pasta com o nome
__mocks__
- dentro da pasta, crie os arquivos
styleMock.js
eglobals.js
Importação de estilos simulados para testes Jest
Se, como este plugin, você usa o Webpack para compilar tudo, incluindo estilos, e está importando o .scss
arquivo no .js
arquivo:
import './main.scss';
você precisa usar styleMock.js para simular arquivos SASS ao importá-los em nosso arquivo JavaScript, caso contrário, o Jest travará, pois não poderá resolver o módulo. Você não precisa de muito para este arquivo, basta adicionar
O Jest usará esse mock toda vez que encontrar uma .scss
importação e os mapeará para o mock, permitindo que você avance com os testes sem se preocupar com os estilos.
Configurar globais para Jest
Vamos trabalhar agora no arquivo globals.js. Uma das vantagens de usar o Jest, é que ele já vem com um já configurado jsdom
, uma implementação de padrões web puro-JavaScript, que simula um ambiente DOM como se você estivesse no navegador, e vamos usá-lo para simular elementos DOM para nossos testes.
Crie uma pasta __mocks__
e um globals.js
arquivo dentro dela. Adicione isso ao arquivo:
import { JSDOM } from 'jsdom';
const dom = new JSDOM();
global.document = dom.window.document;
global.window = dom.window;
global.window.wpJestTests = undefined;
Isso declarará e zombará de alguns objetos e métodos que você usará posteriormente em seus testes. O último é de particular interesse
global.window.wpJestTests = undefined;
Esta é a variável global que escrevemos usando wp_add_inline_script
. Você precisa zombar dela como uma variável global para poder usá-la em seus testes.
Visão geral do arquivo JavaScript
O plugin do WordPress tem um único arquivo JavaScript main.js em uma /src
pasta. Isso é posteriormente transpilado e gerado em um /js/front.js
arquivo que é o que o PHP carregará. O JavaScript carrega cinco posts do WordPress usando fetch
, uma função JavaScript padrão, por meio da API WP REST e insere seu título, com um link para o post, em um arquivo div.entry-content
.
Você vai exportar a função que faz todo o trabalho:
para que você possa usá-lo em seus testes no Jest.
Escrevendo testes de unidade JavaScript com Jest, finalmente!
Agora você pode começar a escrever testes! Jest pode encontrar testes de várias maneiras:
- se o nome do arquivo for
test.js
- ou é prefixado com o nome do arquivo que testa, como
main.test.js
- se forem
.js
arquivos localizados em uma pasta chamada__tests__
Crie a __tests__
pasta e dentro dela, um arquivo front.test.js
. Você pode ver o arquivo JavaScript finalizado para os testes Jest no repositório complementar. Vamos passar por isso em blocos. A primeira linha importa o arquivo JS que queremos testar:
import { wpJestTestsInit } from '../src/main';
Em seguida, limpamos todos os mocks, para que nunca executemos mocks sujos carregando valores de testes anteriores. Fazer isso pode levar a erros, pois, por exemplo, se estivermos espionando quantas vezes uma função simulada foi chamada, podemos obter uma leitura incorreta se não limparmos a simulação entre teste e teste:
O primeiro teste que escreveremos faz afirmações básicas quando algumas coisas falham. Por exemplo, se a variável global wpJestTests
com a qual estávamos escrevendo wp_add_inline_script
não foi escrita por qualquer motivo:
Neste código,
describe
cria um grupo composto por vários testes relacionadostest
é o que realmente realiza um testeexpect
envolve nosso assunto de teste fornecendo acesso a vários “matchers" que permitem fazer diferentes afirmações sobre seu conteúdotoBe
é um desses matchers. O Jest tem muitos matchers incluídos e há ainda outros que você pode adicionar com um pacote de terceiros.
O primeiro teste não está definindo nada para wpJestTests
, portanto, seu valor será o que você definiu em globals.js
. Como é undefined
, não podemos trabalhar, então queremos confirmar que a função retorna sem fazer nada.
O segundo teste define wpJestTests
e simula o document.querySelector
método para retornar undefined
que é o que ele retornaria se não pudesse encontrar um elemento no DOM. Nesse caso, queremos confirmar que estamos retornando sem fazer nada e que nossa função mocking document.querySelector
foi chamada uma vez.
Busca simulada em testes Jest
O próximo conjunto de testes começa com
e dentro disso, temos outra função tear down:
ao contrário afterEach
disso, será executado depois que todos os testes dentro deste describe
bloco forem executados. Como nosso arquivo JavaScript usa fetch
para carregar os posts, precisamos verificar se ele foi chamado e retornou o que solicitamos, então vamos zombar da fetch
função:
Nós zombamos da primeira Promise que resolve para a resposta e a segunda para uma representação JSON dos dados. Esses dados são semelhantes aos que obtemos da API REST do WP. Dado que nosso código precisa apenas do título e do link, estamos zombando disso.
Teste de integração JavaScript com Jest em código assíncrono que usa fetch
Agora podemos escrever o teste usando o mocked fetch
. Há uma grande diferença com este teste em comparação com os outros testes de unidade JavaScript: este é um teste de integração. Testes anteriores explorados aqui simplesmente garantiram que um componente estava funcionando bem. Verificamos que se a variável global de estado inicial não estivesse definida, nosso componente não renderia. Isso é diferente porque vamos testar como todo o sistema funciona quando a variável de estado inicial é definida, acionando assim uma transação de dados e, finalmente, inserindo os títulos dos posts com seus links no documento.
Desde o início, isso é diferente: a função anônima passada para test
recebe um done
parâmetro. Esta é, na verdade, uma função que será chamada quando terminarmos o teste. Jest vai esperar até done
ser chamado antes de terminar o teste. Se done
nunca for chamado, o teste falhará com um erro de tempo limite. Isso é interessante para nós, pois estamos testando código envolvendo fetch
, que é uma função assíncrona.
O global wpJestTests
está definido e nosso mocked document.querySelector
agora retorna o que se assemelha a um elemento HTML, com even classList
e seu add
método filho.
Chamamos wpJestTestsInit
e esperamos que termine corretamente. Agora, como fetch
é assíncrono, vamos fazer uso process.nextTick
do Node.js. O nextTick
no Node.js é a fila que será executada após a conclusão de todos os eventos no loop de eventos atual. Isso é ótimo porque todas as nossas promessas seriam resolvidas então, que é exatamente o que precisamos para testar esse código que envolve fetch
.
O resto são mais asserções para garantir que querySelector
encontrou algo com que trabalhar, que de fetch
fato foi chamado, que uma classe foi adicionada à lista, e que os títulos e links de nossos posts foram inseridos no elemento HTML correspondente. Quando tudo estiver pronto, chamamos done
e nosso teste assíncrono termina.
Execute seus testes Jest
Agora você pode digitar
npm run test
e o Jest executará os testes de unidade JavaScript para o seu plugin WordPress
Conclusão
Então Jest é uma solução ótima e simples para escrever testes que cobrem o código JavaScript de nossos plugins ou temas do WordPress. Mas há mais. Se estivermos escrevendo um aplicativo React para nosso plugin, podemos querer fazer afirmações sobre ele. O Jest também pode ajudar até certo ponto e, se precisarmos de mais, podemos adicionar Enzyme às nossas ferramentas e começar a escrever testes de integração com ele.
Por favor doe!
Se você achou isso útil, sinta-se à vontade para me pagar um café para que eu possa ficar acordado e criar tutoriais mais úteis para você!
$ 3,00