43
loading...
This website collects cookies to deliver better user experience
checkout
na branch
exercise-02
para continuar de onde paramos.Form.test.js
dentro de src/components
e adicione o seguinte conteúdo:import { render, screen } from "@testing-library/react";
import Form from "./Form";
test("submitting the form calls onSubmit with value and coin", () => {
render(<Form />);
screen.getByLabelText(/valor/i);
screen.getByLabelText(/moeda/i);
screen.getByRole("button", { name: /calcular/i });
});
render
. Existem diferentes tipos de queries, você pode ver com mais detalhes acessando a documentação.getByLabelText
e getByRole
.Form.js
, com o seguinte conteúdo:const Form = () => <form />
export default Form
npm test -- --watch
, dessa forma os testes serão executados sempre que um arquivo for modificado. Agora observe o erro:TestingLibraryElementError: Unable to find a label with the text of: /valor/i
Ignored nodes: comments, <script />, <style />
<body>
<div>
<form />
</div>
</body>
5 | render(<Form />);
6 |
> 7 | screen.getByLabelText(/valor/i);
getBy
e o elemento não é encontrado, o teste deve falhar, e além de exibir uma mensagem de erro, também é exibido o html
do componente, além da linha onde o teste falhou.const Form = () => (
<form>
<label htmlFor="value">Valor</label>
<input type="number" id="value" />
</form>
)
> 8 | screen.getByLabelText(/moeda/i);
const Form = () => (
<form>
<label htmlFor="value">Valor</label>
<input type="number" id="value" />
<label htmlFor="coin">Moeda</label>
<select id="coin">
<option value="USD">Dolar Americano</option>
<option value="EUR">Euro</option>
<option value="GBP">Libra Esterlina</option>
</select>
</form>
)
> 9 | screen.getByRole("button", { name: /calcular/i });
const Form = () => (
<form>
<label htmlFor="value">Valor</label>
<input type="number" id="value" />
<label htmlFor="coin">Moeda</label>
<select id="coin">
<option value="USD">Dolar Americano</option>
<option value="EUR">Euro</option>
<option value="GBP">Libra Esterlina</option>
</select>
<button type="submit">Calcular</button>
</form>
)
Form
deve receber uma prop
chamada onSubmit
, ela será uma função que deve ser chamada com os valores preenchidos no formulário quando ocorrer o evento submit
.test("submitting the form calls onSubmit with value and coin", () => {
const handleSubmit = jest.fn();
render(<Form onSubmit={handleSubmit} />);
jest.fn()
retorna uma função mock, esse tipo de função também é conhecido como "spy", e como o próprio nome já diz, eles "espionam" informações secretas sobre funções. Elas possibilitam saber, quantas vezes uma função foi chamada, quais parâmetros ela recebeu, etc.handleSubmit
criada, precisamos preencher o formulário com alguns valores e clicar no botão para submeter o formulário. Para executar o evento de clique precisamos importar o fireEvent
da Testing Library. Faça as seguintes alterações no teste:import { render, screen, fireEvent } from "@testing-library/react";
import Form from "./Form";
test("submitting the form calls onSubmit with value and coin", () => {
const handleSubmit = jest.fn();
render(<Form onSubmit={handleSubmit} />);
screen.getByLabelText(/valor/i).value = "3000";
screen.getByLabelText(/moeda/i).value = "USD";
fireEvent.click(screen.getByRole("button", { name: /calcular/i }));
});
Error: Not implemented: HTMLFormElement.prototype.submit
jest.config.js
, poderá ver a seguinte linha:testEnvironment: "jsdom"
jsdom
não conta com o evento submit
padrão do navegador, e nós também não temos intenção de usá-lo, então para resolver isso, faça a seguinte mudança no componente:const Form = () => {
const handleSubmit = (e) => {
e.preventDefault();
};
return (
<form onSubmit={handleSubmit}>
handleSubmit
seja chamada com as informações corretas quando o formulário é submetido.expect
no final do arquivo Form.test.js
:expect(handleSubmit).toHaveBeenCalledWith({
value: "3000",
coin: "USD",
});
Form
chame a função que foi passada na prop
onSubmit
.Form.js
:const Form = ({ onSubmit }) => {
const handleSubmit = (e) => {
e.preventDefault();
const { value, coin } = e.target.elements;
onSubmit({
value: value.value,
coin: coin.value,
});
};
expect
para garantir que a função foi chamada apenas uma vez:expect(handleSubmit).toHaveBeenCalledTimes(1);
screen.getByLabelText(/valor/i).value = "3000";
screen.getByLabelText(/moeda/i).value = "USD";
fireEvent.click(screen.getByRole("button", { name: /calcular/i }));
click
.keydown
, keyup
, change
, ocorrem diferentes tipos de eventos.user-event
, que também faz parte da Testing Library.user-event
:npm i -D @testing-library/user-event
Form.test.js
, para que fique assim:import { render, screen } from "@testing-library/react";
import userEvent from '@testing-library/user-event'
import Form from "./Form";
test("submitting the form calls onSubmit with value and coin", () => {
const handleSubmit = jest.fn();
render(<Form onSubmit={handleSubmit} />);
userEvent.type(screen.getByLabelText(/valor/i), "3000");
userEvent.selectOptions(screen.getByLabelText(/moeda/i), "USD");
userEvent.click(screen.getByRole("button", { name: /calcular/i }));
expect(handleSubmit).toHaveBeenCalledWith({
value: "3000",
coin: "USD",
});
expect(handleSubmit).toHaveBeenCalledTimes(1);
});
mock
, passamos como prop
, adicionamos eventos, enfim, fizemos bastante coisa. Confesso que foi bem difícil resumir tudo. Como queria fazer algo bem prático, não me aprofundei muito em alguns pontos, mas procurei deixar links em todos eles.