I'm writing test for a component with ref. I'd like to mock the ref element and change some properties but have no idea how to. Any suggestions?
// MyComp.jsx
class MyComp extends React.Component {
constructor(props) {
super(props);
this.getRef = this.getRef.bind(this);
}
componentDidMount() {
this.setState({elmHeight: this.elm.offsetHeight});
}
getRef(elm) {
this.elm = elm;
}
render() {
return <div>
<span ref={getRef}>
Stuff inside
</span>
</div>
}
}
// MyComp.test.jsx
const comp = mount(<MyComp />);
// Since it is not in browser, offsetHeight is 0
// mock ref offsetHeight to be 100 here... How to?
expect(comp.state('elmHeight')).toEqual(100);
To mock React useRef or a function inside a functional component with enzyme and Jest, we can mock the react module by mocking the useRef hook and getting the rest of the mocked module from the real module. import React, { useRef } from "react"; import { shallow } from "enzyme"; import Child2 from "./"; jest.
Regular function or class components don't receive the ref argument, and ref is not available in props either. Ref forwarding is not limited to DOM components. You can forward refs to class component instances, too.
Many people choose to use Jest and Enzyme together to test their React web applications. They use Jest as a test runner and assertion library, then use Enzyme to build the tests for their UI. This results in slimmer, cleaner testing code that's also easier to debug when a test breaks.
So here's the solution, according to discussion in https://github.com/airbnb/enzyme/issues/1937
It is possible to monkey-patch the class with a non-arrow function, where "this" keyword is passed to the right scope.
function mockGetRef(ref:any) {
this.contentRef = {offsetHeight: 100}
}
jest.spyOn(MyComp.prototype, 'getRef').mockImplementationOnce(mockGetRef);
const comp = mount(<MyComp />);
expect(comp.state('contentHeight')).toEqual(100);
You can mock the ref by using Object.defineProperty
. For example:
Object.defineProperty(Element.prototype, 'offsetHeight', {
value: 100,
writable: true,
configurable: true
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With