From 2d6ad58d7850238aad8a1c8d07c66b58ab837bc2 Mon Sep 17 00:00:00 2001 From: afolasope Date: Fri, 16 Aug 2024 15:16:51 +0100 Subject: [PATCH 01/15] create auth tests --- apps/frontend/.gitignore | 1 + apps/frontend/playwright.config.ts | 5 + apps/frontend/tests/auth.setup.ts | 106 ++++++++++++++++++ apps/frontend/tests/utils/constants.ts | 3 + .../tests/workspace/create-workspace.spec.ts | 10 ++ .../tests/workspace/manage-workspace.spec.ts | 0 6 files changed, 125 insertions(+) create mode 100644 apps/frontend/tests/auth.setup.ts create mode 100644 apps/frontend/tests/utils/constants.ts create mode 100644 apps/frontend/tests/workspace/create-workspace.spec.ts create mode 100644 apps/frontend/tests/workspace/manage-workspace.spec.ts diff --git a/apps/frontend/.gitignore b/apps/frontend/.gitignore index b88c8135..2f878a4e 100644 --- a/apps/frontend/.gitignore +++ b/apps/frontend/.gitignore @@ -26,3 +26,4 @@ dist-ssr /playwright-report/ /blob-report/ /playwright/.cache/ +/playwright/.auth/ diff --git a/apps/frontend/playwright.config.ts b/apps/frontend/playwright.config.ts index 55c996b3..dfe125f6 100644 --- a/apps/frontend/playwright.config.ts +++ b/apps/frontend/playwright.config.ts @@ -33,19 +33,24 @@ export default defineConfig({ /* Configure projects for major browsers */ projects: [ + { name: "setup", testMatch: /.*\.setup\.ts/ }, + { name: "chromium", use: { ...devices["Desktop Chrome"] }, + dependencies: ["setup"], }, { name: "firefox", use: { ...devices["Desktop Firefox"] }, + dependencies: ["setup"], }, { name: "webkit", use: { ...devices["Desktop Safari"] }, + dependencies: ["setup"], }, /* Test against mobile viewports. */ diff --git a/apps/frontend/tests/auth.setup.ts b/apps/frontend/tests/auth.setup.ts new file mode 100644 index 00000000..d24f7f1c --- /dev/null +++ b/apps/frontend/tests/auth.setup.ts @@ -0,0 +1,106 @@ +import { expect, Page, test as setup } from "@playwright/test"; +import { NEW_USER_FILE, NON_ONBOARDED_USER_FILE, ONBOARDED_USER_FILE } from "./utils/constants"; + +const e2eTestToken = "e2e_test_token"; + +const createWorkspaceUrl = "/create-workspace"; +const onboardingUrl = /\/[\w-]+\/projects\/[\w-]+\/get-started/; +const surveyListUrl = /\/onboarded\/projects\/[\w-]+\/surveys/; + +async function authenticateUser(page: Page, email: string, stateFile: string) { + await page.goto("/"); + await page.getByPlaceholder("Enter your email").fill(email); + await page.getByRole("button", { name: /Continue with email/i }).click(); + await page.waitForURL(`/auth/magic-sign-in/?email=${encodeURIComponent(email)}`); + await page.getByRole("button", { name: /enter code manually/i }).click(); + await page.fill('input[name="code"]', e2eTestToken); + await page.getByRole("button", { name: /continue/i }).click(); + + await page.context().storageState({ path: stateFile }); +} + +setup("authenticate as new user", async ({ page }) => { + await authenticateUser(page, "new-user@example.com", NEW_USER_FILE); + + await page.waitForURL("/create-workspace"); + await expect(page).toHaveURL("/create-workspace"); + await expect(page.locator("h3")).toContainText("Create a new workspace"); +}); + +setup("authenticate as onboarded user", async ({ page }) => { + await authenticateUser(page, "onboarded@example.com", ONBOARDED_USER_FILE); + + // Wait for the navigation to complete to one of the expected URLs + await page.waitForURL((url) => { + return ( + onboardingUrl.test(url.pathname) || url.pathname === createWorkspaceUrl || surveyListUrl.test(url.pathname) + ); + }); + + const currentUrl = page.url(); + + if (currentUrl.includes(createWorkspaceUrl)) { + await expect(page).toHaveURL(createWorkspaceUrl); + await expect(page.locator("h3")).toContainText("Create a new workspace"); + + await page.locator('[name="workspaceName"]').fill("onboarded"); + await page.locator('[name="workspaceUrl"]').fill("onboarded"); + await page.getByRole("button", { name: /Create Workspace/i }).click(); + + await page.waitForURL(onboardingUrl); + await expect(page).toHaveURL(onboardingUrl); + await handleOnboardingSteps(page); + } else if (surveyListUrl.test(currentUrl)) { + await expect(page).toHaveURL(surveyListUrl); + } else { + throw new Error(`Unexpected URL: ${currentUrl}`); + } +}); + +setup("authenticate as non onboarded user", async ({ page }) => { + await authenticateUser(page, "test2@example.com", NON_ONBOARDED_USER_FILE); + + // Wait for the navigation to either create workspace or existing workspace + await page.waitForURL((url) => { + return onboardingUrl.test(url.pathname) || url.pathname === createWorkspaceUrl; + }); + + const currentUrl = page.url(); + + if (currentUrl.includes(createWorkspaceUrl)) { + await expect(page).toHaveURL(createWorkspaceUrl); + await expect(page.locator("h3")).toContainText("Create a new workspace"); + + await page.locator('[name="workspaceName"]').fill("test2"); + await page.locator('[name="workspaceUrl"]').fill("test2"); + await page.getByRole("button", { name: /Create Workspace/i }).click(); + + await page.waitForURL(onboardingUrl); + await expect(page).toHaveURL(onboardingUrl); + await expect(page.locator("h1").nth(0)).toContainText("Getting started"); + } else if (onboardingUrl.test(currentUrl)) { + await expect(page).toHaveURL(onboardingUrl); + await expect(page.locator("h1").nth(0)).toContainText("Getting started"); + } else { + throw new Error(`Unexpected URL: ${currentUrl}`); + } +}); + +async function handleOnboardingSteps(page: Page) { + const activeButton = page.locator('button[data-state="active"]'); + + const steps = [ + /integrate sdk/i, + /identify your users/i, + /track your events/i, + /publish your first survey/i, + /connect your first integration/i, + ]; + + for (const step of steps) { + await expect(activeButton).toContainText(step); + await page.getByRole("button", { name: /skip/i }).click(); + } + + await page.waitForURL(/\/onboarded\/projects\/[\w-]+\/surveys/); +} diff --git a/apps/frontend/tests/utils/constants.ts b/apps/frontend/tests/utils/constants.ts new file mode 100644 index 00000000..90731adc --- /dev/null +++ b/apps/frontend/tests/utils/constants.ts @@ -0,0 +1,3 @@ +export const NEW_USER_FILE = "playwright/.auth/newUser.json"; +export const ONBOARDED_USER_FILE = "playwright/.auth/onboardedUser.json"; +export const NON_ONBOARDED_USER_FILE = "playwright/.auth/nonOnboardedUser.json"; diff --git a/apps/frontend/tests/workspace/create-workspace.spec.ts b/apps/frontend/tests/workspace/create-workspace.spec.ts new file mode 100644 index 00000000..0a70ffb2 --- /dev/null +++ b/apps/frontend/tests/workspace/create-workspace.spec.ts @@ -0,0 +1,10 @@ +import { test } from "@playwright/test"; +import { ONBOARDED_USER_FILE } from "../utils/constants"; + +test.describe("Create workspace", () => { + test.use({ storageState: ONBOARDED_USER_FILE }); + + test("should allow new user to create a new workspace", async ({ page }) => { + await page.goto("/create-workspace"); + }); +}); diff --git a/apps/frontend/tests/workspace/manage-workspace.spec.ts b/apps/frontend/tests/workspace/manage-workspace.spec.ts new file mode 100644 index 00000000..e69de29b From 776ecbf8346127749cc28dbc5c5cc46d27d63ebd Mon Sep 17 00:00:00 2001 From: afolasope Date: Fri, 16 Aug 2024 19:00:16 +0100 Subject: [PATCH 02/15] update workflow --- .github/workflows/playwright.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index a214e3f5..78ebbd73 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -44,7 +44,8 @@ jobs: working-directory: apps/frontend - name: Run Playwright tests - run: yarn test-e2e + working-directory: apps/frontend + run: yarn playwright test - uses: actions/upload-artifact@v4 if: always() From 750805c9895f1c28dedae3738a22af8c1dd00d56 Mon Sep 17 00:00:00 2001 From: afolasope Date: Mon, 19 Aug 2024 01:00:02 +0100 Subject: [PATCH 03/15] update auth test --- apps/frontend/tests/auth.setup.ts | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/apps/frontend/tests/auth.setup.ts b/apps/frontend/tests/auth.setup.ts index d24f7f1c..1da1ea7a 100644 --- a/apps/frontend/tests/auth.setup.ts +++ b/apps/frontend/tests/auth.setup.ts @@ -31,11 +31,16 @@ setup("authenticate as onboarded user", async ({ page }) => { await authenticateUser(page, "onboarded@example.com", ONBOARDED_USER_FILE); // Wait for the navigation to complete to one of the expected URLs - await page.waitForURL((url) => { - return ( - onboardingUrl.test(url.pathname) || url.pathname === createWorkspaceUrl || surveyListUrl.test(url.pathname) - ); - }); + await page.waitForURL( + (url) => { + return ( + onboardingUrl.test(url.pathname) || + url.pathname === createWorkspaceUrl || + surveyListUrl.test(url.pathname) + ); + }, + { waitUntil: "load" }, + ); const currentUrl = page.url(); @@ -60,10 +65,12 @@ setup("authenticate as onboarded user", async ({ page }) => { setup("authenticate as non onboarded user", async ({ page }) => { await authenticateUser(page, "test2@example.com", NON_ONBOARDED_USER_FILE); - // Wait for the navigation to either create workspace or existing workspace - await page.waitForURL((url) => { - return onboardingUrl.test(url.pathname) || url.pathname === createWorkspaceUrl; - }); + await page.waitForURL( + (url) => { + return onboardingUrl.test(url.pathname) || url.pathname === createWorkspaceUrl; + }, + { waitUntil: "load" }, + ); const currentUrl = page.url(); From 3a9bda1b0d7e46e35ce4ad0599b757380ce0602c Mon Sep 17 00:00:00 2001 From: afolasope Date: Mon, 19 Aug 2024 01:55:07 +0100 Subject: [PATCH 04/15] update auth test --- .github/workflows/playwright.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 78ebbd73..0733d384 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -32,6 +32,8 @@ jobs: - name: Build dashboard run: yarn build:dashboard + env: + - VITE_SERVER_BASE_URL: http://localhost:8000 - name: Start Backend Server run: docker compose -f ./docker-compose-test.yml up -d From 4c64e3b5b0b1bea1a919b79810876922a066ebbb Mon Sep 17 00:00:00 2001 From: afolasope Date: Mon, 19 Aug 2024 02:00:02 +0100 Subject: [PATCH 05/15] update auth test --- .github/workflows/playwright.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 0733d384..ee249983 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -33,7 +33,7 @@ jobs: - name: Build dashboard run: yarn build:dashboard env: - - VITE_SERVER_BASE_URL: http://localhost:8000 + VITE_SERVER_BASE_URL: http://localhost:8000 - name: Start Backend Server run: docker compose -f ./docker-compose-test.yml up -d From b4067849bb891837188f61221e1062fe30ba7331 Mon Sep 17 00:00:00 2001 From: afolasope Date: Mon, 19 Aug 2024 13:49:34 +0100 Subject: [PATCH 06/15] update auth test --- .github/workflows/playwright.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index ee249983..a214e3f5 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -32,8 +32,6 @@ jobs: - name: Build dashboard run: yarn build:dashboard - env: - VITE_SERVER_BASE_URL: http://localhost:8000 - name: Start Backend Server run: docker compose -f ./docker-compose-test.yml up -d @@ -46,8 +44,7 @@ jobs: working-directory: apps/frontend - name: Run Playwright tests - working-directory: apps/frontend - run: yarn playwright test + run: yarn test-e2e - uses: actions/upload-artifact@v4 if: always() From 27ba6d71c697b1b25b9a7e294975f0da81832f55 Mon Sep 17 00:00:00 2001 From: afolasope Date: Mon, 19 Aug 2024 14:44:21 +0100 Subject: [PATCH 07/15] update auth test --- apps/frontend/tests/auth.setup.ts | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/apps/frontend/tests/auth.setup.ts b/apps/frontend/tests/auth.setup.ts index 1da1ea7a..514e91dc 100644 --- a/apps/frontend/tests/auth.setup.ts +++ b/apps/frontend/tests/auth.setup.ts @@ -31,16 +31,11 @@ setup("authenticate as onboarded user", async ({ page }) => { await authenticateUser(page, "onboarded@example.com", ONBOARDED_USER_FILE); // Wait for the navigation to complete to one of the expected URLs - await page.waitForURL( - (url) => { - return ( - onboardingUrl.test(url.pathname) || - url.pathname === createWorkspaceUrl || - surveyListUrl.test(url.pathname) - ); - }, - { waitUntil: "load" }, - ); + await page.waitForURL((url) => { + return ( + onboardingUrl.test(url.pathname) || url.pathname === createWorkspaceUrl || surveyListUrl.test(url.pathname) + ); + }); const currentUrl = page.url(); @@ -65,12 +60,9 @@ setup("authenticate as onboarded user", async ({ page }) => { setup("authenticate as non onboarded user", async ({ page }) => { await authenticateUser(page, "test2@example.com", NON_ONBOARDED_USER_FILE); - await page.waitForURL( - (url) => { - return onboardingUrl.test(url.pathname) || url.pathname === createWorkspaceUrl; - }, - { waitUntil: "load" }, - ); + await page.waitForURL((url) => { + return onboardingUrl.test(url.pathname) || url.pathname === createWorkspaceUrl; + }); const currentUrl = page.url(); From bf17ab5c01fc21ade0e0916402587057ca5934db Mon Sep 17 00:00:00 2001 From: afolasope Date: Mon, 19 Aug 2024 15:28:34 +0100 Subject: [PATCH 08/15] update auth test --- .github/workflows/playwright.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index a214e3f5..ee249983 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -32,6 +32,8 @@ jobs: - name: Build dashboard run: yarn build:dashboard + env: + VITE_SERVER_BASE_URL: http://localhost:8000 - name: Start Backend Server run: docker compose -f ./docker-compose-test.yml up -d @@ -44,7 +46,8 @@ jobs: working-directory: apps/frontend - name: Run Playwright tests - run: yarn test-e2e + working-directory: apps/frontend + run: yarn playwright test - uses: actions/upload-artifact@v4 if: always() From 0258684326e234fa9f094fad750a4ea2e386a852 Mon Sep 17 00:00:00 2001 From: afolasope Date: Mon, 19 Aug 2024 15:49:50 +0100 Subject: [PATCH 09/15] update auth test --- .github/workflows/playwright.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index ee249983..8b9dd2ad 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -46,8 +46,7 @@ jobs: working-directory: apps/frontend - name: Run Playwright tests - working-directory: apps/frontend - run: yarn playwright test + run: yarn test-e2e - uses: actions/upload-artifact@v4 if: always() From 7df43506460ab0408e2a068c394e978be4b71a76 Mon Sep 17 00:00:00 2001 From: afolasope Date: Wed, 18 Sep 2024 16:20:13 +0100 Subject: [PATCH 10/15] update auth test --- apps/frontend/playwright.config.ts | 13 ++-- apps/frontend/tests/auth.setup.ts | 99 ++++++++++++++++++-------- apps/frontend/tests/example.spec.ts | 8 --- apps/frontend/tests/utils/constants.ts | 21 ++++++ 4 files changed, 96 insertions(+), 45 deletions(-) delete mode 100644 apps/frontend/tests/example.spec.ts diff --git a/apps/frontend/playwright.config.ts b/apps/frontend/playwright.config.ts index dfe125f6..6a4663f4 100644 --- a/apps/frontend/playwright.config.ts +++ b/apps/frontend/playwright.config.ts @@ -1,4 +1,5 @@ import { defineConfig, devices } from "@playwright/test"; +import { ONBOARDED_USER_FILE } from "./tests/utils/constants"; /** * Read environment variables from file. @@ -12,14 +13,14 @@ import { defineConfig, devices } from "@playwright/test"; */ export default defineConfig({ testDir: "./tests", + timeout: 90000, /* Run tests in files in parallel */ fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: process.env.CI ? 2 : 0, + retries: 3, /* Opt out of parallel tests on CI. */ - workers: process.env.CI ? 1 : undefined, + workers: process.env.CI ? undefined : "80%", /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: "html", /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ @@ -37,19 +38,19 @@ export default defineConfig({ { name: "chromium", - use: { ...devices["Desktop Chrome"] }, + use: { ...devices["Desktop Chrome"], storageState: ONBOARDED_USER_FILE }, dependencies: ["setup"], }, { name: "firefox", - use: { ...devices["Desktop Firefox"] }, + use: { ...devices["Desktop Firefox"], storageState: ONBOARDED_USER_FILE }, dependencies: ["setup"], }, { name: "webkit", - use: { ...devices["Desktop Safari"] }, + use: { ...devices["Desktop Safari"], storageState: ONBOARDED_USER_FILE }, dependencies: ["setup"], }, diff --git a/apps/frontend/tests/auth.setup.ts b/apps/frontend/tests/auth.setup.ts index 514e91dc..bf17983d 100644 --- a/apps/frontend/tests/auth.setup.ts +++ b/apps/frontend/tests/auth.setup.ts @@ -1,13 +1,17 @@ +import { faker } from "@faker-js/faker"; import { expect, Page, test as setup } from "@playwright/test"; -import { NEW_USER_FILE, NON_ONBOARDED_USER_FILE, ONBOARDED_USER_FILE } from "./utils/constants"; +import fs from "fs"; +import { + NEW_USER_FILE, + NON_ONBOARDED_USER_FILE, + ONBOARDED_USER_FILE, + ROUTES, + userDetailsFile, +} from "./utils/constants"; const e2eTestToken = "e2e_test_token"; -const createWorkspaceUrl = "/create-workspace"; -const onboardingUrl = /\/[\w-]+\/projects\/[\w-]+\/get-started/; -const surveyListUrl = /\/onboarded\/projects\/[\w-]+\/surveys/; - -async function authenticateUser(page: Page, email: string, stateFile: string) { +async function authenticateUser(page: Page, email: string) { await page.goto("/"); await page.getByPlaceholder("Enter your email").fill(email); await page.getByRole("button", { name: /Continue with email/i }).click(); @@ -15,71 +19,104 @@ async function authenticateUser(page: Page, email: string, stateFile: string) { await page.getByRole("button", { name: /enter code manually/i }).click(); await page.fill('input[name="code"]', e2eTestToken); await page.getByRole("button", { name: /continue/i }).click(); - - await page.context().storageState({ path: stateFile }); + await page.waitForURL((url) => { + return ( + ROUTES.PATTERNS.ONBOARDING_URL.test(url.pathname) || + url.pathname === ROUTES.WORKSPACE.CREATE || + ROUTES.PATTERNS.SURVEY_LIST_URL.test(url.pathname) + ); + }); } setup("authenticate as new user", async ({ page }) => { - await authenticateUser(page, "new-user@example.com", NEW_USER_FILE); + await authenticateUser(page, "new-user@example.com"); await page.waitForURL("/create-workspace"); await expect(page).toHaveURL("/create-workspace"); await expect(page.locator("h3")).toContainText("Create a new workspace"); + + await page.context().storageState({ path: NEW_USER_FILE }); }); setup("authenticate as onboarded user", async ({ page }) => { - await authenticateUser(page, "onboarded@example.com", ONBOARDED_USER_FILE); + await authenticateUser(page, "onboarded22@example.com"); - // Wait for the navigation to complete to one of the expected URLs await page.waitForURL((url) => { return ( - onboardingUrl.test(url.pathname) || url.pathname === createWorkspaceUrl || surveyListUrl.test(url.pathname) + ROUTES.PATTERNS.ONBOARDING_URL.test(url.pathname) || + url.pathname === ROUTES.WORKSPACE.CREATE || + ROUTES.PATTERNS.SURVEY_LIST_URL.test(url.pathname) ); }); const currentUrl = page.url(); - if (currentUrl.includes(createWorkspaceUrl)) { - await expect(page).toHaveURL(createWorkspaceUrl); + if (currentUrl.includes(ROUTES.WORKSPACE.CREATE)) { + await expect(page).toHaveURL(ROUTES.WORKSPACE.CREATE); await expect(page.locator("h3")).toContainText("Create a new workspace"); - await page.locator('[name="workspaceName"]').fill("onboarded"); - await page.locator('[name="workspaceUrl"]').fill("onboarded"); + await page.locator('[name="workspaceName"]').fill("onboarded22"); + await page.locator('[name="workspaceUrl"]').fill("onboarded22"); await page.getByRole("button", { name: /Create Workspace/i }).click(); - await page.waitForURL(onboardingUrl); - await expect(page).toHaveURL(onboardingUrl); + await page.waitForURL(ROUTES.PATTERNS.ONBOARDING_URL); + await expect(page).toHaveURL(ROUTES.PATTERNS.ONBOARDING_URL); await handleOnboardingSteps(page); - } else if (surveyListUrl.test(currentUrl)) { - await expect(page).toHaveURL(surveyListUrl); + + await expect(page).toHaveURL(ROUTES.PATTERNS.SURVEY_LIST_URL); + await expect(page.getByRole("button", { name: /Create new survey/i }).last()).toBeVisible(); + + const url = new URL(page.url()); + + const workspaceSlug = url.pathname.split("/")[1]; + const projectSlug = url.pathname.split("/")[3]; + const details = { workspaceSlug, projectSlug }; + + fs.writeFileSync(userDetailsFile, JSON.stringify(details), "utf-8"); + await page.context().storageState({ path: ONBOARDED_USER_FILE }); + } else if (ROUTES.PATTERNS.SURVEY_LIST_URL.test(currentUrl)) { + await expect(page).toHaveURL(ROUTES.PATTERNS.SURVEY_LIST_URL); + await expect(page.getByRole("button", { name: /Create new survey/i }).last()).toBeVisible(); + + const url = new URL(page.url()); + + const workspaceSlug = url.pathname.split("/")[1]; + const projectSlug = url.pathname.split("/")[3]; + const details = { workspaceSlug, projectSlug }; + + fs.writeFileSync(userDetailsFile, JSON.stringify(details), "utf-8"); + await page.context().storageState({ path: ONBOARDED_USER_FILE }); } else { throw new Error(`Unexpected URL: ${currentUrl}`); } }); setup("authenticate as non onboarded user", async ({ page }) => { - await authenticateUser(page, "test2@example.com", NON_ONBOARDED_USER_FILE); + await authenticateUser(page, "test2@example.com"); await page.waitForURL((url) => { - return onboardingUrl.test(url.pathname) || url.pathname === createWorkspaceUrl; + return ROUTES.PATTERNS.ONBOARDING_URL.test(url.pathname) || url.pathname === ROUTES.WORKSPACE.CREATE; }); const currentUrl = page.url(); - if (currentUrl.includes(createWorkspaceUrl)) { - await expect(page).toHaveURL(createWorkspaceUrl); + if (currentUrl.includes(ROUTES.WORKSPACE.CREATE)) { + await expect(page).toHaveURL(ROUTES.WORKSPACE.CREATE); await expect(page.locator("h3")).toContainText("Create a new workspace"); - await page.locator('[name="workspaceName"]').fill("test2"); - await page.locator('[name="workspaceUrl"]').fill("test2"); + await page.locator('[name="workspaceName"]').fill(faker.word.words(2)); + await page.locator('[name="workspaceUrl"]').fill(`${faker.word.words(1)}-${faker.word.words(1)}`); await page.getByRole("button", { name: /Create Workspace/i }).click(); - await page.waitForURL(onboardingUrl); - await expect(page).toHaveURL(onboardingUrl); + await page.waitForURL((url) => ROUTES.PATTERNS.ONBOARDING_URL.test(url.pathname)); + await expect(page).toHaveURL(ROUTES.PATTERNS.ONBOARDING_URL); + await expect(page.locator("h1").nth(0)).toContainText("Getting started"); - } else if (onboardingUrl.test(currentUrl)) { - await expect(page).toHaveURL(onboardingUrl); + await page.context().storageState({ path: NON_ONBOARDED_USER_FILE }); + } else if (ROUTES.PATTERNS.ONBOARDING_URL.test(currentUrl)) { + await expect(page).toHaveURL(ROUTES.PATTERNS.ONBOARDING_URL); await expect(page.locator("h1").nth(0)).toContainText("Getting started"); + await page.context().storageState({ path: NON_ONBOARDED_USER_FILE }); } else { throw new Error(`Unexpected URL: ${currentUrl}`); } @@ -101,5 +138,5 @@ async function handleOnboardingSteps(page: Page) { await page.getByRole("button", { name: /skip/i }).click(); } - await page.waitForURL(/\/onboarded\/projects\/[\w-]+\/surveys/); + await page.waitForURL((url) => ROUTES.PATTERNS.SURVEY_LIST_URL.test(url.pathname)); } diff --git a/apps/frontend/tests/example.spec.ts b/apps/frontend/tests/example.spec.ts deleted file mode 100644 index 9aa7c6f8..00000000 --- a/apps/frontend/tests/example.spec.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { expect, test } from "@playwright/test"; - -test("has title", async ({ page }) => { - await page.goto("/"); - - // Expect a title "to contain" a substring. - await expect(page).toHaveTitle(/Integraflow/); -}); diff --git a/apps/frontend/tests/utils/constants.ts b/apps/frontend/tests/utils/constants.ts index 90731adc..8fca71e7 100644 --- a/apps/frontend/tests/utils/constants.ts +++ b/apps/frontend/tests/utils/constants.ts @@ -1,3 +1,24 @@ export const NEW_USER_FILE = "playwright/.auth/newUser.json"; export const ONBOARDED_USER_FILE = "playwright/.auth/onboardedUser.json"; export const NON_ONBOARDED_USER_FILE = "playwright/.auth/nonOnboardedUser.json"; +export const userDetailsFile = "playwright/.auth/userDetails.json"; + +export const ROUTES = { + WORKSPACE: { + CREATE: "/create-workspace", + ONBOARDING: (workspaceSlug: string, projectSlug: string) => + `/${workspaceSlug}/projects/${projectSlug}/get-started`, + }, + + SURVEY: { + LIST: (workspaceSlug: string, projectSlug: string) => `/${workspaceSlug}/projects/${projectSlug}/surveys`, + SINGLE: (workspaceSlug: string, projectSlug: string, surveySlug: string) => + `/${workspaceSlug}/projects/${projectSlug}/survey/${surveySlug}`, + }, + + PATTERNS: { + ONBOARDING_URL: /\/[\w-]+\/projects\/[\w-]+\/get-started/, + SURVEY_LIST_URL: /\/[\w-]+\/projects\/[\w-]+\/surveys/, + SINGLE_SURVEY: /\/[\w-]+\/projects\/[\w-]+\/survey\/[\w-]+/, + }, +}; From 26054346f2e0d10cbce9818d601dedcc218fc2a1 Mon Sep 17 00:00:00 2001 From: afolasope Date: Wed, 18 Sep 2024 16:35:23 +0100 Subject: [PATCH 11/15] update auth tests --- apps/frontend/package.json | 1 + yarn.lock | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 93317f01..5e312657 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -60,6 +60,7 @@ "zustand": "^4.4.5" }, "devDependencies": { + "@faker-js/faker": "^9.0.1", "@graphql-codegen/cli": "^3.3.1", "@graphql-codegen/client-preset": "^4.1.0", "@graphql-codegen/typescript": "^3.0.4", diff --git a/yarn.lock b/yarn.lock index 1f387ce7..3459a710 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1732,6 +1732,11 @@ dependencies: "@f/map-obj" "^1.2.2" +"@faker-js/faker@^9.0.1": + version "9.0.1" + resolved "https://registry.yarnpkg.com/@faker-js/faker/-/faker-9.0.1.tgz#5e201ffc4524d00a200c648d2be55be6e25b3c3e" + integrity sha512-4mDeYIgM3By7X6t5E6eYwLAa+2h4DeZDF7thhzIg6XB76jeEvMwadYAMCFJL/R4AnEBcAUO9+gL0vhy3s+qvZA== + "@floating-ui/core@^1.0.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.0.tgz#fa41b87812a16bf123122bf945946bae3fdf7fc1" From ee8521547eb1ba11111c9b652718991f4d92701b Mon Sep 17 00:00:00 2001 From: afolasope Date: Wed, 18 Sep 2024 16:58:10 +0100 Subject: [PATCH 12/15] update auth tests --- apps/frontend/playwright.config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/frontend/playwright.config.ts b/apps/frontend/playwright.config.ts index 6a4663f4..69298e40 100644 --- a/apps/frontend/playwright.config.ts +++ b/apps/frontend/playwright.config.ts @@ -18,6 +18,7 @@ export default defineConfig({ fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ forbidOnly: !!process.env.CI, + retries: 3, /* Opt out of parallel tests on CI. */ workers: process.env.CI ? undefined : "80%", From 4fe686e70dd0dcfabad081b5d86a4f0d98e35bb0 Mon Sep 17 00:00:00 2001 From: afolasope Date: Fri, 20 Sep 2024 14:40:47 +0100 Subject: [PATCH 13/15] update auth test --- apps/frontend/src/layout/partials/Navbar.tsx | 1 + .../src/layout/partials/UserProfile.tsx | 11 ++- apps/frontend/tests/{ => auth}/auth.setup.ts | 75 ++++--------------- apps/frontend/tests/auth/logout.spec.ts | 46 ++++++++++++ apps/frontend/tests/types/index.ts | 4 + apps/frontend/tests/utils/constants.ts | 8 ++ apps/frontend/tests/utils/helper.ts | 63 ++++++++++++++++ 7 files changed, 147 insertions(+), 61 deletions(-) rename apps/frontend/tests/{ => auth}/auth.setup.ts (51%) create mode 100644 apps/frontend/tests/auth/logout.spec.ts create mode 100644 apps/frontend/tests/types/index.ts create mode 100644 apps/frontend/tests/utils/helper.ts diff --git a/apps/frontend/src/layout/partials/Navbar.tsx b/apps/frontend/src/layout/partials/Navbar.tsx index 20ee6bea..e68e8b29 100644 --- a/apps/frontend/src/layout/partials/Navbar.tsx +++ b/apps/frontend/src/layout/partials/Navbar.tsx @@ -165,6 +165,7 @@ export const Navbar = () => {