Reputation: 31
<Select
inputProps={{ "data-testid": "change-form" }}
multiple
value={permissionsArr}
onChange={handleChange}
input={<Input />}
renderValue={selected => (
<ChipsContainer >
{ selected.map(value => (
<Chip key={value} label={value} />
))}
</ChipsContainer >
)}
>
{perms.map(name => (
<MenuItem key={name} value={name}>{prettyName(name)}</MenuItem>
))}
</Select>
This is the select element that I am trying to test, Here permissionArr is a list of strings that are displayed. And handleChange is changing the permissionsArr. But when I try to test this:
const labelPermissions = queryByTestId("change-form")
fireEvent.change(labelPermissions, { target: { value: ["string", "string"] }} );
It doesn't call the onChange event. It might be because value shouldn't be an array is my best guess. I've been stuck on this for a while, any help would be much appreciated.
Upvotes: 3
Views: 8112
Reputation: 81026
Select
doesn't really have a change
event. The function provided to onChange
is called when changes occur due to other events -- generally clicking a MenuItem
. I would recommend that you structure your test to use the same interactions as would be done by a user.
Below is an example test using a multiple Select from the documentation:
demo.test.js
import React from "react";
import {
render,
fireEvent,
waitForElementToBeRemoved,
screen
} from "@testing-library/react";
import Demo from "./demo";
import "@testing-library/jest-dom/extend-expect";
test("display and change select", async () => {
render(<Demo />);
// Open the Select
fireEvent.mouseDown(screen.getByLabelText("Name"));
// Click the entries you want to select
fireEvent.click(screen.getByText("Van Henry"));
fireEvent.click(screen.getByText("April Tucker"));
// Close the select using Escape or Tab or clicking away
fireEvent.keyDown(document.activeElement, {
key: "Escape",
code: "Escape"
});
// Wait for Menu to close
await waitForElementToBeRemoved(screen.getByText("Oliver Hansen"));
// Verify selections
expect(screen.getByLabelText("Name")).toHaveTextContent(
"Van Henry, April Tucker"
);
});
and here is the code it is testing:
demo.js
import React from "react";
import { makeStyles, useTheme } from "@material-ui/core/styles";
import Input from "@material-ui/core/Input";
import InputLabel from "@material-ui/core/InputLabel";
import MenuItem from "@material-ui/core/MenuItem";
import FormControl from "@material-ui/core/FormControl";
import Select from "@material-ui/core/Select";
const useStyles = makeStyles(theme => ({
formControl: {
margin: theme.spacing(1),
minWidth: 120,
maxWidth: 300
},
chips: {
display: "flex",
flexWrap: "wrap"
},
chip: {
margin: 2
},
noLabel: {
marginTop: theme.spacing(3)
}
}));
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
PaperProps: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250
}
}
};
const names = [
"Oliver Hansen",
"Van Henry",
"April Tucker",
"Ralph Hubbard",
"Omar Alexander",
"Carlos Abbott",
"Miriam Wagner",
"Bradley Wilkerson",
"Virginia Andrews",
"Kelly Snyder"
];
function getStyles(name, personName, theme) {
return {
fontWeight:
personName.indexOf(name) === -1
? theme.typography.fontWeightRegular
: theme.typography.fontWeightMedium
};
}
export default function MultipleSelect() {
const classes = useStyles();
const theme = useTheme();
const [personName, setPersonName] = React.useState([]);
const handleChange = event => {
setPersonName(event.target.value);
};
return (
<div>
<FormControl className={classes.formControl}>
<InputLabel id="demo-multiple-name-label">Name</InputLabel>
<Select
labelId="demo-multiple-name-label"
id="demo-multiple-name"
multiple
value={personName}
onChange={handleChange}
input={<Input />}
MenuProps={MenuProps}
>
{names.map(name => (
<MenuItem
key={name}
value={name}
style={getStyles(name, personName, theme)}
>
{name}
</MenuItem>
))}
</Select>
</FormControl>
</div>
);
}
Upvotes: 2