React Test Renderer only renders the components as a JS object rather than to a browser environment. Hence, anything that uses dom based refs will have this issue. Related jest issue: https://github.com/facebook/jest/issues/5462.
There is a section in the React Docs for a way to workaround it: https://reactjs.org/docs/test-renderer.html#ideas
EDIT:
Here's a working test. It likely makes a lot of the functionality of the slider not work, since we are setting the internal refs to null. But it does run. The "Next" branch on MUI doesn't have the findDOMNode
function there, so that might be easier to work with.
I wasn't able to get these to work on CodeSandbox because jest
was undefined, and I couldn't find how to fix that.
import React from 'react';
import { Slider } from '@material-ui/core';
import renderer from 'react-test-renderer';
jest.mock('react-dom', () => ({
// the useIsFocusVisible function in Slider.js (MUI component) uses findDOMNOde
// Luckily it checks if there's nulls, so we can return a null
// https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/utils/useIsFocusVisible.js#L136
findDOMNode: () => null,
}));
it('should render', () => {
renderer.create(<Slider />);
});
If you want to try and mock the full functionality (sort of), you can use this implementation of the findDOMNode mock, which will return the values that are needed for the useIsFocusVisible
to run successfully including adding the event listener:
import React from 'react';
import { Slider } from '@material-ui/core';
import renderer from 'react-test-renderer';
jest.mock('react-dom', () => ({
// the useIsFocusVisible function in Slider.js (MUI component) uses findDOMNOde
// https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/utils/useIsFocusVisible.js#L136
findDOMNode: (instance) => {
return { ownerDocument: instance };
},
}));
it('should render', () => {
let eventListenerFn = jest.fn();
renderer.create(<Slider />, {
createNodeMock: (element) => {
if (element.type === 'span') {
return {
addEventListener: eventListenerFn,
};
}
},
});
});
In order to figure out how to get these tests to succesfully run, I had to step through the error stacks/MUI source code to find out what's going wrong and what values were needed to be mocked in order to not throw errors.
Original, showing how much better @testing-library is for this:
However, may I suggest using @testing-library? It's nice to work with and uses jsdom to render the components so it'll work with this component.
I went ahead and made a couple of random tests for the Slider
using the testing library to show that it works with Slider
and throws no errors:
import React from "react";
import { Slider } from "@material-ui/core";
import { render } from "@testing-library/react";
it("should render", () => {
render(<Slider />);
});
it("should render an input", () => {
const component = render(<Slider />);
const input = component.baseElement.querySelector("input");
expect(input).toBeDefined();
});
it("Should have the correct value", () => {
const component = render(<Slider value={50} />);
const input = component.baseElement.querySelector("input");
expect(input.value).toBe("50");
});
CodeSandbox