diff --git a/apps/web/playwright/integrations-stripe.e2e.ts b/apps/web/playwright/integrations-stripe.e2e.ts index c8b434bee0..edf81d0bf4 100644 --- a/apps/web/playwright/integrations-stripe.e2e.ts +++ b/apps/web/playwright/integrations-stripe.e2e.ts @@ -1,8 +1,8 @@ import { expect } from "@playwright/test"; import type Prisma from "@prisma/client"; -import type { Fixtures } from "./lib/fixtures"; import { test } from "./lib/fixtures"; +import type { Fixtures } from "./lib/fixtures"; import { todo, selectFirstAvailableTimeSlotNextMonth } from "./lib/testUtils"; test.describe.configure({ mode: "parallel" }); @@ -155,4 +155,54 @@ test.describe("Stripe integration", () => { todo("Payment should trigger a BOOKING_PAID webhook"); }); + + test.describe("Change stripe presented currency", () => { + test("Should be able to change currency", async ({ page, users }) => { + const user = await users.create(); + const eventType = user.eventTypes.find((e) => e.slug === "paid") as Prisma.EventType; + await user.apiLogin(); + + await user.getPaymentCredential(); + + // Edit currency inside event type page + await page.goto(`/event-types/${eventType?.id}?tabName=apps`); + + // Enable Stripe + await page.locator("#event-type-form").getByRole("switch").click(); + + // Set price + await page.getByTestId("price-input-stripe").fill("200"); + + // Select currency in dropdown + await page.locator("div").filter({ hasText: "United States dollar (USD)" }).nth(1).click(); + await page.locator("#react-select-2-input").fill("mexi"); + await page.locator("#react-select-2-option-81").click(); + + await page.getByTestId("update-eventtype").click(); + + // Book event + await page.goto(`${user.username}/${eventType?.slug}`); + + // Confirm MXN currency it's displayed use expect + await expect(await page.getByText("MX$200.00")).toBeVisible(); + + await selectFirstAvailableTimeSlotNextMonth(page); + + // Confirm again in book form page + await expect(await page.getByText("MX$200.00")).toBeVisible(); + + // --- fill form + await page.fill('[name="name"]', "Stripe Stripeson"); + await page.fill('[name="email"]', "stripe@example.com"); + + // Confirm booking + await page.click('[data-testid="confirm-book-button"]'); + + // wait for url to be payment + await page.waitForURL("/payment/*"); + + // Confirm again in book form page + await expect(await page.getByText("MX$200.00")).toBeVisible(); + }); + }); }); diff --git a/packages/app-store/stripepayment/components/EventTypeAppCardInterface.tsx b/packages/app-store/stripepayment/components/EventTypeAppCardInterface.tsx index e49c827a81..522a07a84e 100644 --- a/packages/app-store/stripepayment/components/EventTypeAppCardInterface.tsx +++ b/packages/app-store/stripepayment/components/EventTypeAppCardInterface.tsx @@ -1,4 +1,5 @@ import { usePathname } from "next/navigation"; +import { useState } from "react"; import { useAppContextWithSchema } from "@calcom/app-store/EventTypeAppContext"; import AppCard from "@calcom/app-store/_components/AppCard"; @@ -9,6 +10,11 @@ import { useLocale } from "@calcom/lib/hooks/useLocale"; import { Alert, Select, TextField } from "@calcom/ui"; import { paymentOptions } from "../lib/constants"; +import { + convertFromSmallestToPresentableCurrencyUnit, + convertToSmallestCurrencyUnit, +} from "../lib/currencyConvertions"; +import { currencyOptions } from "../lib/currencyOptions"; import type { appDataSchema } from "../zod"; type Option = { value: string; label: string }; @@ -18,6 +24,12 @@ const EventTypeAppCard: EventTypeAppCardComponent = function EventTypeAppCard({ const { getAppData, setAppData, disabled } = useAppContextWithSchema(); const price = getAppData("price"); const currency = getAppData("currency"); + const [selectedCurrency, setSelectedCurrency] = useState( + currencyOptions.find((c) => c.value === currency) || { + label: currencyOptions[0].label, + value: currencyOptions[0].value, + } + ); const paymentOption = getAppData("paymentOption"); const paymentOptionSelectValue = paymentOptions.find((option) => paymentOption === option.value); const { enabled: requirePayment, updateEnabled: setRequirePayment } = useIsAppEnabled(app); @@ -50,11 +62,33 @@ const EventTypeAppCard: EventTypeAppCardComponent = function EventTypeAppCard({ )} {!recurringEventDefined && requirePayment && ( <> -
+
+ +