-
Notifications
You must be signed in to change notification settings - Fork 12k
feat: e2e tests for Connect atoms
#23433
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4b2a5ae
5528e76
242d8ab
bf7a1ee
19947b8
f056185
dc026ad
4b0b59d
4e918d0
956de9f
34d5e92
4aaa69d
f39b1b1
614c322
237630e
e4eef2d
4d3e9d7
c544b35
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -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("/"); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainConfirm Playwright baseURL is set for the examples app. Without baseURL, Run to verify: 🏁 Script executed: #!/bin/bash
# Check baseURL and dotenv loading in Playwright config
fd -a 'playwright.config.ts' | xargs -I{} sh -c 'echo "== {} =="; rg -n "baseURL|dotenv|config\\(" {} -n -C2'
# Ensure APPLE_* appears in turbo.json globalEnv and .env.example files
fd -a 'turbo.json' | xargs -I{} sh -c 'echo "== {} =="; cat "{}" | jq .globalEnv'
fd -a '.env.example' | xargs -I{} sh -c 'echo "== {} =="; rg -n "APPLE_ID|APPLE_CONNECT_APP_SPECIFIC_PASSCODE" "{}" -n'Length of output: 9199 Playwright baseURL is configured; add Apple credential placeholders to the example’s
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| 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"); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix brittle URL assertion (exact-match vs full URL). Use regex/suffix to avoid strict equality mismatch with baseURL. - await expect(page).toHaveURL("/calendars");
+ await expect(page).toHaveURL(/\/calendars$/);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| 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"); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+37
to
+42
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Make select interaction deterministic. Wait for listbox and pick a concrete option instead of key presses. - 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.getByTestId("select-control")).toBeVisible();
+ await page.getByTestId("select-control").click();
+ await expect(page.getByRole("listbox")).toBeVisible();
+ await page.getByRole("option").first().click();📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||
| 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(); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+46
to
+47
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Await dialog visibility before acting on it. Eliminates race conditions. - await page.locator('[data-testid="list"] button:has(svg[data-name="start-icon"])').click();
- await page.locator('[data-testid="dialog-rejection"]').click();
+ await page.locator('[data-testid="list"] button:has(svg[data-name="start-icon"])').click();
+ await expect(page.locator('[data-testid="dialog-rejection"]')).toBeVisible();
+ await page.locator('[data-testid="dialog-rejection"]').click();
@@
- await page.locator('[data-testid="list"] button:has(svg[data-name="start-icon"])').click();
- await page.locator('[data-testid="dialog-confirmation"]').click();
+ await page.locator('[data-testid="list"] button:has(svg[data-name="start-icon"])').click();
+ await expect(page.locator('[data-testid="dialog-confirmation"]')).toBeVisible();
+ await page.locator('[data-testid="dialog-confirmation"]').click();Also applies to: 58-59 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| 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(); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+49
to
+56
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Assert switch state changes, not just clicks. Validates behavior via aria-checked. - 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();
+ const list = page.getByTestId("list");
+ const firstSwitch = list.getByRole("switch").first();
+ await expect(firstSwitch).toBeVisible();
+ const prevFirst = await firstSwitch.getAttribute("aria-checked");
+ await firstSwitch.click();
+ await expect(firstSwitch).toHaveAttribute("aria-checked", prevFirst === "true" ? "false" : "true");
+
+ const lastSwitch = list.getByRole("switch").last();
+ await expect(lastSwitch).toBeVisible();
+ const prevLast = await lastSwitch.getAttribute("aria-checked");
+ await lastSwitch.click();
+ await expect(lastSwitch).toHaveAttribute("aria-checked", prevLast === "true" ? "false" : "true");
+
+ await firstSwitch.click(); // revert
+ await expect(firstSwitch).toHaveAttribute("aria-checked", prevFirst);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| await page.locator('[data-testid="list"] button:has(svg[data-name="start-icon"])').click(); | ||||||||||||||||||||||||||||||||||||||||||||||||
| await page.locator('[data-testid="dialog-confirmation"]').click(); | ||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In prod we would not have an
.envfile - all of the variables are already in CI environment but its fine - lets just get this merged and I have started refactoring e2e setup locally with separate test database, database cleanup etc.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI there should be
env.localcomitted to this PR containing all the keys necessary for the local e2e test and then dev fills them manually.usually you call it
env.local.exampleand commit it and then in gitignore ignoreenv.localbecause you renameenv.local.exampletoenv.localand fill necessary keys.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its fine for now as longs as e2e in ci pass because i will fix it in separate PR