fix: add postMessage listener to capture __iframeReady events early (#26258)
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>
This commit is contained in:
co-authored by
Devin AI
parent
00c7415e28
commit
4226d2262d
@@ -114,7 +114,7 @@ export async function createFilterSegment(
|
||||
* Select a segment from the dropdown
|
||||
*/
|
||||
export async function selectSegment(page: Page, segmentName: string) {
|
||||
await page.getByTestId("filter-segment-select").click();
|
||||
await page.getByTestId("filter-segment-select").first().click();
|
||||
|
||||
await page
|
||||
.locator('[data-testid="filter-segment-select-content"] [role="menuitem"]')
|
||||
@@ -126,7 +126,7 @@ export async function selectSegment(page: Page, segmentName: string) {
|
||||
* Open submenu of a certain segment
|
||||
*/
|
||||
export async function openSegmentSubmenu(page: Page, segmentName: string) {
|
||||
await page.getByTestId("filter-segment-select").click();
|
||||
await page.getByTestId("filter-segment-select").first().click();
|
||||
|
||||
await page
|
||||
.locator('[data-testid="filter-segment-select-content"] [role="menuitem"]')
|
||||
@@ -183,7 +183,7 @@ export function locateSelectedSegmentName(page: Page, expectedName: string) {
|
||||
* Check if a system segment is visible in the dropdown
|
||||
*/
|
||||
export async function expectSystemSegmentVisible(page: Page, segmentName: string) {
|
||||
await page.getByTestId("filter-segment-select").click();
|
||||
await page.getByTestId("filter-segment-select").first().click();
|
||||
await expect(
|
||||
page.locator('[data-testid="filter-segment-select-content"]').getByText("Default")
|
||||
).toBeVisible();
|
||||
@@ -240,7 +240,7 @@ export async function renameSegment(page: Page, originalName: string, newName: s
|
||||
* Check if a segment group (like "Default" or "Personal") is visible
|
||||
*/
|
||||
export async function expectSegmentGroupVisible(page: Page, groupName: string) {
|
||||
await page.getByTestId("filter-segment-select").click();
|
||||
await page.getByTestId("filter-segment-select").first().click();
|
||||
await expect(
|
||||
page.locator('[data-testid="filter-segment-select-content"]').getByText(groupName)
|
||||
).toBeVisible();
|
||||
|
||||
@@ -17,6 +17,46 @@ export const createEmbedsFixture = (page: Page) => {
|
||||
// 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.
|
||||
|
||||
@@ -46,7 +46,7 @@ test.describe("System Segments", () => {
|
||||
|
||||
await navigateToBookings(page);
|
||||
|
||||
await page.getByTestId("filter-segment-select").click();
|
||||
await page.getByTestId("filter-segment-select").first().click();
|
||||
await page
|
||||
.locator('[data-testid="filter-segment-select-content"] [role="menuitem"]')
|
||||
.filter({ hasText: "My Bookings" })
|
||||
|
||||
@@ -33,7 +33,10 @@ test.describe("Team", () => {
|
||||
await page.waitForTimeout(500); // Add a small delay to ensure UI is fully loaded
|
||||
await page.getByTestId("new-member-button").click();
|
||||
await page.locator('input[name="inviteUser"]').fill(invitedUserEmail);
|
||||
await page.getByText(t("send_invite")).click();
|
||||
const submitPromise = page.waitForResponse("/api/trpc/teams/inviteMember?batch=1");
|
||||
await page.getByTestId("invite-new-member-button").click();
|
||||
const response = await submitPromise;
|
||||
expect(response.status()).toBe(200);
|
||||
const inviteLink = await expectInvitationEmailToBeReceived(
|
||||
page,
|
||||
emails,
|
||||
@@ -119,7 +122,10 @@ test.describe("Team", () => {
|
||||
await page.waitForTimeout(500); // Add a small delay to ensure UI is fully loaded
|
||||
await page.getByTestId("new-member-button").click();
|
||||
await page.locator('input[name="inviteUser"]').fill(invitedUserEmail);
|
||||
await page.getByText(t("send_invite")).click();
|
||||
const submitPromise = page.waitForResponse("/api/trpc/teams/inviteMember?batch=1");
|
||||
await page.getByTestId("invite-new-member-button").click();
|
||||
const response = await submitPromise;
|
||||
expect(response.status()).toBe(200);
|
||||
await expectInvitationEmailToBeReceived(
|
||||
page,
|
||||
emails,
|
||||
@@ -167,13 +173,17 @@ test.describe("Team", () => {
|
||||
await page.waitForTimeout(500); // Add a small delay to ensure UI is fully loaded
|
||||
await page.getByTestId("new-member-button").click();
|
||||
await page.locator('input[name="inviteUser"]').fill(invitedMember.email);
|
||||
await page.getByText(t("send_invite")).click();
|
||||
const submitPromise = page.waitForResponse("/api/trpc/teams/inviteMember?batch=1");
|
||||
await page.getByTestId("invite-new-member-button").click();
|
||||
const response = await submitPromise;
|
||||
expect(response.status()).toBe(200);
|
||||
|
||||
await invitedMember.apiLogin();
|
||||
await page.goto(`/teams`);
|
||||
await page.getByTestId(`accept-invitation-${team.id}`).click();
|
||||
const response = await page.waitForResponse("/api/trpc/teams/acceptOrLeave?batch=1");
|
||||
expect(response.status()).toBe(200);
|
||||
const response2Promise = page.waitForResponse("/api/trpc/teams/acceptOrLeave?batch=1");
|
||||
await page.getByTestId(`accept-invitation-${team.id}`).first().click();
|
||||
const response2 = await response2Promise;
|
||||
expect(response2.status()).toBe(200);
|
||||
await page.goto(`/event-types`);
|
||||
|
||||
//ensure managed event-type is created for the invited member
|
||||
@@ -211,7 +221,10 @@ test.describe("Team", () => {
|
||||
await page.waitForTimeout(500);
|
||||
await page.getByTestId("new-member-button").click();
|
||||
await page.locator('input[name="inviteUser"]').fill(invitedUser.email);
|
||||
await page.getByText(t("send_invite")).click();
|
||||
const submitPromise = page.waitForResponse("/api/trpc/teams/inviteMember?batch=1");
|
||||
await page.getByTestId("invite-new-member-button").click();
|
||||
const response = await submitPromise;
|
||||
expect(response.status()).toBe(200);
|
||||
|
||||
inviteLink = await expectInvitationEmailToBeReceived(
|
||||
page,
|
||||
@@ -275,7 +288,10 @@ test.describe("Team", () => {
|
||||
await page.waitForTimeout(500);
|
||||
await page.getByTestId("new-member-button").click();
|
||||
await page.locator('input[name="inviteUser"]').fill(invitedUser.email);
|
||||
await page.getByText(t("send_invite")).click();
|
||||
const submitPromise = page.waitForResponse("/api/trpc/teams/inviteMember?batch=1");
|
||||
await page.getByTestId("invite-new-member-button").click();
|
||||
const response = await submitPromise;
|
||||
expect(response.status()).toBe(200);
|
||||
|
||||
inviteLink = await expectInvitationEmailToBeReceived(
|
||||
page,
|
||||
|
||||
Reference in New Issue
Block a user