Reputation: 842
I'm trying to make a test for the material ui autocomplete component, I'm using the same component in this example, I tried following the problem from this question but I didn't find how to solve it.
the code of my test is the following, the problem is that I get only the city I type in the input and not the first result. I test it a little and I think it doesn't select the available options with the ArrowDown
and Enter
.
// Autocomplete is the Autocomplete component from material ui
test("Autocomplete Test", async () => {
render(<Autocomplete />);
const autocomplete = screen.getByTestId("autocomplete");
const input = within(autocomplete).getByRole("textbox");
autocomplete.click();
autocomplete.focus();
fireEvent.change(input, { target: { value: "london" } });
fireEvent.keyDown(autocomplete, { key: "ArrowDown" });
fireEvent.keyDown(autocomplete, { key: "Enter" });
const inputt = within(autocomplete).getByRole("textbox");
console.log(inputt.value);
expect(inputt.value).toEqual("London");
});
Upvotes: 1
Views: 5831
Reputation: 136
If i take the first component from your link to material-ui, the test below will actually succeed.
Component:
<Autocomplete
data-testid="autocomplete"
id="combo-box-demo"
options={top100Films}
getOptionLabel={(option) => option.title}
style={{ width: 300 }}
renderInput={(params) => <TextField {...params} label="Combo box" variant="outlined" />}
/>
and test:
describe("Foo", () => {
it("can select the second item and proceed", async () => {
const { debug, getAllByRole } = render(<Foo />);
const autocomplete = screen.getByTestId("autocomplete");
const input = within(autocomplete).getByRole("textbox");
autocomplete.click();
autocomplete.focus();
fireEvent.change(input, { target: { value: "lo" } });
// to be sure, or do `findAllByRole` which is also async
await act(async () => {
await new Promise(resolve => setTimeout(resolve, 0));
});
fireEvent.click(getAllByRole("option")[1]);
expect(input.value).toEqual("The Lord of the Rings: The Fellowship of the Ring");
})
});
This will create a successful test. With multi-select it will actually create other html so hence my advise about debugging below.
Also notice i take debug from the render, so at any point i can see what the html is (calling debug()). This can give you very good pointers in what is painted on the moment you are trying to achieve something! Personally i run tests in watch mode and can set breakpoints from the editor which helps me much more.
Edit: when i try and rename fireEvent.click(getAllByRole("option")[1]);
into part below it works as well:
fireEvent.keyDown(input, { key: "ArrowDown" });
fireEvent.keyDown(input, { key: "Enter" });
Upvotes: 4