Claro, mostro sim, segue esse artigo que você vai entender como testar alguns cenários, e alguns dos pensamentos que temos quando estamos escrevendo testes.
📑
Vamos usar o modelo Teste Pilha Palito
, não - calma… brincadeira, é que temos um modelo de organização que abreviado fica AAA: Arrange > Act > Assert
.
Ou seja, dentro do teste temos:
O teste roda em cascata, executando de cima para baixo, então se seu Assert verifica um clique em um botão para uma determinada ação, você precisa executar essa ação antes, no Act. E se o seu Act precisa de um contexto ou uma view renderizada, você executa isso no Arrange.
Alguns testes de tela possuem apenas duas etapas, onde o Arrange e Act são o mesmo, como um render()
, por exemplo, ou seja, nem todos os testes seguem rigorosamente esse modelo, nem devem, na verdade, essa é uma forma de organizar o teste para que fique mais simples, você deve usar para ser guiado durante o desenvolvimento.
Vamos considerar o formulário abaixo como exemplo:
Referência da imagem: https://tailwindcomponents.com/component/minimal-login-form-2
Nos exemplos a seguir, estaremos escrevendo os testes utilizando a Vue Testing Library.
Existem vários cenários de teste que podem ser aplicados nesse componente, vamos começar verificando se os campos foram renderizados corretamente para o usuário.
test("Should render the component properly", () => {
// act
render(Component);
// assert
expect(screen.getByRole("textbox", { name: /First name/i })).toBeInTheDocument();
expect(
screen.getByRole("textbox", { name: /Last name/i })
).toBeInTheDocument();
expect(screen.getByRole("textbox", { name: /Company/i })).toBeInTheDocument();
expect(screen.getByRole("textbox", { name: /E-mail/i })).toBeInTheDocument();
expect(screen.getByRole("button", { name: /Login/i })).toBeDisabled();
});
Seguindo o princípio que devemos escrever testes que assemelham como a página é utilizada pelo usuário, foi utilizada a query getByRole
para obter os elementos conforme a sua função. Par esse tipo de teste, podemos verificar se os elementos críticos para funcionamento do componente foram exibidos, o estado inicial de alguns componentes conforme alguma regra de negócio (por exemplo, o botão deve estar desabilitado até o preenchimento do formulário), ou seja.
Nesse teste, usamos a biblioteca @testing-library/jest-dom para ter acessos a métodos de verificação no jest
Para o próximo testes, vamos validar se quando o formulário é preenchido corretamente o evento submit
é emitido corretamente com as propriedades.
test("Should emit submit when valid data is inseted in the form", async () => {
// arrange
const user = userEvent.setup();
const { emitted } = render(Component);
//act
await user.type(screen.getByRole("textbox", { name: /First name/i }, "Iron"));
await user.type(
screen.getByRole("textbox", { name: /Last name/i }, "Maiden")
);
await user.type(
screen.getByRole("textbox", { name: /E-mail/i }, "iron@maiden.com")
);
await user.type(
screen.getByRole("textbox", { name: /Company/i }, "Beast Inc.")
);
await user.click(screen.getByRole("button", { name: /Login/i }));
//assert
expect(emitted().submit).toBeTruthy();
expect(emitted().submit[0]).toEqual([
{ firstName: "Iron", lastName: "Maiden", email: "iron@maiden.com", company: "Beast Inc." },
]);
});
Na preparação do teste, antes do componente ser renderizado invocamos userEvent.setup()
. A user-event é uma biblioteca complementar, a Testing Library simula a interação do usuário como se ele estivesse acontecendo no navegador. A seguir renderizamos o componente e obtemos o objeto emitted
. Esse objeto irá conter os eventos emitidos conforme interagimos com os componentes.
Após a configuração do contexto, podemos usar o objeto user
para preencher o formulário através do método user.type()
e clicar no botão usando o user.click()
.
Na etapa de verificação, usamos o `emitted` para validar que o evento foi gerado corretamente.
Em alguns componentes pode ser interessante validar o comportamento se algo errado acontecer.
test("Should not emit submit and display error message when email is invalid", async () => {
// arrange
const user = userEvent.setup();
const { emitted } = render(Subscriber);
// act
await user.type(screen.getByRole("textbox", { name: /nome/i }, "Alice"));
await user.type(
screen.getByRole("textbox", { name: /celular/i }, "11988887777")
);
await user.type(screen.getByRole("textbox", { name: /email/i }, "alice"));
await user.click(screen.getByRole("button", { name: /cadastrar/i }));
//assert
expect(emitted().submit).not.toBeTruthy();
expect(screen.getByText(/informe um e-mail válido/i)).toBeInTheDocument();
});
Em diversos componentes vamos precisar de passar propriedades externas. Para isso, o método render
da Testing Library pode receber uma propriedade chamada props
no objeto de opções:
<MyComponent message="hello" />
const props = { message: "hello" };
render(MyComponent, { props });
Semelhante ao exemplo anterior, podemos também podemos passar os slots no objeto de opções:
<template>
<div>
<slot name="description" />
<slot name="content" />
</div>
</template>
const slots = {
description: '<p>Description text</p>',
content: '<p>Content text</p>'
}
render(MyComponent, {slots});
expect(screen.getByText('Description text')).toBeInTheDocument()
expect(screen.getByText('Description text')).toBeInTheDocument()
Quando precisamos validar comportamentos em funções chamadas pelos nossos componentes podemos utilizar alguns recursos de mock
e spy
do jest. Como exemplo, imagine que em um componente ao clicar em no botão devemos rolar para o início da tela utilizando o window.scrollTo(0, 0)
.
describe("My component", () => {
const scrollToSpy = jest.fn();
window.scrollTo = scrollToSpy;
beforeEach(() => {
jest.clearAllMocks();
});
test("Should scroll to top", async () => {
const user = userEvent.setup();
render(MyComponent);
await user.click(screen.getByRole("button", { name: /ir para início/i }));
expect(scrollToSpy).toHaveBeenCalledTimes(1);
});
});