123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- import userEvent from '@testing-library/user-event';
- import {findAllByText, findByText, type Matcher, waitFor} from './reactTestingLibrary';
- function getReactSelectContainerFromInput(input: HTMLElement): HTMLElement {
- return input.parentNode!.parentNode!.parentNode!.parentNode!.parentNode as HTMLElement;
- }
- type User = ReturnType<typeof userEvent.setup> | typeof userEvent;
- type UserEventOptions = {
- user?: User;
- };
- const openMenu = async (
- input: HTMLElement,
- {user = userEvent}: UserEventOptions = {}
- ) => {
- await user.click(input, {skipHover: true});
-
-
- };
- const type = async (
- input: HTMLElement,
- text: string,
- {user}: Required<UserEventOptions>
- ) => {
- await user.type(input, text);
- };
- const clear = async (clearButton: Element, {user}: Required<UserEventOptions>) => {
- await user.click(clearButton, {skipHover: true});
- };
- interface Config extends UserEventOptions {
-
- container?: HTMLElement | (() => HTMLElement);
- }
- /**
- * Utility for selecting a value in a `react-select` dropdown.
- * @param input The input field (eg. `getByLabelText('The label')`)
- * @param optionOrOptions The display name(s) for the option(s) to select
- */
- const select = async (
- input: HTMLElement,
- optionOrOptions: Matcher | Array<Matcher>,
- {user = userEvent, ...config}: Config = {}
- ) => {
- const options = Array.isArray(optionOrOptions) ? optionOrOptions : [optionOrOptions];
-
- for (const option of options) {
- await openMenu(input, {user});
- let container: HTMLElement;
- if (typeof config.container === 'function') {
-
-
- await waitFor(config.container);
- container = config.container();
- } else if (config.container) {
- container = config.container;
- } else {
- container = getReactSelectContainerFromInput(input);
- }
-
- const matchingElements = await findAllByText(container, option, {
- ignore: "[aria-live] *,[style*='visibility: hidden']",
- });
-
-
-
- const optionElement = matchingElements[matchingElements.length - 1];
- await user.click(optionElement, {skipHover: true});
- }
- };
- interface CreateConfig extends Config, UserEventOptions {
-
- createOptionText?: string | RegExp;
-
- waitForElement?: boolean;
- }
- const create = async (
- input: HTMLElement,
- option: string,
- {waitForElement = true, user = userEvent, ...config}: CreateConfig = {}
- ) => {
- const createOptionText = config.createOptionText || /^Create "/;
- await openMenu(input, {user});
- await type(input, option, {user});
- await select(input, createOptionText, {...config, user});
- if (waitForElement) {
- await findByText(getReactSelectContainerFromInput(input), option);
- }
- };
- const clearFirst = async (
- input: HTMLElement,
- {user = userEvent}: UserEventOptions = {}
- ) => {
- const container = getReactSelectContainerFromInput(input);
-
- const clearButton = container.querySelector('svg[aria-hidden="true"]')!;
- await clear(clearButton, {user});
- };
- const clearAll = async (
- input: HTMLElement,
- {user = userEvent}: UserEventOptions = {}
- ) => {
- const container = getReactSelectContainerFromInput(input);
-
-
- const elements = container.querySelectorAll('svg[aria-hidden="true"]');
- const clearAllButton = elements[elements.length - 2];
- await clear(clearAllButton, {user});
- };
- const selectEvent = {select, create, clearFirst, clearAll, openMenu};
- export default selectEvent;
|