React Testing Library: Jak zasymulować wybór opcji z listy?
Opublikowano: 16.09.2023 - tagi: JavaScript React Testowanie Test Komponent Formularz Kontrolka Lista
Lista jednego wyboru
Do pracy z listami biblioteka user-event udostępnia dwie funkcje: selectOptions i deselectOptions.
W tym wpisie do testów posłużę się takim przykładem:
import {useState} from "react";
const mealMap = {
1: "Kebab",
2: "Salad",
3: "Soup"
}
export function MyComponent({mealId}) {
const [meal, setMeal] = useState(mealId);
const onListChange = e => {
setMeal(e.target.value);
}
return (
<>
{ meal &&
<div>
Here we go! Your meal: {mealMap[meal]}
</div>
}
<div>
<label htmlFor="meal">Choose your meal:</label>
<select id="meal" onChange={onListChange}>
<option value=""></option>
<option value="1">A</option>
<option value="2">B</option>
<option value="3">C</option>
</select>
</div>
</>
)
}
Wybieranie opcji — selectOptions
Test:
import {render, screen} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import {MyComponent} from "./MyComponent";
const { getByText, getByLabelText } = screen;
test('should display meal chosen by user', async () => {
// given
render(<MyComponent />);
const select = getByLabelText('Choose your meal:');
// when
await userEvent.selectOptions(select, ['1'])
// then
expect(getByText('Here we go! Your meal: Kebab')).toBeInTheDocument();
});
Odznaczanie opcji
Jeśli masz listę jednego wyboru, to jak można przetestować odznaczanie opcji? Musisz zrobić dwie rzeczy.
Do swojej listy dodaj pustą opcję:
<option value=""></option>
Następnie za pomocą metody selectOptions przekaż pusty string.
import {render, screen} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import {MyComponent} from "./MyComponent";
const { queryByText, getByLabelText } = screen;
test('should deselect meal', async () => {
// given
render(<MyComponent mealId='3' />);
const select = getByLabelText('Choose your meal:');
// when
await userEvent.selectOptions(select, [''])
// then
expect(queryByText('Here we go! Your meal: Soup')).not.toBeInTheDocument();
});
Lista wielokrotnego wyboru
Za pomocą atrybutu multiple sprawisz, że użytkownik będzie mógł wybrać więcej niż jedną opcję.
Komponent:
export function MyComponent() {
return (
<>
<label htmlFor="meal">Choose your meal:</label>
<select id="meal" multiple>
<option value="1">Kebab</option>
<option value="2">Salad</option>
<option value="3">Soup</option>
</select>
</>
)
}
Zaznaczanie wielu opcji — selectOptions
import {render, screen} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import {MyComponent} from "./MyComponent";
const { getByText, getByLabelText } = screen;
test('should choose many meals', async () => {
// given
render(<MyComponent />)
const select = getByLabelText('Choose your meal:');
// when
await userEvent.selectOptions(select, ['2', '3'])
// then
expect(getByText('Salad').selected).toBeTruthy();
expect(getByText('Soup').selected).toBeTruthy();
expect(getByText('Kebab').selected).toBeFalsy();
});
Odznaczanie wielu opcji — deselectOptions
import {render, screen} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import {MyComponent} from "./MyComponent";
const { getByText, getByLabelText } = screen;
test('should deselect many meals', async () => {
// given
render(<MyComponent />)
const select = getByLabelText('Choose your meal:');
await userEvent.selectOptions(select, ['1', '2', '3']);
// when
await userEvent.deselectOptions(select, ['1', '3'])
// then
expect(getByText('Salad').selected).toBeTruthy();
expect(getByText('Soup').selected).toBeFalsy();
expect(getByText('Kebab').selected).toBeFalsy();
});