Выбор материала пользовательского интерфейса onChange не работает в библиотеке тестирования реакции

<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>

Это выбранный элемент, который я пытаюсь протестировать. Здесь permissionArr - это список отображаемых строк. И handleChange меняет permissionsArr. Но когда я пытаюсь это проверить:

const labelPermissions = queryByTestId("change-form")
fireEvent.change(labelPermissions, { target: { value:  ["string", "string"] }} );

Он не вызывает событие onChange. Это может быть потому, что значение не должно быть массивом, - это мое лучшее предположение. Я застрял на этом какое-то время, любая помощь будет очень признательна.


person Utkarsh Mishra    schedule 08.07.2020    source источник


Ответы (1)


Select действительно не имеет change события. Функция, предоставленная для onChange, вызывается, когда изменения происходят из-за других событий - обычно при нажатии MenuItem. Я бы порекомендовал вам структурировать свой тест так, чтобы использовать те же взаимодействия, что и пользователь.

Ниже приведен пример теста с использованием множественного выбора из документации:

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"
  );
});

и вот код, который он тестирует:

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>
  );
}

 Редактировать Выбрать изменение тест

person Ryan Cogswell    schedule 09.07.2020
comment
Да, это имеет больше смысла, но по какой-то причине я не могу найти текст MenuItem, отображаемый с помощью getByText. - person Utkarsh Mishra; 09.07.2020
comment
@UtkarshMishra Я рекомендую создать песочницу, демонстрирующую ваш сценарий. Я рекомендую начать с моего и изменить его, чтобы он больше походил на ваш сценарий, пока не воспроизведу вашу проблему. Затем включите эту песочницу в свой вопрос (если вы еще не нашли решение во время этого процесса). - person Ryan Cogswell; 09.07.2020