I recently worked on an unusual and somewhat anachronistic requirement, presenting a marketing/sales form using an iframe inside a React.js app, with a seamless UX to boot. The integration uses postMessage for cross-domain page communication, which proved an interesting challenge for unit-testing.
The stripped down example below demonstrates the use of a React function component and a callback ref. The component sends a message to the page within the iframe once it has loaded.
function IframeComponent({ domain, path }) {
let iframeRef;
const post = (msg) => iframeRef.contentWindow.postMessage(JSON.stringify(msg), domain);
const onIframeLoad = () => post({foo:'bar'});
const getRef = (el) => iframeRef = el;
return (
<iframe
ref={getRef}
src={domain + path}
onLoad={onIframeLoad}
/>
);
}
I wanted to test the load behaviour without having to load the contents of the iframe, my solution (after a lot of digging around on the internet) was to use a test double for the iframe by gaining access to, and invoking the ref callback.
The test below is written with Mocha, Chai, Enzyme and Sinon
describe('IframeComponent', () => {
it('should invoke load message correctly', () => {
const domain = 'https://my.domain.com';
const wrapper = shallow(<IframeComponent domain={domain} path="/page"/>);
const iframe = wrapper.find('iframe');
const spy = mockIframePostMessage(iframe);
const props = iframe.props();
expect(props.src).to.be.equal(domain + path);
expect(spy.called).to.be.equal(false);
iframe.simulate('load');
expect(spy.called).to.be.equal(true);
expect(spy.args[0][0]).to.be.equal(JSON.stringify({ foo: 'bar' }));
expect(spy.args[0][1]).to.be.equal(domain);
});
});
And below shows how, using Enzyme we can find the iframe React node and invoke its ref callback, providing the simple test double.
function mockIframePostMessage(iframe) {
const postMessage = sinon.spy();
const iframeMock = {
contentWindow: {
postMessage,
},
};
iframe.getNode().ref(iframeMock);
return postMessage;
}
Note: I believe
getNode
has now been replaced bygetElement
in the latest version of Enzyme.
This approach provides a nice, simple way to write fast tests for iframes in React 🚀
Top comments (0)