how to handle react ref methods which contain dom api methods in enzyme tests

Viewed 1125

I have a react component which calls a prop method onSizeChange when onRef is called.

onRef contains a dom api query.

I want to assert onSizeChange is called. This fails in enzyme's mount because getBBox() doesn't exist in jsdom. error: getBBox is not a function

How can I get the test to run so I can assert onSizeChange is called?

Broader question: How do you deal with dom api queries inside ref functions which aren't supported when tests are run like inside jsdom, can they be mocked somehow?

/* Abbreviated component class code */

onRef(textNode){
    if(!textNode){
        return;
    }
    const { onSizeChange } = this.props;
    const { width, height } = textNode.getBBox();
    onSizeChange({ width, height });

}

render(){
    return (
        <svg>
            <text 
                ref={textNode => this.onRef(textNode)}
                x="50%"
                y="50%" 
                alignmentBaseline="middle"
                textAnchor="middle"
                stroke="none">
                some text
             </text>
        </svg>
    );
}

Enzyme test:

it('should call onSizeChange handler on render', () => {
    const props = {
        onSizeChange: () => {}
    };
    const spy =  sinon.spy(props, 'onSizeChange');
    const wrapper = mount(<NodeLabel {...props} />);
    expect(spy.called).to.equal(true);
    spy.restore();
});
1 Answers

I failed to solve this myself until I found the approach used here:

The nice thing about it is that there's no need to fiddle around with jsdom itself, you just overwrite the prototype of getBBox using beforeEach/afterEach:

const originalGetBBox = SVGElement.prototype.getBBox;
beforeEach(() => SVGElement.prototype.getBBox = () => {
  return {<insert your mock data for bbox here>};
});
afterEach(() => (SVGElement.prototype.getBBox = originalGetBBox));
Related