feat: e2e tests for Connect atoms (#23433)

* e2e tests for apple connect atom

* update globalEnv for turbo.json

* update pages for tests

* update playwright config so we can use env variables inside tests

* update packages

* update variable names

* update playwright config

* fix: import variables from env instead of separate files

* update env variables for atoms e2e yml
This commit is contained in:
Rajiv Sahal
2025-09-17 11:20:38 +02:00
committed by GitHub
parent f9095d298d
commit eaa1ad6578
6 changed files with 78 additions and 2 deletions
@@ -26,6 +26,7 @@
"@types/react": "^18",
"@types/react-dom": "^18",
"autoprefixer": "^10.0.1",
"dotenv": "^17.2.1",
"eslint": "^8.34.0",
"eslint-config-next": "14.0.4",
"postcss": "^8",
@@ -1,4 +1,10 @@
import { defineConfig, devices } from "@playwright/test";
import dotenv from "dotenv";
import path from "path";
const envPath = process.env.CI ? path.resolve(__dirname, ".env") : path.resolve(__dirname, ".env.local");
dotenv.config({ path: envPath });
const DEFAULT_EXPECT_TIMEOUT = process.env.CI ? 30000 : 120000;
const DEFAULT_TEST_TIMEOUT = process.env.CI ? 60000 : 240000;
@@ -9,7 +9,7 @@ export default function Calendars(props: { calUsername: string; calEmail: string
return (
<main className={`flex min-h-screen flex-col ${inter.className}`}>
<Navbar username={props.calUsername} />
<div>
<div data-testid="calendars-settings-atom">
<CalendarSettings
allowDelete={true}
classNames={{
@@ -1,5 +1,7 @@
import { Navbar } from "@/components/Navbar";
import { Inter, Poppins } from "next/font/google";
// eslint-disable-next-line @calcom/eslint/deprecated-imports-next-router
import { useRouter } from "next/router";
import { Connect, StripeConnect } from "@calcom/atoms";
@@ -7,6 +9,8 @@ const inter = Inter({ subsets: ["latin"] });
const poppins = Poppins({ subsets: ["latin"], weight: ["400", "800"] });
export default function Home(props: { calUsername: string; calEmail: string }) {
const router = useRouter();
return (
<main className={`flex min-h-screen flex-col ${inter.className} items-center justify-center`}>
<Navbar username={props.calUsername} />
@@ -19,7 +23,7 @@ export default function Home(props: { calUsername: string; calEmail: string }) {
<p className={`w-[70%] font-normal ${inter.className} pb-3 text-2xl`}>
To get started, connect your google calendar.
</p>
<div className="flex flex-row gap-4">
<div data-testid="connect-atoms" className="flex flex-row gap-4">
<Connect.GoogleCalendar
redir="http://localhost:4321/calendars"
className="h-[40px] bg-gradient-to-r from-[#8A2387] via-[#E94057] to-[#F27121] text-center text-base font-semibold text-transparent text-white hover:bg-orange-700"
@@ -30,6 +34,9 @@ export default function Home(props: { calUsername: string; calEmail: string }) {
className="h-[40px] bg-gradient-to-r from-[#8A2387] via-[#E94057] to-[#F27121] text-center text-base font-semibold text-transparent text-white hover:bg-orange-700"
/>
<Connect.AppleCalendar
onSuccess={() => {
router.push(`/calendars`);
}}
isMultiCalendar={true}
className="h-[40px] bg-gradient-to-r from-[#8A2387] via-[#E94057] to-[#F27121] text-center text-base font-semibold text-transparent text-white hover:bg-orange-700"
/>
@@ -0,0 +1,60 @@
import { test, expect } from "@playwright/test";
test("connect calendar using the apple connect atom", async ({ page }) => {
const appleId = process.env.ATOMS_E2E_APPLE_ID;
const appSpecificPassword = process.env.ATOMS_E2E_APPLE_CONNECT_APP_SPECIFIC_PASSCODE;
await page.goto("/");
await expect(page.locator("body")).toBeVisible();
await expect(page.locator('[data-testid="connect-atoms"]')).toBeVisible();
await page.locator('[data-testid="connect-atoms"] button:has-text("Connect Apple Calendar")').click();
await expect(page.locator('[role="dialog"]')).toBeVisible();
await expect(page.locator('[role="dialog"] fieldset[data-testid="apple-calendar-form"]')).toBeVisible();
await expect(page.locator('[data-testid="apple-calendar-email"]')).toBeVisible();
await page.locator('[data-testid="apple-calendar-email"]').fill(appleId ?? "");
await expect(page.locator('[data-testid="apple-calendar-password"]')).toBeVisible();
await page.locator('[data-testid="apple-calendar-password"]').fill(appSpecificPassword ?? "");
await page.locator('[data-testid="apple-calendar-login-button"]').click();
await expect(page).toHaveURL("/calendars");
await expect(page.locator("body")).toBeVisible();
await expect(page.locator('[data-testid="calendars-settings-atom"]')).toBeVisible();
await expect(page.locator('h2:has-text("Add to calendar")')).toBeVisible();
await expect(page.locator('label:has-text("Add events to")')).toBeVisible();
await expect(page.locator('[data-testid="select-control"]')).toBeVisible();
await page.locator('[data-testid="select-control"]').click();
await page.keyboard.press("ArrowDown");
await page.keyboard.press("Enter");
await expect(page.locator('h4:has-text("Check for conflicts")')).toBeVisible();
await expect(page.locator('[data-testid="list"]')).toBeVisible();
await page.locator('[data-testid="list"] button:has(svg[data-name="start-icon"])').click();
await page.locator('[data-testid="dialog-rejection"]').click();
await expect(page.locator('[data-testid="list"] button[role="switch"]').first()).toBeVisible();
await page.locator('[data-testid="list"] button[role="switch"]').first().click();
await expect(page.locator('[data-testid="list"] button[role="switch"]').last()).toBeVisible();
await page.locator('[data-testid="list"] button[role="switch"]').last().click();
await expect(page.locator('[data-testid="list"] button[role="switch"]').first()).toBeVisible();
await page.locator('[data-testid="list"] button[role="switch"]').first().click();
await page.locator('[data-testid="list"] button:has(svg[data-name="start-icon"])').click();
await page.locator('[data-testid="dialog-confirmation"]').click();
});
+2
View File
@@ -276,6 +276,8 @@
"NEXT_PUBLIC_WEBAPP_URL",
"NEXT_PUBLIC_WEBSITE_URL",
"BUILD_STANDALONE",
"ATOMS_E2E_APPLE_ID",
"ATOMS_E2E_APPLE_CONNECT_APP_SPECIFIC_PASSCODE",
"INTERCOM_API_TOKEN",
"NEXT_PUBLIC_INTERCOM_APP_ID"
],