react-testing-library: on change for Material UI Select component not triggered
- react-testing-libraryversion: 4.1.3
- reactversion: 16.4.1
- nodeversion: 11.10.1
- npm(or- yarn) version: 6.7.0
Relevant code or config:
    const select = await waitForElement(() =>
      getByTestId("select-testid")
    );
    select.value = "testValue";
    fireEvent.change(select);
   <Select
       className={classes.select}
       onChange={this.handleSelectChange}
       value={selectedValue}
       inputProps={{
         id: "select-id",
         "data-testid": "select-id"
       }}
   >
What you did:
I am trying to fire the onChange method of the Material UI Select.
What happened:
onChange won’t fire. Also tried with
select.dispatchEvent(new Event('change', { bubbles: true }));
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 17
- Comments: 43 (11 by maintainers)
Commits related to this issue
- Add example of firing select event As a new user of this library I had a difficult time determining how to test outcomes of a drop-down selection. There is an example if you use the react-select lib... — committed to rkennel/testing-library-docs by rkennel 4 years ago
- fix(type): ensure the selectionStart/End are consistent with browsers (#322) Closes: #321 Closes: #318 Closes: #316 — committed to lucbpz/react-testing-library by kentcdodds 4 years ago
- Add selectMaterialUiSelectOption to Jest Helpers Add the `selectMaterialUiSelectOption` method to Jest Helpers because the select Material UI uses is react-select under the hood. As a result, it is n... — committed to SpiritBreaker226/pokemon-rewind by SpiritBreaker226 4 years ago
- Add selectMaterialUiSelectOption to Jest Helpers Add the `selectMaterialUiSelectOption` method to Jest Helpers because the select Material UI uses is react-select under the hood. As a result, it is n... — committed to SpiritBreaker226/pokemon-rewind by SpiritBreaker226 4 years ago
I had the problem that the text I want to select is elsewhere on the page, so I needed to target the ‘dropdown’ directly. Also I wanted it as a separate function, ideally not using the
getByTextetc. returned byrender().Edit: added async, since material-ui can take a tic to remove the listbox.
Thx to have share all of this information it help a lot. Since the last release on Material ui, the previous sibling element of the select input must be trigger by the “mouseDown” method from the fireEvent.
onClickdo not trigger anymore the option menu.The same issue occurs for Input components as well.
fireEvent.change(input, { target: { value: "Valid input value" } });does nothing.This by itself did not work. That being said, both of the following do work:
or
I personally prefer the second option.
Something to note for future readers: If you are using a Material UI select, none of the above will work. You’ll have to use the native version of the Select element. For future reference: https://stackoverflow.com/questions/55184037/react-testing-library-on-change-for-material-ui-select-component
Similar to what is in codesandbox worked for me:
Using Material UI 5.10.3:
Try this: https://codesandbox.io/embed/94pm1qprmo I have moved the
data-testidto theinputProps-prop of theSelectofControlledOpenSelect-component also I have written a unit test for you which clicks on Thirty and ensures aonChange-props got triggered (I added the onChange to your comp).Not sure, why it doesn’t work in the browser but when you download it and test locally the unit test is successful. I hope it helps!
It would probably be good to have a few examples for testing MaterialUI components because we regularly get reports about difficulties with that library and I don’t use it so I don’t know why it’s so uniquely difficult.
Thank you very much, I have done my problem with your solution
Hey @weyert , I have updated the codesandbox example and have wrote unit test for it. I would like to thank you for taking a look at this issue.
Here is the link for updated codesandbox: https://codesandbox.io/s/q94q9z1849
Please feel free to edit it or suggest improvements on it.
Thanks for sharing the snippet @davidgilbertson! I couldn’t make it work with my code, but I modified it slightly and the following works for me:
If anyone else comes across this awesome example here, but is using a multi-select, one note of caution – multi-selects stay open when selecting options, so the
waitForElementToBeRemovedwill fail as it doesn’t close the select.You could easily modify this to accept multiple options (if you are looking to test clicking one to many items), and then at the end prior to the
waitForElementToBeRemoved, you can simulate an “escape” keypress on the listbox to close it:userEvent.type(listbox, "{esc}");This will then properly await on the close of the listbox before proceeding.
For anyone coming across this issue like I did and is having trouble removing the list box from jsdom, Material UI uses ReactTransitionGroup under the hood for fading out the the options. You can disable the ReactTransitionGroup transitions by adding:
which solved the issue for me and removed the listbox immediately on clicking an item.
Thank you @davidgilbertson, @bjunix and @zzgab! Had to change it to use ‘fireEvent’ instead of ‘userEvent’ to work for me (using material-ui/core 4.11.3):
We have fixed this issue in https://github.com/mui-org/material-ui/blob/b5a27b18db60138d7b65a02d04f8162d074f32be/packages/material-ui/src/Select/Select.test.js#L1059-L1078
@sateesh-p, I had this issue as well. No fix, but I was able to just validate an
onChangefunction callback.@davidgilbertson, seriously thank you. This was a huge pain in the butt.
It does have a role implicitly. However,
listboxis caused by a bug that is caused by an outdated dependency. Should be fixed soon.The solution shared by @weyert looks great to me: https://codesandbox.io/s/94pm1qprmo, thanks! The non-native variation of the select component relies on click/keyboard interactions. You can’t fire a DOM change event. The input element present is only here to support HTML POST forms.
@TidyIQ for the Input component, let’s move to #359.
Thank you @weyert