wait, waitForDomChange, and waitForElement have been combined into the waitFor method.
lien : https://testing-library.com/docs/dom-testing-library/api-async/
Donc, il faut utiliser
- soit
waitFor
- soit
findBy
**,- ou bien,
waitForElementToBeRemoved
findBy
** Queriessimilaire avec getBy
** mais de manière asynchronique
waitFor
function waitFor<T>(
callback: () => T | Promise<T>,
options?: {
container?: HTMLElement
timeout?: number
interval?: number
onTimeout?: (error: Error) => Error
mutationObserverOptions?: MutationObserverInit
}
): Promise<T>
waitForElementToBeRemoved
function waitForElementToBeRemoved<T>(
callback: (() => T) | T,
options?: {
container?: HTMLElement
timeout?: number
interval?: number
onTimeout?: (error: Error) => Error
mutationObserverOptions?: MutationObserverInit
}
): Promise<void>
import React, { useState } from "react";
function DelayedToggle() {
const [toggle, setToggle] = useState(false);
const onToggle = () => {
setTimeout(() => {
setToggle((toggle) => !toggle);
}, 1000);
};
return (
<div>
<button onClick={onToggle}>Toggle</button>
<div>
state : <span>{toggle ? "ON" : "OFF"}</span>
</div>
{toggle && <div>Boom!!</div>}
</div>
);
}
export default DelayedToggle;
import DelayedToggle from "./DelayedToggle";
import {
render,
screen,
waitFor,
waitForElementToBeRemoved,
} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
describe("<DelayedToggle/>", () => {
let container;
let toggleButton;
beforeEach(() => {
container = render(<DelayedToggle />).container;
toggleButton = screen.getByText("Toggle");
});
it("reveals text when toggle is On", async () => {
userEvent.click(toggleButton);
await screen.findByText("Boom!!");
// await waitFor(() => screen.getByText("Boom!!"));
});
it("toggles text On/Off", async () => {
userEvent.click(toggleButton);
//utilise find
const text1 = await screen.findByText("ON");
expect(text1).toHaveTextContent("ON");
//utilise waitFor avec son option {timeout:}
const text2 = await waitFor(() => screen.getByText("ON"), {
timeout: 3000,
});
expect(text2).toHaveTextContent("ON");
});
it("changes something when button is clicked", async () => {
userEvent.click(toggleButton);
// const mutations = await waitFor(() => screen.getByText("ON"));
const mutations = await screen.findByText("ON");
//console.log(mutations);
});
it("remove text when toggle is OFF", async () => {
userEvent.click(toggleButton);
await screen.findByText("ON"); // toggle "ON"
userEvent.click(toggleButton);
await waitForElementToBeRemoved(() => screen.getByText("Boom!!"));
});
});
axios-mock-adapter
En général, on ne fait pas la requête directement au serveur.
Puisque, le serveur marche bien ou pas,ce n'est pas l'objectif/intérêt
du test en frontend.
L'enjeu
de ce test, c'est de vérifier si les datas reçus s'affichent bien
dans l'écran.
C'est la raison pour laquelle il faudrait
axios-mock-adapter
Comme
Mocking function
, il limite comme si on reçoit des datas du serveur.
$yarn add axios-mock-adapter
Créer instance mock
const
mock =new
MockAdapter(axios, {delayResponse?:__MS__ :number
});
onGet
: répond à axios.get()
prototype: mock.onGet(__ADDRESS__:
string
).reply(__STATUS__ , __DATA__:object
)
import UserProfile from "./UserProfile";
import axios from "axios";
import { render, screen, waitFor } from "@testing-library/react";
import MockAdapter from "axios-mock-adapter";
describe("<UserProfile/>", () => {
const mock = new MockAdapter(axios, { delayResponse: 200 }); //200ms faux delai
mock.onGet("https://jsonplaceholder.typicode.com/users/1").reply(200, {
id: 1,
name: "Leanne Graham",
username: "Bret",
email: "Sincere@april.biz",
address: {
street: "Kulas Light",
suite: "Apt. 556",
city: "Gwenborough",
zipcode: "92998-3874",
geo: {
lat: "-37.3159",
lng: "81.1496",
},
},
phone: "1-770-736-8031 x56442",
website: "hildegard.org",
company: {
name: "Romaguera-Crona",
catchPhrase: "Multi-layered client-server neural-net",
bs: "harness real-time e-markets",
},
});
it("calls getUser API loads & userData correctly", async () => {
render(<UserProfile id={1} />);
await waitFor(() => screen.getByText("Loading...")); // pass si "Loading..." s'affiche
await waitFor(() => screen.getByText("Bret")); // pass si Bret(username) s'affiche
});
});
axios-mock-adapter
.replyOnce()
: utilise mocking une seule fois puis requête de manière ordinaire
(directement au serveur).
mock.
onGet
('/users').replyOnce(200, users);
utilise plusieurs fois .replyOnce()
:
mock.onGet('/users').replyOnce(200,users).
onGet('/users').replyOnce(500)
.onAny()
: mocking soit .onGet()
soit .onPost()
reset
& restore
mock.
reset()
: supprimer handlers inscrites à mockInstance
à utiliser si on veut configurer différemment mock par cas.
** Peut-être, utile avec
BeforeEach() ou AfterEach()
?mock.
restore()
: supprimer complètement moking dans axios.