Testing a material ui slider with @testing-library/react

偶尔善良 提交于 2020-06-27 10:00:07

问题


Hi there I'm trying to test a Slider component created with Material-UI, but I cannot get my tests to penter link description hereass. I would like test the the value changes using the fireEvent with @testing-library/react. I've been following this post to properly query the DOM, I cannot get the correct DOM nodes.

Thanks in advance.

<Slider /> component

// @format
// @flow

import * as React from "react";
import styled from "styled-components";
import { Slider as MaterialUISlider } from "@material-ui/core";
import { withStyles, makeStyles } from "@material-ui/core/styles";
import { priceRange } from "../../../domain/Search/PriceRange/priceRange";

const Wrapper = styled.div`
  width: 93%;
  display: inline-block;
  margin-left: 0.5em;
  margin-right: 0.5em;
  margin-bottom: 0.5em;
`;

// ommited code pertaining props and styles for simplicity

function Slider(props: SliderProps) {
  const initialState = [1, 100];
  const [value, setValue] = React.useState(initialState);

  function onHandleChangeCommitted(e, latestValue) {
    e.preventDefault();
    const { onUpdate } = props;
    const newPriceRange = priceRange(latestValue);
    onUpdate(newPriceRange);
  }

  function onHandleChange(e, newValue) {
    e.preventDefault();
    setValue(newValue);
  }

  return (
    <Wrapper
      aria-label="range-slider"
    >
      <SliderWithStyles
        aria-labelledby="range-slider"
        defaultValue={initialState}
        // getAriaLabel={index =>
        //   index === 0 ? "Minimum Price" : "Maximum Price"
        // }
        getAriaValueText={valueText}
        onChange={onHandleChange}
        onChangeCommitted={onHandleChangeCommitted}
        valueLabelDisplay="auto"
        value={value}
      />
    </Wrapper>
  );
}

export default Slider;

Slider.test.js

// @flow

import React from "react";
import { cleanup,
  render,
  getAllByAltText,
  fireEvent,
  waitForElement } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";

import Slider from "../Slider";


afterEach(cleanup);

describe("<Slider /> specs", () => {

  // [NOTE]: Works, but maybe a better way to do it ?
  xdescribe("<Slider /> component aria-label", () => {

    it("renders without crashing", () => {
      const { container } = render(<Slider />);
      expect(container.firstChild).toBeInTheDocument(); 
    });
  });

  // [ASK]: How to test the event handlers with fireEvent.
  describe("<Slider /> props", () => {

    it("display a initial min value of '1'", () => {
      const renderResult = render(<Slider />);
      // TODO
    });

    it("display a initial max value of '100'", () => {
      const renderResult = render(<Slider />);
      // TODO
    });

    xit("display to values via the onHandleChangeCommitted event when dragging stop", () => {
      const renderResult = render(<Slider />);
      console.log(renderResult)
      // fireEvent.change(renderResult.getByText("1"))
      // expect(onChange).toHaveBeenCalled(0);
    });

    // [NOTE]: Does not work, returns undefined
    xit("display to values via the onHandleChange event when dragging stop", () => {
      const renderResult = render(<Slider />);

      console.log(renderResult.container);

      const spanNodeWithAriaAttribute = renderResult.container.firstChild.getElementsByTagName("span")[0].getAttribute('aria-label')
      expect(spanNodeWithAriaAttribute).toBe(/range-slider/)
    });
  });

  // [ASK]: Works, but a snapshot is an overkill a better way of doing this ?
  xdescribe("<Slider /> snapshot", () => {

    it("renders without crashing", () => {
      const { container } = render(<Slider />);
      expect(container.firstChild).toMatchSnapshot();
    });
  });
});

回答1:


I would recommend not to write tests for a custom component and believe that this component works for all our cases.

Read through this article for more details. In that they have mentioned how to write unit tests for a component that wraps react-select.

I followed the similar approach and wrote a mock for my third-party slider component.

in setupTests.js:

jest.mock('@material-ui/core/Slider', () => (props) => {
  const { id, name, min, max, onChange, testid } = props;
  return (
    <input
      data-testid={testid}
      type="range"
      id={id}
      name={name}
      min={min}
      max={max}
      onChange={(event) => onChange(event.target.value)}
    />
  );
});

With this mock, you can simply fire a change event in your tests like this:

fireEvent.change(getByTestId(`slider`), 25);

Make sure to pass proper testid as a prop to your SliderWithStyles component




回答2:


After battling this for hours I was able to solve my case related to testing MUI slider

It really depends on how you need to test yours, in my case I have to check if a label text content has changed after clicking a mark using marks slider props.

The problems

1) The slider component computes the return value base on elements getBoundingClientRect and MouseEvent

2) How to query the slider and fire the event.

3) JSDOM limitation on reading element actual height and width which causes the problem no.1

The solution

1) mock getBoundingClientRect should also fix the problem no.3

2) add test id to slider and use use fireEvent.mouseDown(contaner, {....})

const sliderLabel = screen.getByText("Default text that the user should see")

// add data-testid to slider
const sliderInput = screen.getByTestId("slider")

// mock the getBoundingClientRect
    sliderInput.getBoundingClientRect = jest.fn(() => {
      return {
        bottom: 286.22918701171875,
        height: 28,
        left: 19.572917938232422,
        right: 583.0937919616699,
        top: 258.22918701171875,
        width: 563.5208740234375,
        x: 19.572917938232422,
        y: 258.22918701171875,
      }
    })

    expect(sliderInput).toBeInTheDocument()

    expect(sliderLabel).toHaveTextContent("Default text that the user should see")
    await fireEvent.mouseDown(sliderInput, { clientX: 162, clientY: 302 })
    expect(sliderLabel).toHaveTextContent(
      "New text that the user should see"
    )



来源:https://stackoverflow.com/questions/58856094/testing-a-material-ui-slider-with-testing-library-react

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!