mirror of
https://github.com/Growstuff/growstuff.git
synced 2026-10-29 10:18:29 -04:00
86 lines
2.8 KiB
React
86 lines
2.8 KiB
React
import {render, screen} from '@testing-library/react';
|
|
import userEvent from '@testing-library/user-event';
|
|
import {beforeEach, describe, expect, it, vi} from 'vitest';
|
|
|
|
import CropPicker from './CropPicker';
|
|
|
|
const maize = {id: 1, name: 'maize', slug: 'maize'};
|
|
const mango = {id: 2, name: 'mango', slug: 'mango'};
|
|
|
|
// A fetch that answers every search with these crops.
|
|
function stubSearch(crops) {
|
|
const fetch = vi.fn(async () => ({ok: true, status: 200, json: async () => crops}));
|
|
vi.stubGlobal('fetch', fetch);
|
|
return fetch;
|
|
}
|
|
|
|
function setup(props = {}) {
|
|
const onChoose = vi.fn();
|
|
const user = userEvent.setup();
|
|
render(<CropPicker id="crop" autoFocus={false} onChoose={onChoose} {...props} />);
|
|
return {onChoose, user, input: screen.getByRole('combobox')};
|
|
}
|
|
|
|
describe('CropPicker', () => {
|
|
beforeEach(() => stubSearch([maize, mango]));
|
|
|
|
it('searches for what is typed', async () => {
|
|
const fetch = stubSearch([maize]);
|
|
const {user, input} = setup();
|
|
await user.type(input, 'mai');
|
|
await screen.findByRole('option', {name: 'maize'});
|
|
expect(fetch).toHaveBeenLastCalledWith('/crops/search.json?term=mai', expect.anything());
|
|
});
|
|
|
|
it('lists the matches', async () => {
|
|
const {user, input} = setup();
|
|
await user.type(input, 'm');
|
|
expect(await screen.findAllByRole('option')).toHaveLength(2);
|
|
});
|
|
|
|
it('does not search for a blank term', async () => {
|
|
const fetch = stubSearch([]);
|
|
const {user, input} = setup();
|
|
await user.type(input, ' ');
|
|
expect(fetch).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('chooses a match by clicking it', async () => {
|
|
const {onChoose, user, input} = setup();
|
|
await user.type(input, 'm');
|
|
await user.click(await screen.findByRole('option', {name: 'mango'}));
|
|
expect(onChoose).toHaveBeenCalledWith(mango);
|
|
});
|
|
|
|
it('chooses the top match with Enter', async () => {
|
|
const {onChoose, user, input} = setup();
|
|
await user.type(input, 'm');
|
|
await screen.findAllByRole('option');
|
|
await user.keyboard('{Enter}');
|
|
expect(onChoose).toHaveBeenCalledWith(maize);
|
|
});
|
|
|
|
it('chooses the highlighted match with the arrow keys', async () => {
|
|
const {onChoose, user, input} = setup();
|
|
await user.type(input, 'm');
|
|
await screen.findAllByRole('option');
|
|
await user.keyboard('{ArrowDown}{ArrowDown}{Enter}');
|
|
expect(onChoose).toHaveBeenCalledWith(mango);
|
|
});
|
|
|
|
it('closes the matches with Escape', async () => {
|
|
const {user, input} = setup();
|
|
await user.type(input, 'm');
|
|
await screen.findAllByRole('option');
|
|
await user.keyboard('{Escape}');
|
|
expect(screen.queryByRole('option')).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('says when nothing matches', async () => {
|
|
stubSearch([]);
|
|
const {user, input} = setup();
|
|
await user.type(input, 'zzz');
|
|
expect(await screen.findByText(/No crops match/)).toBeInTheDocument();
|
|
});
|
|
});
|