Skip to content

Commit 3121602

Browse files
committed
Add tests
1 parent d5070c5 commit 3121602

File tree

2 files changed

+126
-13
lines changed

2 files changed

+126
-13
lines changed

packages/perseus-editor/src/__tests__/iframe-content-renderer.test.tsx

+118-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import {render} from "@testing-library/react";
1+
/* eslint-disable testing-library/no-node-access */
2+
import {render, waitFor} from "@testing-library/react";
23
import * as React from "react";
34

45
import IframeContentRenderer from "../iframe-content-renderer";
6+
import {sendMessageToIframeParent} from "../iframe-utils";
57

68
expect.extend({
79
toHaveSearchParam(
@@ -38,7 +40,23 @@ declare global {
3840
}
3941
}
4042
}
43+
44+
function getIframeID(iframe: HTMLIFrameElement | null): string {
45+
const url = iframe?.src;
46+
if (!url) {
47+
return "";
48+
}
49+
50+
const frameID = new URL(url).searchParams.get("frame-id");
51+
expect(frameID).not.toBeNull();
52+
return frameID!;
53+
}
54+
4155
describe("IframeContentRenderer", () => {
56+
beforeEach(() => {
57+
jest.useRealTimers();
58+
});
59+
4260
it("should render", () => {
4361
// Arrange
4462

@@ -83,12 +101,9 @@ describe("IframeContentRenderer", () => {
83101
// same value twice, our set will be smaller than the count of iframes
84102
// we have).
85103
const idSet = new Set<string | null>();
86-
[...iframes]
87-
.map((frame) => new URL(frame.src).searchParams.get("frame-id"))
88-
.forEach((id) => {
89-
expect(id).not.toBeNull();
90-
idSet.add(id);
91-
});
104+
[...iframes].map(getIframeID).forEach((id) => {
105+
idSet.add(id);
106+
});
92107

93108
expect(idSet.size).toBe(3);
94109
});
@@ -145,4 +160,100 @@ describe("IframeContentRenderer", () => {
145160
const frame = document.querySelector("iframe");
146161
expect(new URL(frame!.src).searchParams.get("lint-gutter")).toBeNull();
147162
});
163+
164+
it("should send requested data", async () => {
165+
// Arrange
166+
const iframeRef = React.createRef<IframeContentRenderer>();
167+
const {container} = render(
168+
<IframeContentRenderer
169+
ref={iframeRef}
170+
seamless={false}
171+
url="http://localhost/perseus/frame"
172+
/>,
173+
);
174+
175+
const messageHandler = jest.fn();
176+
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
177+
const iframe = container.querySelector("iframe");
178+
expect(iframe).not.toBeNull();
179+
expect(iframe?.contentWindow).not.toBeNull();
180+
iframe!.contentWindow!.addEventListener("message", messageHandler);
181+
182+
// Act
183+
iframeRef.current?.sendNewData({
184+
type: "hint",
185+
data: {
186+
hint: {content: "Hello world", images: {}, widgets: {}},
187+
bold: false,
188+
pos: 0,
189+
linterContext: {
190+
contentType: "hint",
191+
highlightLint: true,
192+
paths: [],
193+
stack: [],
194+
},
195+
},
196+
});
197+
198+
// Assert
199+
await waitFor(() => expect(messageHandler).toHaveBeenCalled());
200+
});
201+
202+
it("should handle update-iframe-height message", async () => {
203+
// Arrange
204+
const iframeRef = React.createRef<IframeContentRenderer>();
205+
const {container} = render(
206+
<IframeContentRenderer
207+
ref={iframeRef}
208+
seamless={true}
209+
url="http://localhost/perseus/frame"
210+
/>,
211+
);
212+
213+
const iframeID = getIframeID(document.querySelector("iframe"));
214+
215+
// Act
216+
sendMessageToIframeParent({
217+
type: "perseus:update-iframe-height",
218+
frameID: iframeID,
219+
height: 929,
220+
});
221+
222+
// Assert
223+
await waitFor(() =>
224+
expect(container.firstElementChild).toHaveStyle({height: "929px"}),
225+
);
226+
});
227+
228+
it("should handle request-data message", async () => {
229+
// Arrange
230+
const iframeRef = React.createRef<IframeContentRenderer>();
231+
render(
232+
<IframeContentRenderer
233+
ref={iframeRef}
234+
seamless={false}
235+
url="http://localhost/perseus/frame"
236+
/>,
237+
);
238+
239+
const iframeID = getIframeID(document.querySelector("iframe"));
240+
let message: any = null;
241+
const messageHandler = jest.fn().mockImplementation((e) => {
242+
message = e.data;
243+
});
244+
window.parent!.addEventListener("message", messageHandler);
245+
246+
// Act
247+
sendMessageToIframeParent({
248+
type: "perseus:request-data",
249+
frameID: iframeID,
250+
});
251+
252+
// Assert
253+
await waitFor(() => expect(messageHandler).toHaveBeenCalled());
254+
expect(message).toEqual({
255+
type: "perseus:request-data",
256+
frameID: iframeID,
257+
});
258+
});
148259
});

packages/perseus-editor/src/iframe-content-renderer.tsx

+8-6
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,17 @@ function processIframeParentMessage(message: MessageToIFrameParent) {
6969
const messageType = message.type;
7070
switch (messageType) {
7171
case "perseus:update-iframe-height":
72-
updateIframeHeight[message.frameID](message.height);
72+
message; // ?
73+
updateIframeHeight; // ?
74+
updateIframeHeight[message.frameID]?.(message.height);
7375
return;
7476

7577
case "perseus:request-data":
76-
// In Perseus, we expect the callback to exist, as it is added by
77-
// `IframeContentRenderer.componentDidMount()`. Unfortunately, this
78-
// event listener also gets added in Manticore (since we include Perseus
79-
// from there), and Crowdin fires its own "message" events. So we'll
80-
// just have to ignore the event when we can't find the callback.
78+
// In Perseus, we expect the callback to exist, as it is added by
79+
// `IframeContentRenderer.componentDidMount()`. Unfortunately, this
80+
// event listener also gets added in Manticore (since we include Perseus
81+
// from there), and Crowdin fires its own "message" events. So we'll
82+
// just have to ignore the event when we can't find the callback.
8183
requestIframeData[message.frameID]?.();
8284
return;
8385

0 commit comments

Comments
 (0)