4226d2262d
This fixes a race condition in the embed E2E tests where the __iframeReady event could fire before the Cal.ns[namespace] API was ready to receive it. The fix adds a window.message listener immediately in the addInitScript that captures __iframeReady events directly from postMessage, which doesn't depend on the namespace API being ready. This ensures window.iframeReady is set even if the event fires before the Cal API listener is attached. Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
156 lines
6.4 KiB
TypeScript
156 lines
6.4 KiB
TypeScript
import type { Page } from "@playwright/test";
|
|
|
|
export const createEmbedsFixture = (page: Page) => {
|
|
return {
|
|
/**
|
|
* @deprecated
|
|
* Use 'gotoPlayground' instead, to navigate. It calls `addEmbedListeners` automatically.
|
|
*/
|
|
async addEmbedListeners(calNamespace: string) {
|
|
await page.addInitScript(
|
|
({ calNamespace }: { calNamespace: string }) => {
|
|
console.log(
|
|
"PlaywrightTest - InitScript:",
|
|
"Adding listener for __iframeReady on namespace:",
|
|
calNamespace
|
|
);
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
//@ts-ignore
|
|
window.eventsFiredStoreForPlaywright = window.eventsFiredStoreForPlaywright || {};
|
|
|
|
// Add a postMessage listener immediately to capture __iframeReady events
|
|
// This avoids the race condition where the event fires before Cal.ns[namespace] is ready
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
//@ts-ignore
|
|
if (!window.postMessageListenerAdded) {
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
//@ts-ignore
|
|
window.postMessageListenerAdded = true;
|
|
window.addEventListener("message", (event) => {
|
|
// Filter for Cal.com embed messages
|
|
if (
|
|
event.data &&
|
|
typeof event.data === "object" &&
|
|
event.data.originator === "CAL" &&
|
|
event.data.type
|
|
) {
|
|
const { type, namespace, data } = event.data;
|
|
console.log("PlaywrightTest postMessage:", `Received ${type} for namespace ${namespace}`);
|
|
|
|
// Set iframeReady when we receive __iframeReady event for our namespace
|
|
if (type === "__iframeReady" && namespace === calNamespace) {
|
|
console.log("PlaywrightTest postMessage:", "Setting window.iframeReady = true");
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
//@ts-ignore
|
|
window.iframeReady = true;
|
|
}
|
|
|
|
// Store the event in our event store
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
//@ts-ignore
|
|
const store = window.eventsFiredStoreForPlaywright;
|
|
if (store) {
|
|
const eventStore = (store[`${type}-${namespace}`] = store[`${type}-${namespace}`] || []);
|
|
eventStore.push({ type, namespace, fullType: `CAL:${namespace}:${type}`, data });
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
document.addEventListener("DOMContentLoaded", function tryAddingListener() {
|
|
if (parent !== window) {
|
|
// Firefox seems to execute this snippet for iframe as well. Avoid that. It must be executed only for parent frame.
|
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
//@ts-ignore
|
|
window.initialBodyVisibility = document.body.style.visibility;
|
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
//@ts-ignore
|
|
window.initialBodyBackground = document.body.style.background;
|
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
//@ts-ignore
|
|
window.initialValuesSet = true;
|
|
return;
|
|
}
|
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
//@ts-ignore
|
|
let api = window.Cal;
|
|
|
|
if (!api) {
|
|
console.log("PlaywrightTest:", "window.Cal not available yet, trying again");
|
|
setTimeout(tryAddingListener, 500);
|
|
return;
|
|
}
|
|
if (calNamespace) {
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
//@ts-ignore
|
|
api = window.Cal.ns[calNamespace];
|
|
console.log("Using api from namespace-", { calNamespace, api });
|
|
}
|
|
if (!api) {
|
|
console.log(`namespace "${calNamespace}" not found yet - Trying again`);
|
|
setTimeout(tryAddingListener, 500);
|
|
return;
|
|
}
|
|
console.log("PlaywrightTest:", `Adding listener for __iframeReady on namespace:${calNamespace}`);
|
|
api("on", {
|
|
action: "*",
|
|
callback: (e) => {
|
|
console.log("Playwright Embed Fixture: Received event", JSON.stringify(e.detail));
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
// @ts-ignore
|
|
window.iframeReady = true; // Technically if there are multiple cal embeds, it can be set due to some other iframe. But it works for now. Improve it when it doesn't work
|
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
// @ts-ignore
|
|
const store = window.eventsFiredStoreForPlaywright;
|
|
const eventStore = (store[`${e.detail.type}-${e.detail.namespace}`] =
|
|
store[`${e.detail.type}-${e.detail.namespace}`] || []);
|
|
eventStore.push(e.detail);
|
|
},
|
|
});
|
|
});
|
|
},
|
|
{ calNamespace }
|
|
);
|
|
|
|
page.on("console", (msg) => {
|
|
console.log(`Browser Console: ${msg.type()}: ${msg.text()}`);
|
|
});
|
|
|
|
page.on("framenavigated", async (frame) => {
|
|
console.log(`Navigation occurred in frame: ${frame.url()}`);
|
|
});
|
|
|
|
page.on("pageerror", (error) => {
|
|
console.error(`Page error: ${error.message}`);
|
|
});
|
|
|
|
page.on("requestfailed", (request) => {
|
|
console.error(`Failed request: ${request.url()}, ${request.failure()?.errorText}`);
|
|
});
|
|
},
|
|
|
|
async getActionFiredDetails({ calNamespace, actionType }: { calNamespace: string; actionType: string }) {
|
|
if (!page.isClosed()) {
|
|
return await page.evaluate(
|
|
({ actionType, calNamespace }) => {
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
//@ts-ignore
|
|
return window.eventsFiredStoreForPlaywright[`${actionType}-${calNamespace}`];
|
|
},
|
|
{ actionType, calNamespace }
|
|
);
|
|
}
|
|
},
|
|
|
|
async gotoPlayground({ calNamespace, url }: { calNamespace: string; url: string }) {
|
|
await this.addEmbedListeners(calNamespace);
|
|
await page.goto(url);
|
|
},
|
|
};
|
|
};
|