33
loading...
This website collects cookies to deliver better user experience
checkout
na branch exercise-04
.App.test.js
dentro de src
e adicione o seguinte:import { render } from "@testing-library/react";
import App from "./App";
test("shows the amount in brazilian real after submit", () => {
render(<App />);
});
npm test -- --watch
, e em seguida crie o arquivo App.js
dentro de src
.const App = () => null;
export default App;
Form
e Highlight
;multiply
multiplica o valor pela cotação;multiply
é salvo em um estado e atualizado no componente.App.test.js
:import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import App from "./App";
test("shows the amount in brazilian real after submit", () => {
render(<App />);
userEvent.type(screen.getByLabelText(/valor/i), "3000");
userEvent.selectOptions(screen.getByLabelText(/moeda/i), "USD");
userEvent.click(screen.getByRole("button", { name: /calcular/i }));
expect(screen.getByText("14808.9")).toBeInTheDocument();
});
render
, o formulário é preenchido com o userEvent
e após o clique do botão verificamos se o valor esperado está sendo exibido.TestingLibraryElementError: Unable to find a label with the text of: /valor/i
App.js
:import Form from "./components/Form";
import Highlight from "./components/Highlight";
const App = () => {
const handleSubmit = () => null;
return (
<>
<Form onSubmit={handleSubmit} />
<Highlight value="14808.90" />
</>
)
};
App.js
.import { useState } from "react";
import Form from "./components/Form";
import Highlight from "./components/Highlight";
import { multiply } from './utils/math'
const App = () => {
const [value, setValue] = useState(null);
const handleSubmit = async ({ value, coin }) => {
const res = await window.fetch(
`https://economia.awesomeapi.com.br/json/last/${coin}-BRL`
);
const data = await res.json();
const result = multiply(data[`${coin}BRL`].ask, value).toFixed(2);
setValue(result);
};
return (
<>
<Form onSubmit={handleSubmit} />
<Highlight value={value} />
</>
)
};
handleSubmit
envia os dados, multiplica os valores e armazena o valor em um estado, exatamente como descrevemos antes.TypeError: window.fetch is not a function
npm install --save whatwg-fetch
jest.config.js
:setupFiles: [require.resolve('whatwg-fetch')],
fetch
no ambiente de testes. Se você olhar no terminal, os erros sobre o fetch
não aparecem mais, o único problema é o teste falhando, mas já vamos resolver isso.> 12 | expect(screen.getByText("14808.90")).toBeInTheDocument();
div
onde o valor deveria estar, está vazia:<body>
<div>
<form>...</form>
<div />
</div>
</body>
expect
foi executado antes da requisição ser concluída. Para resolver isso, precisamos fazer duas alterações.test("shows the amount in brazilian real after submit", async () => {
render(<App />);
findBy
ao invés de getBy
, queries desse tipo são assíncronas.expect(await screen.findByText("14808.90")).toBeInTheDocument();
fetch
original, precisamos de algo que funcione no lugar dele, um mock
.beforeAll(() => jest.spyOn(window, "fetch"));
spyOn
funciona de forma parecida com o jest.fn
, ele recebe um objeto, o nome do método que será mocado e adiciona as propriedades de uma função mock, permitindo fazer as seguintes asserções:expect(window.fetch).toHaveBeenCalledWith(
"https://economia.awesomeapi.com.br/json/last/USD-BRL"
);
expect(window.fetch).toHaveBeenCalledTimes(1);
fetch
original continua sendo chamado. Para que isso não aconteça, podemos usar o método mockImplementationOnce
para definir uma implementação própria para o fetch
. Adicione o seguinte código após a chamada do render
no teste:window.fetch.mockImplementationOnce(() => Promise.resolve({
ok: true,
json: async () => ({
USDBRL: { ask: "4.9363" },
}),
}));
fetch
original, a função que passamos para o mockImplementationOnce
é que será chamada. O Jest conta com um método chamado mockResolvedValueOnce
que é um "syntactic sugar" para o que acabamos de fazer.window.fetch.mockResolvedValueOnce({
ok: true,
json: async () => ({
USDBRL: { ask: "4.9363" },
}),
});
test("renders an error message from the server", async () => {
const testError = "test error";
render(<App />);
window.fetch.mockResolvedValueOnce({
ok: false,
json: async () => ({ message: testError }),
});
userEvent.type(screen.getByLabelText(/valor/i), "3000");
userEvent.selectOptions(screen.getByLabelText(/moeda/i), "USD");
userEvent.click(screen.getByRole("button", { name: /calcular/i }));
expect(await screen.findByRole("alert")).toHaveTextContent(testError);
});
App.js
const App = () => {
const [value, setValue] = useState(null);
const [error, setError] = useState(null);
const handleSubmit = async ({ value, coin }) => {
const res = await window.fetch(
`https://economia.awesomeapi.com.br/json/last/${coin}-BRL`
);
const data = await res.json();
if (!res.ok) {
setError(data.message);
return;
}
const result = multiply(data[`${coin}BRL`].ask, value).toFixed(2);
setValue(result);
};
return (
<>
<Form onSubmit={handleSubmit} />
<Highlight value={value} />
{error ? <div role="alert">{error}</div> : null}
</>
)
};