From 2d6ad58d7850238aad8a1c8d07c66b58ab837bc2 Mon Sep 17 00:00:00 2001 From: afolasope Date: Fri, 16 Aug 2024 15:16:51 +0100 Subject: [PATCH 01/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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/49] 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 3107b975cf3cefbbde5ecd2818e7bd016e36b084 Mon Sep 17 00:00:00 2001 From: afolasope Date: Wed, 21 Aug 2024 11:01:40 +0100 Subject: [PATCH 10/49] create test for workspace --- apps/frontend/package.json | 1 + apps/frontend/playwright.config.ts | 9 ++-- apps/frontend/tests/auth.setup.ts | 51 +++++++++++-------- apps/frontend/tests/utils/constants.ts | 6 +++ .../tests/workspace/create-workspace.spec.ts | 49 ++++++++++++++++-- 5 files changed, 85 insertions(+), 31 deletions(-) diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 93317f01..8317d54b 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -60,6 +60,7 @@ "zustand": "^4.4.5" }, "devDependencies": { + "@faker-js/faker": "^8.4.1", "@graphql-codegen/cli": "^3.3.1", "@graphql-codegen/client-preset": "^4.1.0", "@graphql-codegen/typescript": "^3.0.4", diff --git a/apps/frontend/playwright.config.ts b/apps/frontend/playwright.config.ts index dfe125f6..09c06649 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. @@ -19,7 +20,7 @@ export default defineConfig({ /* Retry on CI only */ retries: process.env.CI ? 2 : 0, /* Opt out of parallel tests on CI. */ - workers: process.env.CI ? 1 : undefined, + workers: process.env.CI ? 2 : undefined, /* 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..dba45f08 100644 --- a/apps/frontend/tests/auth.setup.ts +++ b/apps/frontend/tests/auth.setup.ts @@ -1,12 +1,9 @@ +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 { NEW_USER_FILE, NON_ONBOARDED_USER_FILE, ONBOARDED_USER_FILE, ROUTES } 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); @@ -15,7 +12,13 @@ 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.waitForURL((url) => { + return ( + ROUTES.ONBOARDING_URL.test(url.pathname) || + url.pathname === ROUTES.CREATE_WORKSPACE_URL || + ROUTES.SURVEY_LIST_URL.test(url.pathname) + ); + }); await page.context().storageState({ path: stateFile }); } @@ -33,25 +36,29 @@ setup("authenticate as onboarded user", async ({ page }) => { // 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.ONBOARDING_URL.test(url.pathname) || + url.pathname === ROUTES.CREATE_WORKSPACE_URL || + ROUTES.SURVEY_LIST_URL.test(url.pathname) ); }); const currentUrl = page.url(); - if (currentUrl.includes(createWorkspaceUrl)) { - await expect(page).toHaveURL(createWorkspaceUrl); + if (currentUrl.includes(ROUTES.CREATE_WORKSPACE_URL)) { + await expect(page).toHaveURL(ROUTES.CREATE_WORKSPACE_URL); 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 page.waitForURL(ROUTES.ONBOARDING_URL); + await expect(page).toHaveURL(ROUTES.ONBOARDING_URL); await handleOnboardingSteps(page); - } else if (surveyListUrl.test(currentUrl)) { - await expect(page).toHaveURL(surveyListUrl); + } else if (ROUTES.SURVEY_LIST_URL.test(currentUrl)) { + console.log("survey list"); + await expect(page).toHaveURL(ROUTES.SURVEY_LIST_URL); + await expect(page.locator("h1").nth(0)).toContainText(/Create your first survey/i); } else { throw new Error(`Unexpected URL: ${currentUrl}`); } @@ -61,24 +68,24 @@ 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; + return ROUTES.ONBOARDING_URL.test(url.pathname) || url.pathname === ROUTES.CREATE_WORKSPACE_URL; }); const currentUrl = page.url(); - if (currentUrl.includes(createWorkspaceUrl)) { - await expect(page).toHaveURL(createWorkspaceUrl); + if (currentUrl.includes(ROUTES.CREATE_WORKSPACE_URL)) { + await expect(page).toHaveURL(ROUTES.CREATE_WORKSPACE_URL); 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(ROUTES.ONBOARDING_URL); + await expect(page).toHaveURL(ROUTES.ONBOARDING_URL); await expect(page.locator("h1").nth(0)).toContainText("Getting started"); - } else if (onboardingUrl.test(currentUrl)) { - await expect(page).toHaveURL(onboardingUrl); + } else if (ROUTES.ONBOARDING_URL.test(currentUrl)) { + await expect(page).toHaveURL(ROUTES.ONBOARDING_URL); await expect(page.locator("h1").nth(0)).toContainText("Getting started"); } else { throw new Error(`Unexpected URL: ${currentUrl}`); diff --git a/apps/frontend/tests/utils/constants.ts b/apps/frontend/tests/utils/constants.ts index 90731adc..baf85ed8 100644 --- a/apps/frontend/tests/utils/constants.ts +++ b/apps/frontend/tests/utils/constants.ts @@ -1,3 +1,9 @@ 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 ROUTES = { + CREATE_WORKSPACE_URL: "/create-workspace", + ONBOARDING_URL: /\/[\w-]+\/projects\/[\w-]+\/get-started/, + SURVEY_LIST_URL: /\/[\w-]+\/projects\/[\w-]+\/surveys/, +}; diff --git a/apps/frontend/tests/workspace/create-workspace.spec.ts b/apps/frontend/tests/workspace/create-workspace.spec.ts index 0a70ffb2..883c6492 100644 --- a/apps/frontend/tests/workspace/create-workspace.spec.ts +++ b/apps/frontend/tests/workspace/create-workspace.spec.ts @@ -1,10 +1,49 @@ -import { test } from "@playwright/test"; -import { ONBOARDED_USER_FILE } from "../utils/constants"; +import { faker } from "@faker-js/faker"; +import { expect, test } from "@playwright/test"; +import { ROUTES } from "../utils/constants"; + +const word1 = faker.word.words(1); +const word2 = faker.word.words(1); +const workspaceUrl = `${word1}-${word2}`; test.describe("Create workspace", () => { - test.use({ storageState: ONBOARDED_USER_FILE }); + test.beforeEach(async ({ page }) => { + await page.goto(ROUTES.CREATE_WORKSPACE_URL); + await page.waitForSelector("h3"); + await expect(page.locator("h3")).toContainText("Create a new workspace"); + }); + // test.use({ storageState: NON_ONBOARDED_USER_FILE }); + + test("should allow user to create a new workspace", async ({ page }) => { + await page.locator('[name="workspaceName"]').fill(faker.word.words(2)); + // await page.locator('[name="workspaceUrl"]').fill(faker.word.words(2)); + await page.getByRole("button", { name: /Create Workspace/i }).click(); + + await page.waitForURL((url) => { + return ROUTES.SURVEY_LIST_URL.test(url.pathname); + }); + + await expect(page.locator("h1").nth(0)).toContainText(/Create your first survey/i); + }); + + test("should allow specifying workspace URL", async ({ page }) => { + await page.locator('[name="workspaceName"]').fill(faker.word.words(2)); + await page.locator('[name="workspaceUrl"]').fill(workspaceUrl); + + await page.getByRole("button", { name: /Create Workspace/i }).click(); + + await page.waitForURL((url) => { + return ROUTES.SURVEY_LIST_URL.test(url.pathname); + }); + + await expect(page.locator("h1").nth(0)).toContainText(/Create your first survey/i); + }); + + test("should not allow repeating workspace URL", async ({ page }) => { + await page.locator('[name="workspaceName"]').fill(faker.word.words(2)); + await page.locator('[name="workspaceUrl"]').fill(workspaceUrl); + await page.getByRole("button", { name: /Create Workspace/i }).click(); - test("should allow new user to create a new workspace", async ({ page }) => { - await page.goto("/create-workspace"); + await expect(page.locator(".tremor-TextInput-errorMessage")).toBeVisible(); }); }); From fc0e9c01aced4bb278b483e29cf09b3d7b22f1a6 Mon Sep 17 00:00:00 2001 From: afolasope Date: Wed, 21 Aug 2024 14:26:30 +0100 Subject: [PATCH 11/49] update workspace test --- apps/frontend/playwright.config.ts | 2 +- apps/frontend/tests/workspace/create-workspace.spec.ts | 8 +++----- yarn.lock | 5 +++++ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/frontend/playwright.config.ts b/apps/frontend/playwright.config.ts index 09c06649..fb183422 100644 --- a/apps/frontend/playwright.config.ts +++ b/apps/frontend/playwright.config.ts @@ -20,7 +20,7 @@ export default defineConfig({ /* Retry on CI only */ retries: process.env.CI ? 2 : 0, /* Opt out of parallel tests on CI. */ - workers: process.env.CI ? 2 : undefined, + workers: undefined, /* 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. */ diff --git a/apps/frontend/tests/workspace/create-workspace.spec.ts b/apps/frontend/tests/workspace/create-workspace.spec.ts index 883c6492..dd3638df 100644 --- a/apps/frontend/tests/workspace/create-workspace.spec.ts +++ b/apps/frontend/tests/workspace/create-workspace.spec.ts @@ -12,11 +12,9 @@ test.describe("Create workspace", () => { await page.waitForSelector("h3"); await expect(page.locator("h3")).toContainText("Create a new workspace"); }); - // test.use({ storageState: NON_ONBOARDED_USER_FILE }); test("should allow user to create a new workspace", async ({ page }) => { await page.locator('[name="workspaceName"]').fill(faker.word.words(2)); - // await page.locator('[name="workspaceUrl"]').fill(faker.word.words(2)); await page.getByRole("button", { name: /Create Workspace/i }).click(); await page.waitForURL((url) => { @@ -26,7 +24,7 @@ test.describe("Create workspace", () => { await expect(page.locator("h1").nth(0)).toContainText(/Create your first survey/i); }); - test("should allow specifying workspace URL", async ({ page }) => { + test("should not allow repeating workspace URL", async ({ page }) => { await page.locator('[name="workspaceName"]').fill(faker.word.words(2)); await page.locator('[name="workspaceUrl"]').fill(workspaceUrl); @@ -37,9 +35,9 @@ test.describe("Create workspace", () => { }); await expect(page.locator("h1").nth(0)).toContainText(/Create your first survey/i); - }); - test("should not allow repeating workspace URL", async ({ page }) => { + await page.goto(ROUTES.CREATE_WORKSPACE_URL); + await page.waitForSelector("h3"); await page.locator('[name="workspaceName"]').fill(faker.word.words(2)); await page.locator('[name="workspaceUrl"]').fill(workspaceUrl); await page.getByRole("button", { name: /Create Workspace/i }).click(); diff --git a/yarn.lock b/yarn.lock index 1f387ce7..74932664 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1732,6 +1732,11 @@ dependencies: "@f/map-obj" "^1.2.2" +"@faker-js/faker@^8.4.1": + version "8.4.1" + resolved "https://registry.yarnpkg.com/@faker-js/faker/-/faker-8.4.1.tgz#5d5e8aee8fce48f5e189bf730ebd1f758f491451" + integrity sha512-XQ3cU+Q8Uqmrbf2e0cIC/QN43sTBSC8KF12u29Mb47tWrt2hAgBXSgpZMj4Ao8Uk0iJcU99QsOCaIL8934obCg== + "@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 353c326d4b340fad0123223d9874c9a64249ba51 Mon Sep 17 00:00:00 2001 From: afolasope Date: Wed, 21 Aug 2024 14:44:00 +0100 Subject: [PATCH 12/49] update create workspace test --- apps/frontend/playwright.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/frontend/playwright.config.ts b/apps/frontend/playwright.config.ts index fb183422..97f1c330 100644 --- a/apps/frontend/playwright.config.ts +++ b/apps/frontend/playwright.config.ts @@ -20,7 +20,7 @@ export default defineConfig({ /* Retry on CI only */ retries: process.env.CI ? 2 : 0, /* Opt out of parallel tests on CI. */ - workers: undefined, + workers: "100%", /* 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. */ From 82864ab5891275f5b37953cfa59dec49b2ae72a4 Mon Sep 17 00:00:00 2001 From: afolasope Date: Wed, 21 Aug 2024 15:01:16 +0100 Subject: [PATCH 13/49] update workspace test --- apps/frontend/playwright.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/frontend/playwright.config.ts b/apps/frontend/playwright.config.ts index 97f1c330..242df480 100644 --- a/apps/frontend/playwright.config.ts +++ b/apps/frontend/playwright.config.ts @@ -20,7 +20,7 @@ export default defineConfig({ /* Retry on CI only */ retries: process.env.CI ? 2 : 0, /* Opt out of parallel tests on CI. */ - workers: "100%", + workers: process.env.CI ? "100%" : undefined, /* 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. */ From 06b57cb1fccc2804012133f4590a318bc6d7b57b Mon Sep 17 00:00:00 2001 From: afolasope Date: Wed, 21 Aug 2024 15:26:14 +0100 Subject: [PATCH 14/49] update auth layout --- .github/workflows/playwright.yml | 2 -- apps/frontend/src/layout/AuthLayout.tsx | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 8b9dd2ad..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 diff --git a/apps/frontend/src/layout/AuthLayout.tsx b/apps/frontend/src/layout/AuthLayout.tsx index e7ebd192..f54e23aa 100644 --- a/apps/frontend/src/layout/AuthLayout.tsx +++ b/apps/frontend/src/layout/AuthLayout.tsx @@ -6,7 +6,7 @@ import Profile2 from "../assets/images/loginScreen/profile-2.png"; import Profile3 from "../assets/images/loginScreen/profile-3.png"; import Logo from "../assets/images/logo.png"; -const clientId = import.meta.env.VITE_GOOGLE_CLIENT_ID; +const clientId = import.meta.env.VITE_GOOGLE_CLIENT_ID ?? ""; export function AuthLayout() { return ( From ea3f194e046d49d56b01c500b3a7c5b5d9c1912f Mon Sep 17 00:00:00 2001 From: afolasope Date: Wed, 21 Aug 2024 15:35:36 +0100 Subject: [PATCH 15/49] update config --- apps/frontend/playwright.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/frontend/playwright.config.ts b/apps/frontend/playwright.config.ts index 242df480..eee11751 100644 --- a/apps/frontend/playwright.config.ts +++ b/apps/frontend/playwright.config.ts @@ -20,7 +20,7 @@ export default defineConfig({ /* Retry on CI only */ retries: process.env.CI ? 2 : 0, /* Opt out of parallel tests on CI. */ - workers: process.env.CI ? "100%" : undefined, + workers: process.env.CI ? "75%" : undefined, /* 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. */ From a2c647049439592319991f9a799594473d5b837a Mon Sep 17 00:00:00 2001 From: afolasope Date: Wed, 21 Aug 2024 15:56:54 +0100 Subject: [PATCH 16/49] update action --- .github/workflows/playwright.yml | 6 ++++++ apps/frontend/playwright.config.ts | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index a214e3f5..6f878150 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -32,6 +32,12 @@ jobs: - name: Build dashboard run: yarn build:dashboard + env: + VITE_GOOGLE_CLIENT_ID: ${{ secrets.VITE_GOOGLE_CLIENT_ID }} + VITE_SERVER_BASE_URL: ${{ secrets.VITE_SERVER_BASE_URL }} + VITE_LINK_SURVEY_HOST: ${{ secrets.VITE_LINK_SURVEY_HOST }} + VITE_PUBLIC_POSTHOG_KEY: ${{ secrets.VITE_PUBLIC_POSTHOG_KEY }} + VITE_PUBLIC_POSTHOG_HOST: ${{ secrets.VITE_PUBLIC_POSTHOG_HOST }} - name: Start Backend Server run: docker compose -f ./docker-compose-test.yml up -d diff --git a/apps/frontend/playwright.config.ts b/apps/frontend/playwright.config.ts index eee11751..242df480 100644 --- a/apps/frontend/playwright.config.ts +++ b/apps/frontend/playwright.config.ts @@ -20,7 +20,7 @@ export default defineConfig({ /* Retry on CI only */ retries: process.env.CI ? 2 : 0, /* Opt out of parallel tests on CI. */ - workers: process.env.CI ? "75%" : undefined, + workers: process.env.CI ? "100%" : undefined, /* 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. */ From 18b82d538c27ab907888e485f62633708864b32a Mon Sep 17 00:00:00 2001 From: afolasope Date: Wed, 21 Aug 2024 16:15:49 +0100 Subject: [PATCH 17/49] update config --- apps/frontend/playwright.config.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/frontend/playwright.config.ts b/apps/frontend/playwright.config.ts index 242df480..a1c0f2ec 100644 --- a/apps/frontend/playwright.config.ts +++ b/apps/frontend/playwright.config.ts @@ -19,8 +19,6 @@ export default defineConfig({ forbidOnly: !!process.env.CI, /* Retry on CI only */ retries: process.env.CI ? 2 : 0, - /* Opt out of parallel tests on CI. */ - workers: process.env.CI ? "100%" : undefined, /* 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. */ From ea6ced14a41d9f557ecf316f0364d55111b4bcf8 Mon Sep 17 00:00:00 2001 From: afolasope Date: Wed, 28 Aug 2024 17:05:51 +0100 Subject: [PATCH 18/49] create survey tests --- apps/frontend/playwright.config.ts | 7 +- apps/frontend/tests/auth.setup.ts | 69 ++++++++++++------- .../tests/survey/create-survey.spec.ts | 21 ++++++ apps/frontend/tests/utils/constants.ts | 21 ++++++ .../tests/workspace/create-workspace.spec.ts | 3 - 5 files changed, 91 insertions(+), 30 deletions(-) create mode 100644 apps/frontend/tests/survey/create-survey.spec.ts diff --git a/apps/frontend/playwright.config.ts b/apps/frontend/playwright.config.ts index dfe125f6..a72372ca 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. @@ -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..908569da 100644 --- a/apps/frontend/tests/auth.setup.ts +++ b/apps/frontend/tests/auth.setup.ts @@ -1,12 +1,16 @@ +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) { await page.goto("/"); await page.getByPlaceholder("Enter your email").fill(email); @@ -15,7 +19,13 @@ 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.waitForURL((url) => { + return ( + ROUTES.PATTERNS.ONBOARDING_URL.test(url.pathname) || + url.pathname === ROUTES.WORKSPACE.CREATE || + ROUTES.PATTERNS.SURVEY_LIST_URL.test(url.pathname) + ); + }); await page.context().storageState({ path: stateFile }); } @@ -30,28 +40,38 @@ setup("authenticate as new user", async ({ page }) => { 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) + 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.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); + } 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"); } else { throw new Error(`Unexpected URL: ${currentUrl}`); } @@ -61,24 +81,25 @@ 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; + 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); + } 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"); } else { throw new Error(`Unexpected URL: ${currentUrl}`); @@ -101,5 +122,5 @@ async function handleOnboardingSteps(page: Page) { await page.getByRole("button", { name: /skip/i }).click(); } - await page.waitForURL(/\/onboarded\/projects\/[\w-]+\/surveys/); + await page.waitForURL(/\/[\w-]+\/projects\/[\w-]+\/surveys/); } diff --git a/apps/frontend/tests/survey/create-survey.spec.ts b/apps/frontend/tests/survey/create-survey.spec.ts new file mode 100644 index 00000000..d8e74cd4 --- /dev/null +++ b/apps/frontend/tests/survey/create-survey.spec.ts @@ -0,0 +1,21 @@ +import { expect, test } from "@playwright/test"; +import fs from "fs"; +import { ROUTES, userDetailsFile } from "../utils/constants"; + +test.describe("Create survey", () => { + test("should allow user to create a survey", async ({ page }) => { + const details = JSON.parse(fs.readFileSync(userDetailsFile, "utf-8")); + const workspaceSlug = details.workspaceSlug; + const projectSlug = details.projectSlug; + + await page.goto(ROUTES.SURVEY.LIST(workspaceSlug, projectSlug)); + await expect(page.getByRole("button", { name: /Create new survey/i }).last()).toBeVisible(); + await page + .getByRole("button", { name: /Create new survey/i }) + .last() + .click(); + + await page.waitForURL((url) => ROUTES.PATTERNS.SINGLE_SURVEY.test(url.pathname)); + await expect(page.getByRole("tab", { name: "Create" })).toBeVisible(); + }); +}); diff --git a/apps/frontend/tests/utils/constants.ts b/apps/frontend/tests/utils/constants.ts index 90731adc..5d4e342b 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, surveyId: string) => + `/${workspaceSlug}/projects/${projectSlug}/survey/${surveyId}`, + }, + + PATTERNS: { + ONBOARDING_URL: /\/[\w-]+\/projects\/[\w-]+\/get-started/, + SURVEY_LIST_URL: /\/[\w-]+\/projects\/[\w-]+\/surveys/, + SINGLE_SURVEY: /\/[\w-]+\/projects\/[\w-]+\/survey\/[\w-]+/, + }, +}; diff --git a/apps/frontend/tests/workspace/create-workspace.spec.ts b/apps/frontend/tests/workspace/create-workspace.spec.ts index 0a70ffb2..8209e181 100644 --- a/apps/frontend/tests/workspace/create-workspace.spec.ts +++ b/apps/frontend/tests/workspace/create-workspace.spec.ts @@ -1,9 +1,6 @@ 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"); }); From ed911c9d3da83555c456c60ee59e6d898ca50e56 Mon Sep 17 00:00:00 2001 From: afolasope Date: Thu, 5 Sep 2024 11:44:26 +0100 Subject: [PATCH 19/49] create survey tests --- .../SurveyHome/components/SurveyList.tsx | 4 +- .../editor-panel/questions/LogicTab.tsx | 4 +- .../editor-panel/questions/QuestionPanel.tsx | 13 +- .../questions/attributes/QuestionTypes.tsx | 3 +- .../create/editor-panel/questions/index.tsx | 9 +- apps/frontend/src/ui/Pagination/index.tsx | 3 +- .../tests/survey/create-survey.spec.ts | 21 -- apps/frontend/tests/survey/question.spec.ts | 253 ++++++++++++++++++ apps/frontend/tests/survey/survey.spec.ts | 56 ++++ apps/frontend/tests/utils/constants.ts | 4 +- 10 files changed, 335 insertions(+), 35 deletions(-) delete mode 100644 apps/frontend/tests/survey/create-survey.spec.ts create mode 100644 apps/frontend/tests/survey/question.spec.ts create mode 100644 apps/frontend/tests/survey/survey.spec.ts diff --git a/apps/frontend/src/modules/surveys/components/SurveyHome/components/SurveyList.tsx b/apps/frontend/src/modules/surveys/components/SurveyHome/components/SurveyList.tsx index 5a4c9774..cd1063ea 100644 --- a/apps/frontend/src/modules/surveys/components/SurveyHome/components/SurveyList.tsx +++ b/apps/frontend/src/modules/surveys/components/SurveyHome/components/SurveyList.tsx @@ -152,7 +152,7 @@ export const SurveyList = () => { - + @@ -252,6 +252,7 @@ export const SurveyList = () => { getSurveyNameOnSelect(survey?.id ?? "", event) } className="flex gap-[6px] rounded-md py-[7px] text-sm font-normal text-intg-text-4 transition-all duration-300 ease-in hover:cursor-pointer hover:bg-intg-bg-1 hover:pl-[8px]" + data-testid="delete-survey" > Delete @@ -265,6 +266,7 @@ export const SurveyList = () => { className="w-[500px]" > + diff --git a/apps/frontend/src/modules/surveys/components/studio/create/editor-panel/questions/attributes/QuestionTypes.tsx b/apps/frontend/src/modules/surveys/components/studio/create/editor-panel/questions/attributes/QuestionTypes.tsx index 861f7e66..89467979 100644 --- a/apps/frontend/src/modules/surveys/components/studio/create/editor-panel/questions/attributes/QuestionTypes.tsx +++ b/apps/frontend/src/modules/surveys/components/studio/create/editor-panel/questions/attributes/QuestionTypes.tsx @@ -62,13 +62,14 @@ export const QuestionOptions = () => { return ( setShowQuestionTypes(open)}> - + )} From 0126d514323ae35e32c358f26284d6217b093def Mon Sep 17 00:00:00 2001 From: afolasope Date: Thu, 31 Oct 2024 09:13:29 +0100 Subject: [PATCH 47/49] create logic tests --- .../question/logic/boolean-logic.spec.ts | 70 +++++++++ .../survey/question/logic/form-logic.spec.ts | 85 +++++++++++ .../logic/multiple-answer-logic.spec.ts | 127 +++++++++++++++++ .../question/logic/rating-logic.spec.ts | 134 ++++++++++++++++++ .../survey/question/logic/text-logic.spec.ts | 82 +++++++++++ apps/frontend/tests/utils/helper/index.ts | 13 +- 6 files changed, 508 insertions(+), 3 deletions(-) create mode 100644 apps/frontend/tests/survey/question/logic/boolean-logic.spec.ts create mode 100644 apps/frontend/tests/survey/question/logic/form-logic.spec.ts create mode 100644 apps/frontend/tests/survey/question/logic/multiple-answer-logic.spec.ts create mode 100644 apps/frontend/tests/survey/question/logic/rating-logic.spec.ts create mode 100644 apps/frontend/tests/survey/question/logic/text-logic.spec.ts diff --git a/apps/frontend/tests/survey/question/logic/boolean-logic.spec.ts b/apps/frontend/tests/survey/question/logic/boolean-logic.spec.ts new file mode 100644 index 00000000..9a575f54 --- /dev/null +++ b/apps/frontend/tests/survey/question/logic/boolean-logic.spec.ts @@ -0,0 +1,70 @@ +import test, { expect } from "@playwright/test"; +import { SURVEY_MAKER_FILE } from "../../../utils/constants"; +import { createQuestion, gotoSurvey } from "../../../utils/helper"; +import { setupQuestion } from "../../../utils/helper/questionSetup"; + +test.use({ storageState: SURVEY_MAKER_FILE }); + +test.describe.serial("Edit questions and verify Boolean logic ", () => { + let workspaceSlug: string, projectSlug: string, surveySlug: string; + + test.beforeAll(async ({ browser }) => { + const setup = await setupQuestion(browser); + workspaceSlug = setup.workspaceSlug; + projectSlug = setup.projectSlug; + surveySlug = setup.surveySlug; + }); + + test("should allow users to edit and update question", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + await page.getByTestId("add-question").waitFor(); + + await createQuestion(page, "Welcome message", { label: "Question one" }); //01 + + await createQuestion(page, "Boolean", { label: "Question two" }); //02 + + await createQuestion(page, "Boolean", { label: "Question three" }); //03 + + await createQuestion(page, "Thank you", { label: "Thank you. Question four" }); //04 + }); + test("should allow user to update question logic", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + await page.getByTestId("question-trigger").nth(1).click(); + await page.getByRole("tab", { name: "Logic" }).click(); + await page.getByTestId("add-new-logic").click(); + await page.getByTestId("condition-indicator").click(); + await page.getByRole("option", { name: "is false" }).click(); + await page.getByTestId("destination-indicator").click(); + await page.getByRole("option", { name: "Question four" }).click(); + + await page.getByTestId("add-new-logic").click(); + await page.getByTestId("condition-indicator").click(); + await page.getByRole("option", { name: "is true" }).click(); + await page.getByTestId("destination-indicator").click(); + await page.getByRole("option", { name: "End survey" }).click(); + }); + + test("should verify IS_FALSE logic in the survey preview", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + const iframe = page.frameLocator('iframe[title="Survey preview"]'); + await iframe.getByRole("button", { name: "Submit" }).waitFor(); + + await iframe.getByRole("button", { name: "Submit" }).click(); + await iframe.getByTestId("thumbs-down").click(); + await expect(iframe.getByText("Question four")).toBeVisible(); + }); + + test("should verify IS_TRUE logic in the survey preview", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + const iframe = page.frameLocator('iframe[title="Survey preview"]'); + await iframe.getByRole("button", { name: "Submit" }).waitFor(); + + await iframe.getByRole("button", { name: "Submit" }).click(); + await iframe.getByTestId("thumbs-up").click(); + await expect(iframe.getByText("Question one")).toBeVisible(); + }); +}); diff --git a/apps/frontend/tests/survey/question/logic/form-logic.spec.ts b/apps/frontend/tests/survey/question/logic/form-logic.spec.ts new file mode 100644 index 00000000..6e3e1645 --- /dev/null +++ b/apps/frontend/tests/survey/question/logic/form-logic.spec.ts @@ -0,0 +1,85 @@ +import test, { expect } from "@playwright/test"; +import { SURVEY_MAKER_FILE } from "../../../utils/constants"; +import { createQuestion, gotoSurvey } from "../../../utils/helper"; +import { setupQuestion } from "../../../utils/helper/questionSetup"; + +test.use({ storageState: SURVEY_MAKER_FILE }); + +test.describe.serial("Edit questions and verify Form logic ", () => { + let workspaceSlug: string, projectSlug: string, surveySlug: string; + + test.beforeAll(async ({ browser }) => { + const setup = await setupQuestion(browser); + workspaceSlug = setup.workspaceSlug; + projectSlug = setup.projectSlug; + surveySlug = setup.surveySlug; + }); + + test("should allow users to edit and update question", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + await page.getByTestId("add-question").waitFor(); + + await createQuestion(page, "Welcome message", { label: "Question one" }); //01 + + await createQuestion(page, "Contact form", { label: "Question two" }); //02 + + await createQuestion(page, "Contact form", { label: "Question three" }); //03 + + await createQuestion(page, "Contact form", { label: "Question four" }); //04 + + await createQuestion(page, "Thank you", { label: "Thank you. Question five" }); //05 + }); + test("should allow user to update question logic", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + await page.getByTestId("question-trigger").nth(1).click(); + await page.getByRole("tab", { name: "Logic" }).click(); + await page.getByTestId("add-new-logic").click(); + await page.getByTestId("value-indicator").click(); + await page.getByRole("option", { name: "First name" }).click(); + await page.getByRole("option", { name: "Last name" }).click(); + await page.getByText("Add logic").click(); + await page.getByTestId("condition-indicator").click(); + await page.getByRole("option", { name: "is filled in" }).click(); + await page.getByTestId("destination-indicator").click(); + await page.getByRole("option", { name: "Question four" }).click(); + + await page.getByTestId("question-trigger").nth(2).click(); + await page.getByRole("tab", { name: "Logic" }).click(); + await page.getByTestId("add-new-logic").click(); + await page.getByTestId("value-indicator").click(); + await page.getByRole("option", { name: "First name" }).click(); + await page.getByRole("option", { name: "Last name" }).click(); + await page.getByText("Add logic").click(); + await page.getByTestId("condition-indicator").click(); + await page.getByRole("option", { name: "is not filled in" }).click(); + await page.getByTestId("destination-indicator").click(); + await page.getByRole("option", { name: "End survey" }).click(); + }); + + test("should verify IS_FILLED_IN logic in the survey preview", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + const iframe = page.frameLocator('iframe[title="Survey preview"]'); + await iframe.getByRole("button", { name: "Submit" }).waitFor(); + + await iframe.getByRole("button", { name: "Submit" }).click(); + await iframe.getByLabel("First name").fill("integra"); + await iframe.getByLabel("Last name").fill("flow"); + await iframe.getByRole("button", { name: "Submit" }).click(); + await expect(iframe.getByText("Question four")).toBeVisible(); + }); + + test("should verify IS_NOT_FILLED_IN logic in the survey preview", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + const iframe = page.frameLocator('iframe[title="Survey preview"]'); + await iframe.getByRole("button", { name: "Submit" }).waitFor(); + + await iframe.getByRole("button", { name: "Submit" }).click(); + await iframe.getByRole("button", { name: "Submit" }).click(); + await iframe.getByRole("button", { name: "Submit" }).click(); + await expect(iframe.getByText("Question one")).toBeVisible(); + }); +}); diff --git a/apps/frontend/tests/survey/question/logic/multiple-answer-logic.spec.ts b/apps/frontend/tests/survey/question/logic/multiple-answer-logic.spec.ts new file mode 100644 index 00000000..6ab144a6 --- /dev/null +++ b/apps/frontend/tests/survey/question/logic/multiple-answer-logic.spec.ts @@ -0,0 +1,127 @@ +import test from "@playwright/test"; +import { SURVEY_MAKER_FILE } from "../../../utils/constants"; +import { createQuestion, gotoSurvey } from "../../../utils/helper"; +import { setupQuestion } from "../../../utils/helper/questionSetup"; + +test.use({ storageState: SURVEY_MAKER_FILE }); + +test.describe.serial("Edit questions and verify Multiple Answer Selection logic ", () => { + let workspaceSlug: string, projectSlug: string, surveySlug: string; + + test.beforeAll(async ({ browser }) => { + const setup = await setupQuestion(browser); + workspaceSlug = setup.workspaceSlug; + projectSlug = setup.projectSlug; + surveySlug = setup.surveySlug; + }); + + test("should allow users to edit and update question", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + await page.getByTestId("add-question").waitFor(); + + await createQuestion(page, "Welcome message", { label: "Question one" }); //01 + + await createQuestion(page, "Multiple answer selection", { label: "Question two" }); + await page.getByPlaceholder("Answer 1").fill("green"); + await page.getByPlaceholder("Answer 2").fill("blue"); + await page.getByText("Add an answer at choice").click(); + await page.getByPlaceholder("Answer 3").fill("red"); + await page.getByText("Add an answer at choice").click(); + await page.getByPlaceholder("Answer 4").fill("yellow"); + await page.getByText("Add an answer at choice").click(); + await page.getByPlaceholder("Answer 5").fill("white"); + await page.getByRole("tab", { name: "Settings" }).click(); + await page.getByTestId("randomize-answers").click(); + + await createQuestion(page, "Boolean", { label: "Question two" }); //02 + + await createQuestion(page, "Multiple answer selection", { label: "Question three" }); + await page.getByPlaceholder("Answer 1").fill("green"); + await page.getByPlaceholder("Answer 2").fill("blue"); + await page.getByText("Add an answer at choice").click(); + await page.getByPlaceholder("Answer 3").fill("red"); + await page.getByText("Add an answer at choice").click(); + await page.getByPlaceholder("Answer 4").fill("yellow"); + await page.getByText("Add an answer at choice").click(); + await page.getByPlaceholder("Answer 5").fill("white"); + await page.getByRole("tab", { name: "Settings" }).click(); + await page.getByTestId("randomize-answers").click(); + + await createQuestion(page, "Boolean", { label: "Question four" }); //02 + + await createQuestion(page, "Multiple answer selection", { label: "Question five" }); + await page.getByPlaceholder("Answer 1").fill("green"); + await page.getByPlaceholder("Answer 2").fill("blue"); + await page.getByText("Add an answer at choice").click(); + await page.getByPlaceholder("Answer 3").fill("red"); + await page.getByText("Add an answer at choice").click(); + await page.getByPlaceholder("Answer 4").fill("yellow"); + await page.getByText("Add an answer at choice").click(); + await page.getByPlaceholder("Answer 5").fill("white"); + await page.getByRole("tab", { name: "Settings" }).click(); + await page.getByTestId("randomize-answers").click(); + + await createQuestion(page, "Boolean", { label: "Question six" }); //02 + + await createQuestion(page, "Thank you", { label: "Thank you. Question seven" }); //05 + }); + + test("should allow user to update question logic", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + await page.getByTestId("question-trigger").nth(1).click(); + await page.getByRole("tab", { name: "Logic" }).click(); + await page.getByTestId("add-new-logic").click(); + await page.getByTestId("condition-indicator").click(); + await page.getByRole("option", { name: "does not include any" }).click(); + await page.getByTestId("value-indicator").click(); + await page.getByRole("option", { name: "green" }).click(); + await page.getByRole("option", { name: "blue" }).click(); + await page.getByText("Add logic").click(); + await page.getByTestId("destination-indicator").click(); + await page.getByRole("option", { name: "Question four" }).click(); + + await page.getByTestId("question-trigger").nth(2).click(); + await page.getByRole("tab", { name: "Logic" }).click(); + await page.getByTestId("add-new-logic").click(); + await page.getByTestId("condition-indicator").click(); + await page.getByRole("option", { name: "includes all" }).click(); + await page.getByTestId("value-indicator").click(); + await page.getByRole("option", { name: "green" }).click(); + await page.getByRole("option", { name: "blue" }).click(); + await page.getByText("Add logic").click(); + await page.getByTestId("destination-indicator").click(); + await page.getByRole("option", { name: "Question four" }).click(); + + await page.getByTestId("add-new-logic").click(); + await page.getByTestId("condition-indicator").click(); + await page.getByRole("option", { name: "has any value" }).click(); + + await page.getByTestId("destination-indicator").click(); + await page.getByRole("option", { name: "End survey" }).click(); + }); + + // test("should verify DOES_NOT_INCLUDE_ANY logic in the survey preview", async ({ page }) => { + // await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + // const iframe = page.frameLocator('iframe[title="Survey preview"]'); + // await iframe.getByRole("button", { name: "Submit" }).waitFor(); + + // await iframe.getByRole("button", { name: "Submit" }).click(); + + // await iframe.getByTestId("white").click(); + // await expect(iframe.getByText("Question four")).toBeVisible(); + // }); + + // test("should verify INCLUDES_ALL logic in the survey preview", async ({ page }) => { + // await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + // const iframe = page.frameLocator('iframe[title="Survey preview"]'); + // await iframe.getByRole("button", { name: "Submit" }).waitFor(); + + // await iframe.getByRole("button", { name: "Submit" }).click(); + // await iframe.getByTestId("thumbs-up").click(); + // await expect(iframe.getByText("Question one")).toBeVisible(); + // }); +}); diff --git a/apps/frontend/tests/survey/question/logic/rating-logic.spec.ts b/apps/frontend/tests/survey/question/logic/rating-logic.spec.ts new file mode 100644 index 00000000..a3458efa --- /dev/null +++ b/apps/frontend/tests/survey/question/logic/rating-logic.spec.ts @@ -0,0 +1,134 @@ +import test, { expect } from "@playwright/test"; +import { SURVEY_MAKER_FILE } from "../../../utils/constants"; +import { createQuestion, gotoSurvey } from "../../../utils/helper"; +import { setupQuestion } from "../../../utils/helper/questionSetup"; + +test.use({ storageState: SURVEY_MAKER_FILE }); + +test.describe.serial("Edit questions and verify Rating logic ", () => { + let workspaceSlug: string, projectSlug: string, surveySlug: string; + + test.beforeAll(async ({ browser }) => { + const setup = await setupQuestion(browser); + workspaceSlug = setup.workspaceSlug; + projectSlug = setup.projectSlug; + surveySlug = setup.surveySlug; + }); + + test("should allow users to edit and update question", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + await page.getByTestId("add-question").waitFor(); + + await createQuestion(page, "Welcome message", { label: "Question one" }); //01 + + await createQuestion(page, "Rating scale", { label: "Question two" }); //02 + + await createQuestion(page, "Rating scale", { label: "Question three" }); //03 + + await createQuestion(page, "Rating scale", { label: "Question four" }); //04 + + await createQuestion(page, "Rating scale", { label: "Question five" }); //05 + + await createQuestion(page, "Thank you", { label: "Thank you. Question six" }); //06 + }); + test("should allow user to update question logic", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + await page.getByTestId("question-trigger").nth(1).click(); + await page.getByRole("tab", { name: "Logic" }).click(); + await page.getByTestId("add-new-logic").click(); + await page.getByTestId("condition-indicator").click(); + await page.getByRole("option", { name: "is", exact: true }).click(); + await page.getByTestId("value-indicator").click(); + await page.getByRole("option", { name: "1" }).click(); + await page.getByText("Add logic").click(); + await page.getByTestId("destination-indicator").click(); + await page.getByRole("option", { name: "Question four" }).click(); + + await page.getByTestId("add-new-logic").click(); + await page.getByTestId("condition-indicator").click(); + await page.getByRole("option", { name: "is between" }).click(); + await page.getByTestId("min-indicator").click(); + await page.getByRole("option", { name: "2" }).click(); + await page.getByTestId("max-indicator").click(); + await page.getByRole("option", { name: "4" }).click(); + await page.getByTestId("destination-indicator").click(); + await page.getByRole("option", { name: "End survey" }).click(); + + await page.getByTestId("question-trigger").nth(2).click(); + await page.getByRole("tab", { name: "Logic" }).click(); + await page.getByTestId("add-new-logic").click(); + await page.getByTestId("condition-indicator").click(); + await page.getByRole("option", { name: "is not" }).click(); + await page.getByTestId("value-indicator").click(); + await page.getByRole("option", { name: "2" }).click(); + await page.getByText("Add logic").click(); + await page.getByTestId("destination-indicator").click(); + await page.getByRole("option", { name: "End survey" }).click(); + + await page.getByTestId("question-trigger").nth(3).click(); + await page.getByRole("tab", { name: "Logic" }).click(); + await page.getByTestId("add-new-logic").click(); + await page.getByTestId("condition-indicator").click(); + await page.getByRole("option", { name: "has any value" }).click(); + await page.getByTestId("destination-indicator").click(); + await page.getByRole("option", { name: "End survey" }).click(); + }); + + test("should verify IS logic in the survey preview", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + const iframe = page.frameLocator('iframe[title="Survey preview"]'); + await iframe.getByRole("button", { name: "Submit" }).waitFor(); + + await iframe.getByRole("button", { name: "Submit" }).click(); + await iframe.getByTestId("star").nth(0).click(); + await expect(iframe.getByText("Question four")).toBeVisible(); + }); + + test("should verify IS_BETWEEN logic in the survey preview", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + const iframe = page.frameLocator('iframe[title="Survey preview"]'); + + await page.waitForTimeout(3000); + + await iframe.getByRole("button", { name: "Submit" }).waitFor(); + await iframe.getByRole("button", { name: "Submit" }).click(); + + await iframe.getByTestId("star").nth(2).click(); + await expect(iframe.getByText("Question one")).toBeVisible(); + }); + + test("should verify IS_NOT logic in the survey preview", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + const iframe = page.frameLocator('iframe[title="Survey preview"]'); + + await page.waitForTimeout(3000); + + await iframe.getByRole("button", { name: "Submit" }).waitFor(); + await iframe.getByRole("button", { name: "Submit" }).click(); + + await iframe.getByTestId("star").nth(4).click(); + await iframe.getByTestId("star").nth(0).click(); + await expect(iframe.getByText("Question one")).toBeVisible(); + }); + + test("should verify HAS_ANY_VALUE logic in the survey preview", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + const iframe = page.frameLocator('iframe[title="Survey preview"]'); + + await page.waitForTimeout(3000); + + await iframe.getByRole("button", { name: "Submit" }).waitFor(); + await iframe.getByRole("button", { name: "Submit" }).click(); + + await iframe.getByTestId("star").nth(4).click(); + await iframe.getByTestId("star").nth(1).click(); + await iframe.getByTestId("star").nth(1).click(); + await expect(iframe.getByText("Question one")).toBeVisible(); + }); +}); diff --git a/apps/frontend/tests/survey/question/logic/text-logic.spec.ts b/apps/frontend/tests/survey/question/logic/text-logic.spec.ts new file mode 100644 index 00000000..8d8b55f1 --- /dev/null +++ b/apps/frontend/tests/survey/question/logic/text-logic.spec.ts @@ -0,0 +1,82 @@ +import test from "@playwright/test"; +import { SURVEY_MAKER_FILE } from "../../../utils/constants"; +import { createQuestion, gotoSurvey } from "../../../utils/helper"; +import { setupQuestion } from "../../../utils/helper/questionSetup"; + +test.use({ storageState: SURVEY_MAKER_FILE }); + +test.describe.serial("Test ", () => { + let workspaceSlug: string, projectSlug: string, surveySlug: string; + + test.beforeAll(async ({ browser }) => { + const setup = await setupQuestion(browser); + workspaceSlug = setup.workspaceSlug; + projectSlug = setup.projectSlug; + surveySlug = setup.surveySlug; + }); + + test("should allow users to edit and update question", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + await page.getByTestId("add-question").waitFor(); + + await createQuestion(page, "Welcome message", { label: "Question one" }); //01 + await page.getByRole("tab", { name: "Settings" }).click(); + await page.getByTestId("button-label").fill("Next"); + + await createQuestion(page, "Text answer", { label: "Question two" }); //02 + + await createQuestion(page, "Text answer", { label: "Question three" }); //03 + + await createQuestion(page, "Smiley scale", { label: "Question four" }); //04 + + await createQuestion(page, "Thank you", { label: "Thank you. Question five" }); //05 + }); + test("should allow user to update question logic", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + await page.getByTestId("question-trigger").nth(1).click(); + await page.getByRole("tab", { name: "Logic" }).click(); + // await page.getByTestId("add-new-logic").click(); + // await page.getByTestId("condition-indicator").click(); + // await page.getByRole("option", { name: "answer contains" }).click(); + // await page.getByTestId("value-indicator").click(); + // await page.locator(".react-select__input-container").fill("Hello"); + // await page.getByText("Add logic").click(); + // await page.getByRole("option", { name: "Question four" }).click(); + + await page.getByTestId("add-new-logic").click(); + await page.getByTestId("condition-indicator").click(); + await page.getByRole("option", { name: "question is not answered" }).click(); + await page.getByTestId("destination-indicator").click(); + await page.getByRole("option", { name: "Thank you" }).click(); + + await page.getByTestId("question-trigger").nth(2).click(); + await page.getByRole("tab", { name: "Logic" }).click(); + // await page.getByTestId("add-new-logic").click(); + // await page.getByTestId("condition-indicator").click(); + // await page.getByRole("option", { name: "answer does not contain" }).click(); + // await page.getByTestId("value-indicator").click(); + // await page.locator(".react-select__input-container").fill("Hello"); + // await page.getByText("Add logic").click(); + // await page.getByRole("option", { name: "Thank you. Question five" }).click(); + + await page.getByTestId("add-new-logic").click(); + await page.getByTestId("condition-indicator").click(); + await page.getByRole("option", { name: "question is answered" }).click(); + await page.getByTestId("destination-indicator").click(); + await page.getByRole("option", { name: "End survey" }).click(); + }); + + test("should display the updated button label correctly in the survey preview", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + const iframe = page.frameLocator('iframe[title="Survey preview"]'); + + // await page.getByTestId("question-trigger").nth(0).click(); + // await iframe.getByRole("button", { name: "Next" }).waitFor(); + + // await expect(iframe.getByRole("button", { name: "Next" })).toBeVisible(); + // await iframe.getByRole("button", { name: "Next" }).click(); + }); +}); diff --git a/apps/frontend/tests/utils/helper/index.ts b/apps/frontend/tests/utils/helper/index.ts index b66ec591..26b4f4fa 100644 --- a/apps/frontend/tests/utils/helper/index.ts +++ b/apps/frontend/tests/utils/helper/index.ts @@ -75,16 +75,23 @@ export const gotoSurvey = async (page: Page, workspaceSlug: string, projectSlug: }); }; -export const createQuestion = async (page: Page, questionType: string) => { +export const createQuestion = async ( + page: Page, + questionType: string, + text: { label?: string; desc?: string } = {}, +) => { await page.getByTestId("add-question").click(); await waitForResponse(page, "SurveyQuestionCreate", async () => { await page.getByTestId(questionType).click(); }); await waitForResponse(page, "SurveyQuestionUpdate", async () => { - await page.locator(".ql-editor").fill("Hello"); + await page.locator(".ql-editor").fill(text.label ?? "Hello"); }); await page.getByTestId("add-description-btn").click(); await waitForResponse(page, "SurveyQuestionUpdate", async () => { - await page.locator(".ql-editor").last().fill("Hi there"); + await page + .locator(".ql-editor") + .last() + .fill(text.desc ?? "Hi there"); }); }; From 19dbcdfcb95d9e277b43a81e72c811852b1c0c60 Mon Sep 17 00:00:00 2001 From: afolasope Date: Mon, 11 Nov 2024 16:23:50 +0100 Subject: [PATCH 48/49] update logic tests --- .../logic/multiple-answer-logic.spec.ts | 1 + .../survey/question/logic/text-logic.spec.ts | 94 ++++++++++++++----- 2 files changed, 71 insertions(+), 24 deletions(-) diff --git a/apps/frontend/tests/survey/question/logic/multiple-answer-logic.spec.ts b/apps/frontend/tests/survey/question/logic/multiple-answer-logic.spec.ts index 6ab144a6..568c131f 100644 --- a/apps/frontend/tests/survey/question/logic/multiple-answer-logic.spec.ts +++ b/apps/frontend/tests/survey/question/logic/multiple-answer-logic.spec.ts @@ -24,6 +24,7 @@ test.describe.serial("Edit questions and verify Multiple Answer Selection logic await createQuestion(page, "Multiple answer selection", { label: "Question two" }); await page.getByPlaceholder("Answer 1").fill("green"); + await page.getByPlaceholder("Answer 2").fill("blue"); await page.getByText("Add an answer at choice").click(); await page.getByPlaceholder("Answer 3").fill("red"); diff --git a/apps/frontend/tests/survey/question/logic/text-logic.spec.ts b/apps/frontend/tests/survey/question/logic/text-logic.spec.ts index 8d8b55f1..b746cdaa 100644 --- a/apps/frontend/tests/survey/question/logic/text-logic.spec.ts +++ b/apps/frontend/tests/survey/question/logic/text-logic.spec.ts @@ -1,4 +1,4 @@ -import test from "@playwright/test"; +import test, { expect } from "@playwright/test"; import { SURVEY_MAKER_FILE } from "../../../utils/constants"; import { createQuestion, gotoSurvey } from "../../../utils/helper"; import { setupQuestion } from "../../../utils/helper/questionSetup"; @@ -21,29 +21,32 @@ test.describe.serial("Test ", () => { await page.getByTestId("add-question").waitFor(); await createQuestion(page, "Welcome message", { label: "Question one" }); //01 - await page.getByRole("tab", { name: "Settings" }).click(); - await page.getByTestId("button-label").fill("Next"); await createQuestion(page, "Text answer", { label: "Question two" }); //02 await createQuestion(page, "Text answer", { label: "Question three" }); //03 - await createQuestion(page, "Smiley scale", { label: "Question four" }); //04 + await createQuestion(page, "Text answer", { label: "Question four" }); //04 - await createQuestion(page, "Thank you", { label: "Thank you. Question five" }); //05 + await createQuestion(page, "Text answer", { label: "Question five" }); //04 + + await createQuestion(page, "Thank you", { label: "Thank you. Question six" }); //05 }); test("should allow user to update question logic", async ({ page }) => { await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); await page.getByTestId("question-trigger").nth(1).click(); await page.getByRole("tab", { name: "Logic" }).click(); - // await page.getByTestId("add-new-logic").click(); - // await page.getByTestId("condition-indicator").click(); - // await page.getByRole("option", { name: "answer contains" }).click(); - // await page.getByTestId("value-indicator").click(); - // await page.locator(".react-select__input-container").fill("Hello"); - // await page.getByText("Add logic").click(); - // await page.getByRole("option", { name: "Question four" }).click(); + await page.getByTestId("add-new-logic").click(); + await page.getByTestId("condition-indicator").click(); + await page.getByRole("option", { name: "answer contains" }).click(); + await page.getByTestId("value-indicator").click(); + await page.locator(".react-select__input").focus(); + await page.locator(".react-select__input").fill("Hello"); + await page.keyboard.press("Enter"); + await page.getByText("Add logic").click(); + await page.getByTestId("destination-indicator").click(); + await page.getByRole("option", { name: "Question four" }).click(); await page.getByTestId("add-new-logic").click(); await page.getByTestId("condition-indicator").click(); @@ -53,14 +56,19 @@ test.describe.serial("Test ", () => { await page.getByTestId("question-trigger").nth(2).click(); await page.getByRole("tab", { name: "Logic" }).click(); - // await page.getByTestId("add-new-logic").click(); - // await page.getByTestId("condition-indicator").click(); - // await page.getByRole("option", { name: "answer does not contain" }).click(); - // await page.getByTestId("value-indicator").click(); - // await page.locator(".react-select__input-container").fill("Hello"); - // await page.getByText("Add logic").click(); - // await page.getByRole("option", { name: "Thank you. Question five" }).click(); + await page.getByTestId("add-new-logic").click(); + await page.getByTestId("condition-indicator").click(); + await page.getByRole("option", { name: "answer does not contain" }).click(); + await page.getByTestId("value-indicator").click(); + await page.locator(".react-select__input").focus(); + await page.locator(".react-select__input").fill("Hello"); + await page.keyboard.press("Enter"); + await page.getByText("Add logic").click(); + await page.getByTestId("destination-indicator").click(); + await page.getByRole("option", { name: "Thank you" }).click(); + await page.getByTestId("question-trigger").nth(3).click(); + await page.getByRole("tab", { name: "Logic" }).click(); await page.getByTestId("add-new-logic").click(); await page.getByTestId("condition-indicator").click(); await page.getByRole("option", { name: "question is answered" }).click(); @@ -68,15 +76,53 @@ test.describe.serial("Test ", () => { await page.getByRole("option", { name: "End survey" }).click(); }); - test("should display the updated button label correctly in the survey preview", async ({ page }) => { + test("should verify ANSWER_CONTAINS logic in the survey preview", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + const iframe = page.frameLocator('iframe[title="Survey preview"]'); + + await iframe.getByRole("button", { name: "Submit" }).waitFor(); + await iframe.getByRole("button", { name: "Submit" }).click(); + await iframe.getByTestId("textarea-box").fill("hello there"); + await iframe.getByRole("button", { name: "Submit" }).click(); + await expect(iframe.getByText("Question four")).toBeVisible(); + }); + + test("should verify QUESTION_IS_NOT_ANSWERED logic in the survey preview", async ({ page }) => { await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); const iframe = page.frameLocator('iframe[title="Survey preview"]'); - // await page.getByTestId("question-trigger").nth(0).click(); - // await iframe.getByRole("button", { name: "Next" }).waitFor(); + await iframe.getByRole("button", { name: "Submit" }).waitFor(); + await iframe.getByRole("button", { name: "Submit" }).click(); + await iframe.getByRole("button", { name: "Submit" }).click(); + await expect(iframe.getByText("Thank you")).toBeVisible(); + }); + + test("should verify ANSWER_DOES_NOT_CONTAIN logic in the survey preview", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + const iframe = page.frameLocator('iframe[title="Survey preview"]'); + + await iframe.getByRole("button", { name: "Submit" }).waitFor(); + await iframe.getByRole("button", { name: "Submit" }).click(); + await iframe.getByRole("button", { name: "Submit" }).click(); + await iframe.getByTestId("textarea-box").fill("hi there"); + await iframe.getByRole("button", { name: "Submit" }).click(); + await expect(iframe.getByText("Thank you")).toBeVisible(); + }); + + test("should verify QUESTION_IS_ANSWERED logic in the survey preview", async ({ page }) => { + await gotoSurvey(page, workspaceSlug, projectSlug, surveySlug); + + const iframe = page.frameLocator('iframe[title="Survey preview"]'); - // await expect(iframe.getByRole("button", { name: "Next" })).toBeVisible(); - // await iframe.getByRole("button", { name: "Next" }).click(); + await iframe.getByRole("button", { name: "Submit" }).waitFor(); + await iframe.getByRole("button", { name: "Submit" }).click(); + await iframe.getByRole("button", { name: "Submit" }).click(); + await iframe.getByRole("button", { name: "Submit" }).click(); + await iframe.getByTestId("textarea-box").fill("hi there"); + await iframe.getByRole("button", { name: "Submit" }).click(); + await expect(iframe.getByText("Question one")).toBeVisible(); }); }); From c8d4a8810748dcde4b0999550447e1fd38b22e6a Mon Sep 17 00:00:00 2001 From: afolasope Date: Wed, 13 Nov 2024 14:08:26 +0100 Subject: [PATCH 49/49] update logic test --- apps/frontend/tests/survey/question/logic/text-logic.spec.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/frontend/tests/survey/question/logic/text-logic.spec.ts b/apps/frontend/tests/survey/question/logic/text-logic.spec.ts index b746cdaa..4ae24c89 100644 --- a/apps/frontend/tests/survey/question/logic/text-logic.spec.ts +++ b/apps/frontend/tests/survey/question/logic/text-logic.spec.ts @@ -106,6 +106,7 @@ test.describe.serial("Test ", () => { await iframe.getByRole("button", { name: "Submit" }).waitFor(); await iframe.getByRole("button", { name: "Submit" }).click(); + await iframe.getByTestId("textarea-box").fill("hey there"); await iframe.getByRole("button", { name: "Submit" }).click(); await iframe.getByTestId("textarea-box").fill("hi there"); await iframe.getByRole("button", { name: "Submit" }).click(); @@ -119,9 +120,11 @@ test.describe.serial("Test ", () => { await iframe.getByRole("button", { name: "Submit" }).waitFor(); await iframe.getByRole("button", { name: "Submit" }).click(); + await iframe.getByTestId("textarea-box").fill("hey there"); await iframe.getByRole("button", { name: "Submit" }).click(); + await iframe.getByTestId("textarea-box").fill("hello there"); await iframe.getByRole("button", { name: "Submit" }).click(); - await iframe.getByTestId("textarea-box").fill("hi there"); + await iframe.getByTestId("textarea-box").fill("hello there"); await iframe.getByRole("button", { name: "Submit" }).click(); await expect(iframe.getByText("Question one")).toBeVisible(); });