diff --git a/apps/web/components/booking/CancelBooking.tsx b/apps/web/components/booking/CancelBooking.tsx index 81d883b50a..ea04cd43c1 100644 --- a/apps/web/components/booking/CancelBooking.tsx +++ b/apps/web/components/booking/CancelBooking.tsx @@ -2,12 +2,11 @@ import { useCallback, useState } from "react"; import { sdkActionManager } from "@calcom/embed-core/embed-iframe"; import { useLocale } from "@calcom/lib/hooks/useLocale"; +import { useRefreshData } from "@calcom/lib/hooks/useRefreshData"; import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry"; import type { RecurringEvent } from "@calcom/types/Calendar"; import { Button, Icon, TextArea } from "@calcom/ui"; -import { useRefreshData } from "@lib/hooks/useRefreshData"; - type Props = { booking: { title?: string; diff --git a/apps/web/playwright/fixtures/users.ts b/apps/web/playwright/fixtures/users.ts index 16584a3a45..6e887999d8 100644 --- a/apps/web/playwright/fixtures/users.ts +++ b/apps/web/playwright/fixtures/users.ts @@ -1,4 +1,4 @@ -import type { Page, WorkerInfo } from "@playwright/test"; +import type { Browser, Page, WorkerInfo } from "@playwright/test"; import { expect } from "@playwright/test"; import type Prisma from "@prisma/client"; import type { Team } from "@prisma/client"; @@ -732,6 +732,14 @@ const createUserFixture = (user: UserWithIncludes, page: Page) => { self, apiLogin: async (password?: string) => apiLogin({ ...(await self()), password: password || user.username }, store.page), + /** Don't forget to close context at the end */ + apiLoginOnNewBrowser: async (browser: Browser, password?: string) => { + const newContext = await browser.newContext(); + const newPage = await newContext.newPage(); + await apiLogin({ ...(await self()), password: password || user.username }, newPage); + // Don't forget to: newContext.close(); + return [newContext, newPage] as const; + }, /** * @deprecated use apiLogin instead */ diff --git a/apps/web/playwright/managed-event-types.e2e.ts b/apps/web/playwright/managed-event-types.e2e.ts index 3951594d2b..ca0e85e542 100644 --- a/apps/web/playwright/managed-event-types.e2e.ts +++ b/apps/web/playwright/managed-event-types.e2e.ts @@ -185,10 +185,7 @@ test.describe("Managed Event Types", () => { await saveAndWaitForResponse(memberPage); // We edit the managed event as original owner - const adminContext = await browser.newContext(); - const adminPage = await adminContext.newPage(); - const adminUserSnapshot = await adminUser.self(); - await apiLogin({ ...adminUserSnapshot, password: adminUserSnapshot.username }, adminPage); + const [adminContext, adminPage] = await adminUser.apiLoginOnNewBrowser(browser); await adminPage.goto("/event-types"); await adminPage.getByTestId("event-types").locator(`a[title="${teamEventTitle}"]`).click(); await adminPage.waitForURL("event-types/**"); diff --git a/apps/web/playwright/organization/booking.e2e.ts b/apps/web/playwright/organization/booking.e2e.ts index 5fb2a9c45b..cc4e423b6b 100644 --- a/apps/web/playwright/organization/booking.e2e.ts +++ b/apps/web/playwright/organization/booking.e2e.ts @@ -542,9 +542,9 @@ test.describe("Bookings", () => { const usernameOutsideOrg = userOutsideOrganization.username; // Before invite is accepted the booking page isn't available await expectPageToBeNotFound({ page, url: `/${usernameInOrg}` }); - await userOutsideOrganization.apiLogin(); - await acceptTeamOrOrgInvite(page); - await userOutsideOrganization.logout(); + const [newContext, newPage] = await userOutsideOrganization.apiLoginOnNewBrowser(browser); + await acceptTeamOrOrgInvite(newPage); + await newContext.close(); await test.step("Book through new link", async () => { await doOnOrgDomain( { diff --git a/apps/web/playwright/reschedule.e2e.ts b/apps/web/playwright/reschedule.e2e.ts index 174a3dfdc6..b008dd1c09 100644 --- a/apps/web/playwright/reschedule.e2e.ts +++ b/apps/web/playwright/reschedule.e2e.ts @@ -287,10 +287,7 @@ test.describe("Reschedule Tests", async () => { const eventType = user.eventTypes.find((e) => e.slug === "opt-in")!; const confirmBooking = async (bookingId: number) => { - const authedContext = await browser.newContext(); - const authedPage = await authedContext.newPage(); - const userSnapshot = await user.self(); - await apiLogin({ ...userSnapshot, password: userSnapshot.username }, authedPage); + const [authedContext, authedPage] = await user.apiLoginOnNewBrowser(browser); await authedPage.goto("/bookings/upcoming"); await submitAndWaitForResponse(authedPage, "/api/trpc/bookings/confirm?batch=1", { action: () => authedPage.locator(`[data-bookingid="${bookingId}"][data-testid="confirm"]`).click(), diff --git a/packages/features/ee/teams/components/TeamListItem.tsx b/packages/features/ee/teams/components/TeamListItem.tsx index 099674dac2..6dacdd1ff9 100644 --- a/packages/features/ee/teams/components/TeamListItem.tsx +++ b/packages/features/ee/teams/components/TeamListItem.tsx @@ -9,6 +9,7 @@ import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage"; import { getTeamUrlSync } from "@calcom/lib/getBookerUrl/client"; import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams"; import { useLocale } from "@calcom/lib/hooks/useLocale"; +import { useRefreshData } from "@calcom/lib/hooks/useRefreshData"; import { MembershipRole } from "@calcom/prisma/enums"; import type { RouterOutputs } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react"; @@ -51,6 +52,7 @@ export default function TeamListItem(props: Props) { const showDialog = searchParams?.get("inviteModal") === "true"; const [openMemberInvitationModal, setOpenMemberInvitationModal] = useState(showDialog); const [openInviteLinkSettingsModal, setOpenInviteLinkSettingsModal] = useState(false); + const refreshData = useRefreshData(); const acceptOrLeaveMutation = trpc.viewer.teams.acceptOrLeave.useMutation({ onSuccess: (_data, variables) => { @@ -64,7 +66,7 @@ export default function TeamListItem(props: Props) { const isDifferentOrg = team.isOrganization && team.id !== userOrganizationId; // If the user team being accepted is a sub-team of different organization or the different organization itself then page must be reloaded to let the session change reflect reliably everywhere. if (variables.accept && (isSubTeamOfDifferentOrg || isDifferentOrg)) { - window.location.reload(); + refreshData(); } }, }); diff --git a/packages/features/shell/Shell.tsx b/packages/features/shell/Shell.tsx index 461c5cb44a..247f443f98 100644 --- a/packages/features/shell/Shell.tsx +++ b/packages/features/shell/Shell.tsx @@ -56,6 +56,7 @@ import { useBookerUrl } from "@calcom/lib/hooks/useBookerUrl"; import { useCopy } from "@calcom/lib/hooks/useCopy"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { ButtonState, useNotifications } from "@calcom/lib/hooks/useNotifications"; +import { useRefreshData } from "@calcom/lib/hooks/useRefreshData"; import useTheme from "@calcom/lib/hooks/useTheme"; import { isKeyInObject } from "@calcom/lib/isKeyInObject"; import { localStorage } from "@calcom/lib/webstorage"; @@ -1286,6 +1287,7 @@ function ProfileDropdown() { const { update, data: sessionData } = useSession(); const { data } = trpc.viewer.me.useQuery(); const [menuOpen, setMenuOpen] = useState(false); + const refreshData = useRefreshData(); if (!data || !ENABLE_PROFILE_SWITCHER || !sessionData) { return null; @@ -1349,7 +1351,7 @@ function ProfileDropdown() { update({ upId: option.value, }).then(() => { - window.location.reload(); + refreshData(); }); }} className={classNames("flex w-full", isSelected ? "bg-subtle text-emphasis" : "")}> diff --git a/apps/web/lib/hooks/useAsPath.ts b/packages/lib/hooks/useAsPath.ts similarity index 100% rename from apps/web/lib/hooks/useAsPath.ts rename to packages/lib/hooks/useAsPath.ts diff --git a/apps/web/lib/hooks/useRefreshData.ts b/packages/lib/hooks/useRefreshData.ts similarity index 100% rename from apps/web/lib/hooks/useRefreshData.ts rename to packages/lib/hooks/useRefreshData.ts