@lokalise/react-select-event
v1.0.0
Published
Simulate react-select events for react-testing-library
Downloads
12
Readme
Install
npm install --save-dev react-select-event
Import react-select-event
in your unit tests:
import selectEvent from "react-select-event";
// or
const selectEvent = require("react-select-event");
Supported versions of react-select
This library is tested against all versions of react-select
starting from 4.0.0
.
API
Every helper exported by react-select-event
takes a handle on the react-select
input field as its first argument. For instance, this can be: getByLabelText("Your label name")
.
select(input: HTMLElement, optionOrOptions: Matcher | Array<Matcher>, config?: object): Promise<void>
The optionOrOptions
parameter can be any valid dom-testing-library TextMatch object (eg. string, regex, function, number).
Select one or more values in a react-select dropdown.
const { getByRole, getByLabelText } = render(
<form role="form">
<label htmlFor="food">Food</label>
<Select options={OPTIONS} name="food" inputId="food" isMulti />
</form>
);
expect(getByRole("form")).toHaveFormValues({ food: "" });
await selectEvent.select(getByLabelText("Food"), ["Strawberry", "Mango"]);
expect(getByRole("form")).toHaveFormValues({ food: ["strawberry", "mango"] });
await selectEvent.select(getByLabelText("Food"), "Chocolate");
expect(getByRole("form")).toHaveFormValues({
food: ["strawberry", "mango", "chocolate"],
});
This also works for async selects:
const { getByRole, getByLabelText } = render(
<form role="form">
<label htmlFor="food">Food</label>
<Async
options={[]}
loadOptions={fetchTheOptions}
name="food"
inputId="food"
isMulti
/>
</form>
);
expect(getByRole("form")).toHaveFormValues({ food: "" });
// start typing to trigger the `loadOptions`
userEvent.type(getByLabelText("Food"), "Choc");
await selectEvent.select(getByLabelText("Food"), "Chocolate");
expect(getByRole("form")).toHaveFormValues({
food: ["chocolate"],
});
select
also accepts an optional config
parameter.
config.container
can be used to specify a custom container to use when the react-select
dropdown is rendered
in a portal using menuPortalTarget
:
const { getByRole, getByLabelText } = render(
<form role="form">
<label htmlFor="food">Food</label>
<Select
options={OPTIONS}
name="food"
inputId="food"
isMulti
menuPortalTarget={document.body}
/>
</form>
);
await selectEvent.select(getByLabelText("Food"), ["Strawberry", "Mango"], {
container: document.body,
});
expect(getByRole("form")).toHaveFormValues({ food: ["strawberry", "mango"] });
The container can also be passed in as a function if it needs to be lazily evaluated:
const { getByRole, getByLabelText } = render(
<form role="form">
<label htmlFor="food">Food</label>
<Select
options={OPTIONS}
name="food"
inputId="food"
isMulti
menuPortalTarget={document.body}
/>
</form>
);
await selectEvent.select(getByLabelText("Food"), ["Strawberry", "Mango"], {
container: () => document.body.querySelector("[class$=-menu]"),
});
expect(getByRole("form")).toHaveFormValues({ food: ["strawberry", "mango"] });
create(input: HTMLElement, option: string, config?: object): Promise<void> }
Creates and selects a new item. Only applicable to react-select
Creatable
elements.
const { getByRole, getByLabelText } = render(
<form role="form">
<label htmlFor="food">Food</label>
<Creatable options={OPTIONS} name="food" inputId="food" />
</form>
);
expect(getByRole("form")).toHaveFormValues({ food: "" });
await selectEvent.create(getByLabelText("Food"), "papaya");
expect(getByRole("form")).toHaveFormValues({ food: "papaya" });
create
take an optional config
parameter:
config.createOptionText
can be used when creating elements with a custom label text, using theformatCreateLabel
prop.config.container
can be used when thereact-select
dropdown is rendered in a portal usingmenuPortalTarget
.config.waitForElement
Whethercreate
should wait for new option to be populated in the select container. Defaults totrue
.
clearFirst(input: HTMLElement): Promise<void>
Clears the first value in the dropdown.
const { getByRole, getByLabelText } = render(
<form role="form">
<label htmlFor="food">Food</label>
<Creatable
defaultValue={OPTIONS[0]}
options={OPTIONS}
name="food"
inputId="food"
isMulti
/>
</form>
);
expect(getByRole("form")).toHaveFormValues({ food: "chocolate" });
await selectEvent.clearFirst(getByLabelText("Food"));
expect(getByRole("form")).toHaveFormValues({ food: "" });
clearAll(input: HTMLElement): Promise<void>
Clears all values in the dropdown.
const { getByRole, getByLabelText } = render(
<form role="form">
<label htmlFor="food">Food</label>
<Creatable
defaultValue={[OPTIONS[0], OPTIONS[1], OPTIONS[2]]}
options={OPTIONS}
name="food"
inputId="food"
isMulti
/>
</form>
);
expect(getByRole("form")).toHaveFormValues({
food: ["chocolate", "vanilla", "strawberry"],
});
await selectEvent.clearAll(getByLabelText("Food"));
expect(getByRole("form")).toHaveFormValues({ food: "" });
openMenu(input: HTMLElement): void
Opens the select dropdown menu by focusing the input and simulating a down arrow keypress.
const { getByLabelText, queryByText } = render(
<form>
<label htmlFor="food">Food</label>
<Select options={[{ label: "Pizza", value: 1 }]} inputId="food" />
</form>
);
expect(queryByText("Pizza")).toBeNull();
selectEvent.openMenu(getByLabelText("Food"));
expect(getByText("Pizza")).toBeInTheDocument();
Credits
All the credit goes to Daniel and his StackOverflow answer: https://stackoverflow.com/a/56085734.