React Testing Library์ ์ปดํฌ๋ํธ ํ ์คํธ
ํน์ ๊ฐ๋ฐ(๋ฆฌ์กํธ ์ธ ๋ทฐ,์ค๋ฒจํธ์์๋), ํ ์คํธ ํ๋ ์์ํฌ์ ์ข ์๋์ง๋ ์๋๋ค.
Testing Library์ ํต์ฌ ์ฒ ํ์ UI ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉ์๊ฐ ์ฌ์ฉํ๋ ๋ฐฉ์์ผ๋ก ํ ์คํธ ํ๋๊ฒ.
- ์ฌ์ฉ์๊ฐ ์ฌ์ฉํ๋ ๋ฐฉ์ : DOM ๋ ธ๋ ์กฐํ, ์ฌ์ฉ์์ ๋น์ทํ ๋ฐฉ์์ผ๋ก ์ด๋ฒคํธ ๋ฐ์.
- ํ ์คํธ ์ฝ๋ ์์ฑ ์์น์ค ์ธํฐํ์ด์ค๋ฅผ ๊ธฐ์ค์ผ๋ก ์์ฑํด์ผํ๋ค๋ ์์น๊ณผ ์ผ์น.
- getBy api์ค role, label-text, image-alt-text ์ฒ๋ผ ์ฌ์ฉ์ ๊ด์ ์ ๊ฐ๊น์ด api๋ฅผ ์ฌ์ฉํ๋ค.
userEvent
// TextField.spec.jsx
import render from '@/utils/test/render';
it('ํ
์คํธ๋ฅผ ์
๋ ฅํ๋ฉด onChange prop์ผ๋ก ๋ฑ๋กํ ํจ์๊ฐ ํธ์ถ๋๋ค', async () => {
const { user } = await render(<TextField />);
const textInput = screen.getByPlaceholderText('์ํ๋ช
์ ์
๋ ฅํด ์ฃผ์ธ์.');
await user.type(textInput, 'test');
...
});
// render.jsx
import { render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
export default async component => {
const user = userEvent.setup();
return {
user,
...render(component),
};
};
userEvent.setup() ํจ์๊ฐ ๋ฐํํ๋ user๊ฐ์ฒด๋ ์ฌ์ฉ์์ ํ๋์ ์๋ฎฌ๋ ์ด์
ํ๋ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํฌ ์ ์๋ค.
spy ํจ์
vi.fn() ํจ์๋ฅผ ํธ์ถํด ๋ง๋ค ์ ์๋ค.
์คํ์ด ํจ์๋ ํ
์คํธ ์ฝ๋์์ ํน์ ํจ์๊ฐ ํธ์ถ๋์๋์ง, ํจ์์ ์ธ์๋ก ์ด๋ค ๊ฒ์ด ๋์ด์๊ณ ์ด๋ค ๊ฐ์ ๋ฐํํ๋์ง ๋ฑ ๋ค์ํ ๊ฐ๋ค์ ์ ์ฅํ๊ณ ์๋ค.
์ปดํฌ๋ํธ ์์์ ์คํ๋๋ ํจ์๋ฅผ ๊ฒ์ฆํ๊ธฐ ์ํด ํ์๋ค.
it('ํ
์คํธ๋ฅผ ์
๋ ฅํ๋ฉด onChange prop์ผ๋ก ๋ฑ๋กํ ํจ์๊ฐ ํธ์ถ๋๋ค', async () => {
const spy = vi.fn();
const { user } = await render(<TextField onChange={spy} />);
const textInput = screen.getByPlaceholderText('ํ
์คํธ๋ฅผ ์
๋ ฅํด ์ฃผ์ธ์.');
await user.type(textInput, 'test');
expect(spy).toHaveBeenCalledWith('test');
});
