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)