我正在编写一个react组件,该组件将在iframe中加载URL,然后当iframe的onLoad事件触发时,它将调用contentWindow.postMessage()。我想使用Jest,Enzyme和JSDOM证明此功能。
我的组件包装了react-iframe,看起来非常简单:
export class FilteredIframe extends React.PureComponent<FilteredIframeProps> {
onload = (e:Window) => {
console.log("ONLOAD CALLED");
if (this.props.filters) {
e.postMessage(this.props.filters, this.props.url);
}
}
render() {
return (<Iframe url={this.props.url}
display="initial"
position="static"
onLoad={this.onload}
/>);
}
}
我正在尝试弄清楚如何使用酶/ jsdom对此进行测试,但是我失败了:
test("Posts message once the frame has loaded", async () => {
const payLoad = { data: "data" };
const result = mount(<FilteredIframe url="https:///www.bing.com" filters={payLoad}/>);
})
以开玩笑的方式运行此程序时,我在控制台中从未看到“ ONLOAD CALLED”消息。我需要为jsdom或酶做某种特殊的事情以使其实际上调用onLoad吗?
答案 0 :(得分:0)
强制对已安装的包装程序进行更新对我而言有效。
<iframe onLoad={this.iframeLoaded}></iframe>
并像这样测试...
const mountWrapper = mount(<App />);
let container;
describe('iframe', () => {
beforeEach(() => {
container = mountWrapper.find('iframe');
});
it('calls iframeLoaded() when loaded', () => {
const spy = jest.spyOn(mountWrapper.instance(), 'iframeLoaded');
mountWrapper.instance().forceUpdate();
container.simulate('load');
expect(spy).toHaveBeenCalledTimes(1);
});
});
答案 1 :(得分:0)
您需要将已挂载的iframe附加到文档上,挂载有attachTo选项可以做到这一点。
答案 2 :(得分:0)
OPs的答案满足了我的需要。如果您不需要加载iframe,而只需加载触发器(例如,如果iframe src是pdf),则触发onLoad并更新。
act(() => {
result.find('iframe').props().onLoad();
});
result.update();
答案 3 :(得分:-1)
我再次进行了研究,发现可以直接在组件内部调用iframe的onLoad()。我现在有这样的东西:
test("Posts message once the frame has loaded", async () => {
const payLoad = { data: "data" };
const result = mount(<FilteredIframe url="https:///www.bing.com" filters={payLoad} />);
const iframe = result.find("iframe");
//mock contentWindow so we can examine messages
let receivedFilters = {};
const mockIFrameContents = {
contentWindow : {
postMessage: function (filters, url) {
receivedFilters = filters;
}
}
}
result.instance().setIframeRef(mockIFrameContents);
//Signal the contents have loaded
iframe.props().onLoad();
expect(receivedFilters === payLoad).toBeTruthy();
});
我还对组件进行了一些修改,以将ref用于iframe本身,并使用ref的contentWindow而不是事件目标。但是,真正的答案只是模拟iframe contentWindow并直接调用它的onLoad(),而不是尝试使其实际加载某些东西。