From edd158cceaf2cd528384045d58bf09a0550d621f Mon Sep 17 00:00:00 2001 From: Florian Zia Date: Fri, 30 Aug 2024 13:01:45 +0200 Subject: [PATCH 01/10] feat: Add Github workflow to run the full e2e test suite on PRs --- .github/workflows/e2e_cron.yml | 4 +- .github/workflows/e2e_pr_full.yml | 89 ++ .../{e2e_pr.yml => e2e_pr_smoke.yml} | 2 +- src/e2e/specs/auth.spec.ts | 117 +- src/e2e/specs/breachResolution.spec.ts | 211 +-- src/e2e/specs/dashboard.spec.ts | 1239 +++++++++-------- src/e2e/specs/landing.spec.ts | 685 ++++----- src/e2e/specs/purchase.spec.ts | 361 ++--- src/e2e/specs/settings.spec.ts | 2 +- 9 files changed, 1423 insertions(+), 1287 deletions(-) create mode 100644 .github/workflows/e2e_pr_full.yml rename .github/workflows/{e2e_pr.yml => e2e_pr_smoke.yml} (99%) diff --git a/.github/workflows/e2e_cron.yml b/.github/workflows/e2e_cron.yml index fa7e6074e24..3a1f9271721 100644 --- a/.github/workflows/e2e_cron.yml +++ b/.github/workflows/e2e_cron.yml @@ -76,7 +76,6 @@ jobs: name: test-results path: src/e2e/test-results/ retention-days: 30 - - name: Send GitHub Action trigger data to Slack workflow id: slack uses: slackapi/slack-github-action@v1.26.0 @@ -90,7 +89,7 @@ jobs: "type": "section", "text": { "type": "mrkdwn", - "text": "*Link to job:* **" + "text": "*Link to job:* **" } }, { @@ -127,4 +126,3 @@ jobs: env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_GHA_FAILURES_WEBHOOK }} SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK - \ No newline at end of file diff --git a/.github/workflows/e2e_pr_full.yml b/.github/workflows/e2e_pr_full.yml new file mode 100644 index 00000000000..b3f2219478c --- /dev/null +++ b/.github/workflows/e2e_pr_full.yml @@ -0,0 +1,89 @@ +name: Monitor E2E Full Test Suite +on: push +jobs: + e2e-tests: + timeout-minutes: 60 + runs-on: ubuntu-latest + # Service containers to run with `container-job` + services: + # Label used to access the service container + postgres: + # Docker Hub image + image: postgres + # Provide the password for postgres + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: blurts + # Set health checks to wait until postgres has started + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 5432:5432 + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22.6.x + + - name: Install dependencies + run: npm ci + - name: Setting up postgres + run: npm run db:migrate + env: + DATABASE_URL: postgres://postgres:postgres@localhost:5432/blurts + - name: Store Playwright's Version + run: | + # Get the current Playwright version listed in package.json + PLAYWRIGHT_VERSION=$(npx playwright --version | sed 's/Version //') + echo "Playwright Version: $PLAYWRIGHT_VERSION" + echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV + + - name: Cache Playwright Browsers for Playwright's Version + id: cache-playwright-browsers + uses: actions/cache@v4 + with: + path: ~/.cache/ms-playwright + key: playwright-browsers-${{ env.PLAYWRIGHT_VERSION }} + + - name: Setup Playwright Browser + if: steps.cache-playwright-browsers.outputs.cache-hit != 'true' + run: npx playwright install --with-deps + + - name: Run Playwright tests + if: github.actor != 'dependabot[bot]' + run: npm run e2e + timeout-minutes: 40 + env: + E2E_TEST_ENV: ${{ inputs.environment != null && inputs.environment || 'stage' }} + E2E_TEST_BASE_URL: ${{ secrets.E2E_TEST_BASE_URL }} + E2E_TEST_ACCOUNT_EMAIL: ${{ secrets.E2E_TEST_ACCOUNT_EMAIL }} + E2E_TEST_ACCOUNT_PASSWORD: ${{ secrets.E2E_TEST_ACCOUNT_PASSWORD }} + E2E_TEST_ACCOUNT_EMAIL_ZERO_BREACHES: ${{ secrets.E2E_TEST_ACCOUNT_EMAIL_ZERO_BREACHES }} + E2E_TEST_ACCOUNT_EMAIL_EXPOSURES_STARTED: ${{ secrets.E2E_TEST_ACCOUNT_EMAIL_EXPOSURES_STARTED }} + E2E_TEST_PAYPAL_LOGIN: ${{ secrets.E2E_TEST_PAYPAL_LOGIN }} + E2E_TEST_PAYPAL_PASSWORD: ${{ secrets.E2E_TEST_PAYPAL_PASSWORD }} + ADMINS: ${{ secrets.ADMINS }} + OAUTH_CLIENT_SECRET: ${{ secrets.OAUTH_CLIENT_SECRET }} + ONEREP_API_KEY: ${{ secrets.ONEREP_API_KEY }} + NEXTAUTH_SECRET: ${{ secrets.NEXTAUTH_SECRET }} + NEXTAUTH_URL: ${{ secrets.NEXTAUTH_URL }} + HIBP_KANON_API_TOKEN: ${{ secrets.HIBP_KANON_API_TOKEN }} + HIBP_API_TOKEN: ${{ secrets.HIBP_API_TOKEN }} + REDIS_URL: "redis://redis.mock" + - uses: actions/upload-artifact@v4 + if: always() + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 + - uses: actions/upload-artifact@v4 + if: always() + with: + name: test-results + path: src/e2e/test-results/ + retention-days: 30 diff --git a/.github/workflows/e2e_pr.yml b/.github/workflows/e2e_pr_smoke.yml similarity index 99% rename from .github/workflows/e2e_pr.yml rename to .github/workflows/e2e_pr_smoke.yml index 63629f61549..08b33d561a0 100644 --- a/.github/workflows/e2e_pr.yml +++ b/.github/workflows/e2e_pr_smoke.yml @@ -1,4 +1,4 @@ -name: Monitor e2e Smoke Tests +name: Monitor E2E Smoke Test Suite on: push: branches: [ main ] diff --git a/src/e2e/specs/auth.spec.ts b/src/e2e/specs/auth.spec.ts index 92959b012d7..120be8bcc48 100644 --- a/src/e2e/specs/auth.spec.ts +++ b/src/e2e/specs/auth.spec.ts @@ -4,71 +4,74 @@ import { test, expect } from "../fixtures/basePage.js"; -test.describe(`${process.env.E2E_TEST_ENV} - Authentication flow verification @smoke`, () => { - test.beforeEach(async ({ landingPage }) => { - await landingPage.open(); - }); - - test("Verify sign up with new user", async ({ - page, - authPage, - landingPage, - }, testInfo) => { - // speed up test by ignore non necessary requests - await page.route(/(analytics)/, async (route) => { - await route.abort(); +test.describe.skip( + `${process.env.E2E_TEST_ENV} - Authentication flow verification @smoke`, + () => { + test.beforeEach(async ({ landingPage }) => { + await landingPage.open(); }); - // start authentication flow - await landingPage.goToSignIn(); + test("Verify sign up with new user", async ({ + page, + authPage, + landingPage, + }, testInfo) => { + // speed up test by ignore non necessary requests + await page.route(/(analytics)/, async (route) => { + await route.abort(); + }); - // Fill out sign up form - const randomEmail = `${Date.now()}_tstact@restmail.net`; - await authPage.signUp(randomEmail, page); + // start authentication flow + await landingPage.goToSignIn(); - // assert successful login - const successUrl = - process.env.E2E_TEST_ENV === "local" - ? "/user/dashboard" - : "/user/welcome"; - expect(page.url()).toBe(`${process.env.E2E_TEST_BASE_URL}${successUrl}`); + // Fill out sign up form + const randomEmail = `${Date.now()}_tstact@restmail.net`; + await authPage.signUp(randomEmail, page); - await testInfo.attach( - `${process.env.E2E_TEST_ENV}-signup-monitor-dashboard.png`, - { - body: await page.screenshot(), - contentType: "image/png", - }, - ); - }); + // assert successful login + const successUrl = + process.env.E2E_TEST_ENV === "local" + ? "/user/dashboard" + : "/user/welcome"; + expect(page.url()).toBe(`${process.env.E2E_TEST_BASE_URL}${successUrl}`); - test("Verify sign in with existing user", async ({ - page, - authPage, - landingPage, - dashboardPage, - }, testInfo) => { - // speed up test by ignore non necessary requests - await page.route(/(analytics)/, async (route) => { - await route.abort(); + await testInfo.attach( + `${process.env.E2E_TEST_ENV}-signup-monitor-dashboard.png`, + { + body: await page.screenshot(), + contentType: "image/png", + }, + ); }); - // start authentication flow - await landingPage.goToSignIn(); + test("Verify sign in with existing user", async ({ + page, + authPage, + landingPage, + dashboardPage, + }, testInfo) => { + // speed up test by ignore non necessary requests + await page.route(/(analytics)/, async (route) => { + await route.abort(); + }); + + // start authentication flow + await landingPage.goToSignIn(); - // sign in - await authPage.signIn(process.env.E2E_TEST_ACCOUNT_EMAIL as string); + // sign in + await authPage.signIn(process.env.E2E_TEST_ACCOUNT_EMAIL as string); - // assert successful login - await expect(dashboardPage.fixedTab).toBeVisible(); - await expect(dashboardPage.actionNeededTab).toBeVisible(); + // assert successful login + await expect(dashboardPage.fixedTab).toBeVisible(); + await expect(dashboardPage.actionNeededTab).toBeVisible(); - await testInfo.attach( - `${process.env.E2E_TEST_ENV}-signin-monitor-dashboard.png`, - { - body: await page.screenshot(), - contentType: "image/png", - }, - ); - }); -}); + await testInfo.attach( + `${process.env.E2E_TEST_ENV}-signin-monitor-dashboard.png`, + { + body: await page.screenshot(), + contentType: "image/png", + }, + ); + }); + }, +); diff --git a/src/e2e/specs/breachResolution.spec.ts b/src/e2e/specs/breachResolution.spec.ts index e17370ed457..16bcd0a4a7e 100644 --- a/src/e2e/specs/breachResolution.spec.ts +++ b/src/e2e/specs/breachResolution.spec.ts @@ -6,112 +6,115 @@ import { test, expect } from "../fixtures/basePage.js"; // bypass login test.use({ storageState: "./e2e/storageState.json" }); -test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Headers`, () => { - test("Verify that the site header is displayed correctly for signed in users", async ({ - dataBreachPage, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2095101", +test.describe.skip( + `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Headers`, + () => { + test("Verify that the site header is displayed correctly for signed in users", async ({ + dataBreachPage, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2095101", + }); + + // should go directly to data breach page + await dataBreachPage.open(); + + // verify logo and profile button + await expect(dataBreachPage.dataBreachesLogo).toBeVisible(); + await expect(dataBreachPage.dataBreachesNavbarProfile).toBeVisible(); }); - // should go directly to data breach page - await dataBreachPage.open(); - - // verify logo and profile button - await expect(dataBreachPage.dataBreachesLogo).toBeVisible(); - await expect(dataBreachPage.dataBreachesNavbarProfile).toBeVisible(); - }); - - // skip as settings dropdown menu is currently wip for redesign TODO: update for redesign when its done - test.skip("Verify that the site header options work correctly for a signed in user", async ({ - dataBreachPage, - settingsPage, - page, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2095102", + // skip as settings dropdown menu is currently wip for redesign TODO: update for redesign when its done + test.skip("Verify that the site header options work correctly for a signed in user", async ({ + dataBreachPage, + settingsPage, + page, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2095102", + }); + + // should go directly to data breach page + await settingsPage.open(); + + // verify logo and profile button + expect( + await dataBreachPage.dataBreachesLogoLink.first().getAttribute("href"), + ).toBe("/user/breaches"); + + await page.waitForLoadState("networkidle"); + await dataBreachPage.dataBreachesNavbarProfile.click(); + + // verify manage your Mozilla account link, settings option, help and support option, sign out option + // menu is open + expect(await dataBreachPage.profileMenuExpanded()).toBe(true); + + // menu header + await expect( + dataBreachPage.dataBreachesNavbarProfileMenuHeader, + ).toBeVisible(); + + // head text + await expect( + dataBreachPage.dataBreachesNavbarProfileMenuHeaderSubtitle, + ).toHaveText("Manage your Mozilla account"); + + // check settings + await expect( + dataBreachPage.dataBreachesNavbarProfileMenuSettings, + ).toBeVisible(); + + // help and support + await expect( + dataBreachPage.dataBreachesNavbarProfileMenuHelpAndSupport, + ).toBeVisible(); + + // sign out + await expect( + dataBreachPage.dataBreachesNavbarProfileMenuSignOut, + ).toBeVisible(); }); - // should go directly to data breach page - await settingsPage.open(); - - // verify logo and profile button - expect( - await dataBreachPage.dataBreachesLogoLink.first().getAttribute("href"), - ).toBe("/user/breaches"); - - await page.waitForLoadState("networkidle"); - await dataBreachPage.dataBreachesNavbarProfile.click(); - - // verify manage your Mozilla account link, settings option, help and support option, sign out option - // menu is open - expect(await dataBreachPage.profileMenuExpanded()).toBe(true); - - // menu header - await expect( - dataBreachPage.dataBreachesNavbarProfileMenuHeader, - ).toBeVisible(); - - // head text - await expect( - dataBreachPage.dataBreachesNavbarProfileMenuHeaderSubtitle, - ).toHaveText("Manage your Mozilla account"); - - // check settings - await expect( - dataBreachPage.dataBreachesNavbarProfileMenuSettings, - ).toBeVisible(); - - // help and support - await expect( - dataBreachPage.dataBreachesNavbarProfileMenuHelpAndSupport, - ).toBeVisible(); - - // sign out - await expect( - dataBreachPage.dataBreachesNavbarProfileMenuSignOut, - ).toBeVisible(); - }); - - test(" Verify that the user can navigate through the Monitor dashboard", async ({ - dashboardPage, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2095103", + test(" Verify that the user can navigate through the Monitor dashboard", async ({ + dashboardPage, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2095103", + }); + + // open dashboard page + await dashboardPage.open(); + + // get expected links + const links = dashboardPage.dashboardLinks(); + + // verify the navigation within monitor + // settings button redirects the user to "Settings" tab + await expect(dashboardPage.settingsPageLink).toHaveAttribute( + "href", + links.settingsNavButtonLink, + ); + + // redirects the user to the "Resolve data breaches (dashboard)" tab + await expect(dashboardPage.dashboardPageLink).toHaveAttribute( + "href", + links.resolveDataBreachesNavButtonLink, + ); + + // opens a new tab in which user is redirected to the "Monitor Help (FAQs)" page + await expect(dashboardPage.faqsPageLink).toHaveAttribute( + "href", + links.helpAndSupportNavButtonLink, + ); }); - - // open dashboard page - await dashboardPage.open(); - - // get expected links - const links = dashboardPage.dashboardLinks(); - - // verify the navigation within monitor - // settings button redirects the user to "Settings" tab - await expect(dashboardPage.settingsPageLink).toHaveAttribute( - "href", - links.settingsNavButtonLink, - ); - - // redirects the user to the "Resolve data breaches (dashboard)" tab - await expect(dashboardPage.dashboardPageLink).toHaveAttribute( - "href", - links.resolveDataBreachesNavButtonLink, - ); - - // opens a new tab in which user is redirected to the "Monitor Help (FAQs)" page - await expect(dashboardPage.faqsPageLink).toHaveAttribute( - "href", - links.helpAndSupportNavButtonLink, - ); - }); -}); + }, +); diff --git a/src/e2e/specs/dashboard.spec.ts b/src/e2e/specs/dashboard.spec.ts index db28297f81e..d30c1745e3b 100644 --- a/src/e2e/specs/dashboard.spec.ts +++ b/src/e2e/specs/dashboard.spec.ts @@ -20,213 +20,216 @@ import { // bypass login test.use({ storageState: "./e2e/storageState.json" }); -test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Headers @smoke`, () => { - test.beforeEach(async ({ dashboardPage, page }) => { - await dashboardPage.open(); - - try { - await checkAuthState(page); - } catch { - console.log("[E2E_LOG] - No fxa auth required, proceeding..."); - } - }); +test.describe.skip( + `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Headers @smoke`, + () => { + test.beforeEach(async ({ dashboardPage, page }) => { + await dashboardPage.open(); - test("Verify that the site header is displayed correctly for signed in users", async ({ - dashboardPage, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301512", + try { + await checkAuthState(page); + } catch { + console.log("[E2E_LOG] - No fxa auth required, proceeding..."); + } }); - await expect(dashboardPage.dashboardNavButton).toHaveAttribute( - "href", - "/user/dashboard", - ); - await expect(dashboardPage.FAQsNavButton).toHaveAttribute( - "href", - "https://support.mozilla.org/kb/firefox-monitor-faq", - ); - }); - - test("Verify that the site header and navigation bar is displayed correctly", async ({ - dashboardPage, - }) => { - // link to testrail - test.info().annotations.push( - { - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301511", - }, - { + test("Verify that the site header is displayed correctly for signed in users", async ({ + dashboardPage, + }) => { + // link to testrail + test.info().annotations.push({ type: "testrail", description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463567", - }, - ); + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301512", + }); - // verify the navigation bar left side elements - await expect(dashboardPage.fireFoxMonitorLogoImgButton).toBeVisible(); - await expect(dashboardPage.dashboardNavButton).toBeVisible(); - await expect(dashboardPage.exposuresHeading).toBeVisible(); - await expect(dashboardPage.settingsPageLink).toBeVisible(); - await expect(dashboardPage.FAQsNavButton).toBeVisible(); - - // verify the site header elements - await expect(dashboardPage.actionNeededTab).toBeVisible(); - await expect(dashboardPage.fixedTab).toBeVisible(); - - // auto data removal button - await expect(dashboardPage.subscribeButton).toBeVisible(); - - // apps and services - await expect(dashboardPage.appsAndServices).toBeVisible(); - await dashboardPage.appsAndServices.click(); - await expect(dashboardPage.servicesVpn).toBeVisible(); - await expect(dashboardPage.servicesRelay).toBeVisible(); - await expect(dashboardPage.servicesPocket).toBeVisible(); - await expect(dashboardPage.servicesFirefoxDesktop).toBeVisible(); - await expect(dashboardPage.servicesFirefoxMobile).toBeVisible(); - - // profile button - await dashboardPage.closeAppsAndServices.click(); - await expect(dashboardPage.profileButton).toBeVisible(); - await dashboardPage.profileButton.click(); - await expect(dashboardPage.profileEmail).toBeVisible(); - await expect(dashboardPage.manageProfile).toBeVisible(); - await expect(dashboardPage.settingsPageLink).toBeVisible(); - await expect(dashboardPage.helpAndSupport).toBeVisible(); - await expect(dashboardPage.signOut).toBeVisible(); - }); + await expect(dashboardPage.dashboardNavButton).toHaveAttribute( + "href", + "/user/dashboard", + ); + await expect(dashboardPage.FAQsNavButton).toHaveAttribute( + "href", + "https://support.mozilla.org/kb/firefox-monitor-faq", + ); + }); - test("Verify that the correct message is displayed on the Action Needed tab when all the exposures are fixed", async ({ - dashboardPage, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301511", + test("Verify that the site header and navigation bar is displayed correctly", async ({ + dashboardPage, + }) => { + // link to testrail + test.info().annotations.push( + { + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301511", + }, + { + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463567", + }, + ); + + // verify the navigation bar left side elements + await expect(dashboardPage.fireFoxMonitorLogoImgButton).toBeVisible(); + await expect(dashboardPage.dashboardNavButton).toBeVisible(); + await expect(dashboardPage.exposuresHeading).toBeVisible(); + await expect(dashboardPage.settingsPageLink).toBeVisible(); + await expect(dashboardPage.FAQsNavButton).toBeVisible(); + + // verify the site header elements + await expect(dashboardPage.actionNeededTab).toBeVisible(); + await expect(dashboardPage.fixedTab).toBeVisible(); + + // auto data removal button + await expect(dashboardPage.subscribeButton).toBeVisible(); + + // apps and services + await expect(dashboardPage.appsAndServices).toBeVisible(); + await dashboardPage.appsAndServices.click(); + await expect(dashboardPage.servicesVpn).toBeVisible(); + await expect(dashboardPage.servicesRelay).toBeVisible(); + await expect(dashboardPage.servicesPocket).toBeVisible(); + await expect(dashboardPage.servicesFirefoxDesktop).toBeVisible(); + await expect(dashboardPage.servicesFirefoxMobile).toBeVisible(); + + // profile button + await dashboardPage.closeAppsAndServices.click(); + await expect(dashboardPage.profileButton).toBeVisible(); + await dashboardPage.profileButton.click(); + await expect(dashboardPage.profileEmail).toBeVisible(); + await expect(dashboardPage.manageProfile).toBeVisible(); + await expect(dashboardPage.settingsPageLink).toBeVisible(); + await expect(dashboardPage.helpAndSupport).toBeVisible(); + await expect(dashboardPage.signOut).toBeVisible(); }); - // verify overview card - await expect(dashboardPage.dashboardMozLogo).toBeVisible(); + test("Verify that the correct message is displayed on the Action Needed tab when all the exposures are fixed", async ({ + dashboardPage, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301511", + }); - // TODO: add verifications for all fixed exposures state - }); + // verify overview card + await expect(dashboardPage.dashboardMozLogo).toBeVisible(); - test("Verify that the Fixed tab layout and tooltips are displayed correctly", async ({ - dashboardPage, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301532", + // TODO: add verifications for all fixed exposures state }); - // verify fixed tab's tooltips and popups - await dashboardPage.fixedTab.click(); + test("Verify that the Fixed tab layout and tooltips are displayed correctly", async ({ + dashboardPage, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301532", + }); - // verify tooltip - await expect(dashboardPage.fixedHeading).toBeVisible(); - await dashboardPage.chartTooltip.click(); - await expect(dashboardPage.aboutFixedExposuresPopup).toBeVisible(); - await dashboardPage.popupCloseButton.click(); - await expect(dashboardPage.aboutFixedExposuresPopup).toBeHidden(); - }); + // verify fixed tab's tooltips and popups + await dashboardPage.fixedTab.click(); - test("Verify that the Apps and Services header options work correctly.", async ({ - dashboardPage, - page, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463569", + // verify tooltip + await expect(dashboardPage.fixedHeading).toBeVisible(); + await dashboardPage.chartTooltip.click(); + await expect(dashboardPage.aboutFixedExposuresPopup).toBeVisible(); + await dashboardPage.popupCloseButton.click(); + await expect(dashboardPage.aboutFixedExposuresPopup).toBeHidden(); }); - await dashboardPage.fixedTab.click(); - expect(page.url()).toMatch(/.*dashboard\/fixed\/?/); - await dashboardPage.actionNeededTab.click(); - expect(page.url()).toMatch(/.*dashboard\/action-needed\/?/); - - //apps and services button check - const clickOnLinkAndGoBack = async ( - aTag: Locator, - host: string | RegExp = /.*/, - path: string | RegExp = /.*/, - ) => { - await expect(dashboardPage.appsAndServices).toBeVisible(); - await dashboardPage.appsAndServices.click(); - await expect(dashboardPage.appsAndServicesMenu).toBeVisible(); - await clickOnATagCheckDomain(aTag, host, path, page); - }; - - await clickOnLinkAndGoBack( - dashboardPage.servicesVpn, - "www.mozilla.org", - /.*\/products\/vpn\/?.*/, - ); - await clickOnLinkAndGoBack( - dashboardPage.servicesRelay, - "relay.firefox.com", - ); - await clickOnLinkAndGoBack( - dashboardPage.servicesPocket, - /getpocket\.com|apps\.apple\.com|app\.adjust\.com/, - /.*(\/pocket-and-firefox\/?).*|.*about.*|.*pocket-stay-informed.*/, - ); - await clickOnLinkAndGoBack( - dashboardPage.servicesFirefoxDesktop, - "www.mozilla.org", - /.*\/firefox\/new\/?.*/, - ); - await clickOnLinkAndGoBack( - dashboardPage.servicesFirefoxMobile, - "www.mozilla.org", - /.*\/browsers\/mobile\/?.*/, - ); - await clickOnLinkAndGoBack( - dashboardPage.servicesMozilla, - "www.mozilla.org", - ); + test("Verify that the Apps and Services header options work correctly.", async ({ + dashboardPage, + page, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463569", + }); - const openProfileMenuItem = async ( - what: Locator, - whatUrl: string | RegExp, - ) => { - await dashboardPage.open(); - await dashboardPage.profileButton.click(); - await expect(what).toBeVisible(); - if (await what.evaluate((e) => e.hasAttribute("href"))) { - const href = await what.getAttribute("href"); - expect(href).not.toBeNull(); - await page.goto(href!); - } else { - await what.click(); - } - await page.waitForURL(whatUrl); - }; + await dashboardPage.fixedTab.click(); + expect(page.url()).toMatch(/.*dashboard\/fixed\/?/); + await dashboardPage.actionNeededTab.click(); + expect(page.url()).toMatch(/.*dashboard\/action-needed\/?/); + + //apps and services button check + const clickOnLinkAndGoBack = async ( + aTag: Locator, + host: string | RegExp = /.*/, + path: string | RegExp = /.*/, + ) => { + await expect(dashboardPage.appsAndServices).toBeVisible(); + await dashboardPage.appsAndServices.click(); + await expect(dashboardPage.appsAndServicesMenu).toBeVisible(); + await clickOnATagCheckDomain(aTag, host, path, page); + }; + + await clickOnLinkAndGoBack( + dashboardPage.servicesVpn, + "www.mozilla.org", + /.*\/products\/vpn\/?.*/, + ); + await clickOnLinkAndGoBack( + dashboardPage.servicesRelay, + "relay.firefox.com", + ); + await clickOnLinkAndGoBack( + dashboardPage.servicesPocket, + /getpocket\.com|apps\.apple\.com|app\.adjust\.com/, + /.*(\/pocket-and-firefox\/?).*|.*about.*|.*pocket-stay-informed.*/, + ); + await clickOnLinkAndGoBack( + dashboardPage.servicesFirefoxDesktop, + "www.mozilla.org", + /.*\/firefox\/new\/?.*/, + ); + await clickOnLinkAndGoBack( + dashboardPage.servicesFirefoxMobile, + "www.mozilla.org", + /.*\/browsers\/mobile\/?.*/, + ); + await clickOnLinkAndGoBack( + dashboardPage.servicesMozilla, + "www.mozilla.org", + ); - await openProfileMenuItem( - dashboardPage.manageProfile, - /.*accounts.*settings.*/, - ); - await openProfileMenuItem( - dashboardPage.profileSettings, - /.*\/user\/settings.*/, - ); + const openProfileMenuItem = async ( + what: Locator, + whatUrl: string | RegExp, + ) => { + await dashboardPage.open(); + await dashboardPage.profileButton.click(); + await expect(what).toBeVisible(); + if (await what.evaluate((e) => e.hasAttribute("href"))) { + const href = await what.getAttribute("href"); + expect(href).not.toBeNull(); + await page.goto(href!); + } else { + await what.click(); + } + await page.waitForURL(whatUrl); + }; - const base_url = process.env["E2E_TEST_BASE_URL"]; - expect(base_url).toBeTruthy(); - await openProfileMenuItem(dashboardPage.profileSignOut, base_url!); - }); -}); + await openProfileMenuItem( + dashboardPage.manageProfile, + /.*accounts.*settings.*/, + ); + await openProfileMenuItem( + dashboardPage.profileSettings, + /.*\/user\/settings.*/, + ); + + const base_url = process.env["E2E_TEST_BASE_URL"]; + expect(base_url).toBeTruthy(); + await openProfileMenuItem(dashboardPage.profileSignOut, base_url!); + }); + }, +); // fix coming - playwright does not currently have access to the aws headers, skipping for now test.describe.skip( @@ -261,469 +264,487 @@ test.describe.skip( }, ); -test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Content @smoke`, () => { - test.beforeEach(async ({ dashboardPage, page }) => { - await dashboardPage.open(); - - try { - await checkAuthState(page); - } catch { - console.log("[E2E_LOG] - No fxa auth required, proceeding..."); - } - }); - - test("Verify that the exposure list contains action needed", async ({ - dashboardPage, - page, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301533", - }); +test.describe.skip( + `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Content @smoke`, + () => { + test.beforeEach(async ({ dashboardPage, page }) => { + await dashboardPage.open(); - await expect(dashboardPage.exposuresHeading).toBeVisible(); - const listCount = await page - .locator('//div[starts-with(@class, "StatusPill_pill")]') - .count(); - - // verify exposure list conatins only exposures that need to be fixed - if (listCount > 0) { - for (let i = 0; i < listCount; i++) { - await expect( - page.locator( - `(//div[starts-with(@class, 'StatusPill_pill')])[${i + 1}]`, - ), - ).toHaveText("Action needed"); + try { + await checkAuthState(page); + } catch { + console.log("[E2E_LOG] - No fxa auth required, proceeding..."); } - } - }); + }); - test("Verify that the exposure list contains only fixed and in progress cards", async ({ - dashboardPage, - page, - }) => { - // link to testrail - test.info().annotations.push( - { + test("Verify that the exposure list contains action needed", async ({ + dashboardPage, + page, + }) => { + // link to testrail + test.info().annotations.push({ type: "testrail", description: "https://testrail.stage.mozaws.net/index.php?/cases/view/2301533", - }, - { - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2546463", - }, - ); + }); - await expect(dashboardPage.exposuresHeading).toBeVisible(); - await dashboardPage.fixedTab.click(); - - // verify fixed or in-progress - await expect(dashboardPage.fixedHeading).toBeVisible(); - - // TODO: add stub to fill in fixed/in-progress items - const listCount = await page - .locator('//div[starts-with(@class, "StatusPill_pill")]') - .count(); - // verify exposure list contains only exposures that need to be fixed - if (listCount > 0) { - for (let i = 0; i < listCount; i++) { - await expect( - page.locator( - `(//div[starts-with(@class, "StatusPill_pill")])[${i + 1}]`, - ), - ).toHaveText(/In progress|Fixed/); + await expect(dashboardPage.exposuresHeading).toBeVisible(); + const listCount = await page + .locator('//div[starts-with(@class, "StatusPill_pill")]') + .count(); + + // verify exposure list conatins only exposures that need to be fixed + if (listCount > 0) { + for (let i = 0; i < listCount; i++) { + await expect( + page.locator( + `(//div[starts-with(@class, 'StatusPill_pill')])[${i + 1}]`, + ), + ).toHaveText("Action needed"); + } } - } - }); -}); - -test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Payment`, () => { - test.beforeEach(async ({ dashboardPage, page }) => { - await dashboardPage.open(); + }); - try { - await checkAuthState(page); - } catch { - console.log("[E2E_LOG] - No fxa auth required, proceeding..."); - } - }); + test("Verify that the exposure list contains only fixed and in progress cards", async ({ + dashboardPage, + page, + }) => { + // link to testrail + test.info().annotations.push( + { + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301533", + }, + { + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2546463", + }, + ); - test("Verify that the user can select what type of plan they want, verify that the Premium upsell modal is displayed correctly", async ({ - dashboardPage, - }) => { - test.info().annotations.push( - { - type: "testrail id #1", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301529", - }, - { - type: "testrail id #2", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463623", - }, - { - type: "testrail id #3", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463624", - }, - ); + await expect(dashboardPage.exposuresHeading).toBeVisible(); + await dashboardPage.fixedTab.click(); + + // verify fixed or in-progress + await expect(dashboardPage.fixedHeading).toBeVisible(); + + // TODO: add stub to fill in fixed/in-progress items + const listCount = await page + .locator('//div[starts-with(@class, "StatusPill_pill")]') + .count(); + // verify exposure list contains only exposures that need to be fixed + if (listCount > 0) { + for (let i = 0; i < listCount; i++) { + await expect( + page.locator( + `(//div[starts-with(@class, "StatusPill_pill")])[${i + 1}]`, + ), + ).toHaveText(/In progress|Fixed/); + } + } + }); + }, +); - await dashboardPage.subscribeButton.click(); - await dashboardPage.verifyPremiumUpsellModalOptions(); - }); -}); +test.describe.skip( + `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Payment`, + () => { + test.beforeEach(async ({ dashboardPage, page }) => { + await dashboardPage.open(); -test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Breaches Scan, Continuous Protection, Data Profile Actions`, () => { - test.use({ storageState: { cookies: [], origins: [] } }); + try { + await checkAuthState(page); + } catch { + console.log("[E2E_LOG] - No fxa auth required, proceeding..."); + } + }); - test.beforeEach(async ({ landingPage, page, authPage, welcomePage }) => { - test.slow( - true, - "this test runs through the welcome scan flow, increasing timeout to address it", - ); + test("Verify that the user can select what type of plan they want, verify that the Premium upsell modal is displayed correctly", async ({ + dashboardPage, + }) => { + test.info().annotations.push( + { + type: "testrail id #1", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301529", + }, + { + type: "testrail id #2", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463623", + }, + { + type: "testrail id #3", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463624", + }, + ); - // speed up test by ignoring non necessary requests - await page.route(/(analytics)/, async (route) => { - await route.abort(); + await dashboardPage.subscribeButton.click(); + await dashboardPage.verifyPremiumUpsellModalOptions(); }); + }, +); - await landingPage.open(); - await landingPage.goToSignIn(); +test.describe.skip( + `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Breaches Scan, Continuous Protection, Data Profile Actions`, + () => { + test.use({ storageState: { cookies: [], origins: [] } }); - const randomEmail = `_${Date.now()}@restmail.net`; - await authPage.signUp(randomEmail, page); + test.beforeEach(async ({ landingPage, page, authPage, welcomePage }) => { + test.slow( + true, + "this test runs through the welcome scan flow, increasing timeout to address it", + ); - await page.waitForURL("**/user/welcome"); - await welcomePage.goThroughFirstScan(); - expect(page.url()).toContain("/user/dashboard"); - }); + // speed up test by ignoring non necessary requests + await page.route(/(analytics)/, async (route) => { + await route.abort(); + }); - test("Verify that the Premium upsell modal is displayed correctly - Continuous Protection, verify that the user can mark Data broker profiles as fixed", async ({ - dashboardPage, - }) => { - test.info().annotations.push( - { - type: "testrail id #1", - description: - "(continuous protection step) https://testrail.stage.mozaws.net/index.php?/cases/view/2463623", - }, - { - type: "testrail id #2", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463591", - }, - ); - let initialExposuresCount = - (await dashboardPage.numExposures.textContent()) as string; - initialExposuresCount = removeUnicodeChars(initialExposuresCount); - - if (initialExposuresCount !== "0") { - await dashboardPage.allExposures.first().click(); - await dashboardPage.fixExposureButton.click(); - await dashboardPage.removeExposuresManually.click(); - await dashboardPage.reviewAndRemoveProfiles.waitFor(); - - const count = await dashboardPage.allExposures.count(); - // Fix first exposure - await dashboardPage.markAsFixed.click(); - - for (let i = 1; i < count; i++) { - const exposure = dashboardPage.allExposures.nth(i); - await exposure.click(); - - if (await dashboardPage.markAsFixed.isVisible()) { - await dashboardPage.markAsFixed.click(); - } - } + await landingPage.open(); + await landingPage.goToSignIn(); - await dashboardPage.skipExposureRemoval.click(); - } - - await dashboardPage.continuousProtectionButton.waitFor(); - await expect(dashboardPage.continuousProtectionButton).toBeVisible(); - await dashboardPage.continuousProtectionButton.click(); - await dashboardPage.verifyPremiumUpsellModalOptions(); - // Using toMatch to avoid invisible unicode chars mismatch - expect(await dashboardPage.numExposures.textContent()).toMatch("0"); - await dashboardPage.fixedTab.click(); - const fixedExposures = await dashboardPage.numFixed.textContent(); - expect(fixedExposures as string).toMatch(initialExposuresCount); - }); -}); + const randomEmail = `_${Date.now()}@restmail.net`; + await authPage.signUp(randomEmail, page); -test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Overview Card`, () => { - test.beforeEach(async ({ dashboardPage, page }) => { - await dashboardPage.open(); + await page.waitForURL("**/user/welcome"); + await welcomePage.goThroughFirstScan(); + expect(page.url()).toContain("/user/dashboard"); + }); - try { - await checkAuthState(page); - } catch { - console.log("[E2E_LOG] - No fxa auth required, proceeding..."); - } - }); + test("Verify that the Premium upsell modal is displayed correctly - Continuous Protection, verify that the user can mark Data broker profiles as fixed", async ({ + dashboardPage, + }) => { + test.info().annotations.push( + { + type: "testrail id #1", + description: + "(continuous protection step) https://testrail.stage.mozaws.net/index.php?/cases/view/2463623", + }, + { + type: "testrail id #2", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463591", + }, + ); + let initialExposuresCount = + (await dashboardPage.numExposures.textContent()) as string; + initialExposuresCount = removeUnicodeChars(initialExposuresCount); + + if (initialExposuresCount !== "0") { + await dashboardPage.allExposures.first().click(); + await dashboardPage.fixExposureButton.click(); + await dashboardPage.removeExposuresManually.click(); + await dashboardPage.reviewAndRemoveProfiles.waitFor(); + + const count = await dashboardPage.allExposures.count(); + // Fix first exposure + await dashboardPage.markAsFixed.click(); + + for (let i = 1; i < count; i++) { + const exposure = dashboardPage.allExposures.nth(i); + await exposure.click(); + + if (await dashboardPage.markAsFixed.isVisible()) { + await dashboardPage.markAsFixed.click(); + } + } - test("Verify that the Premium upsell screen is displayed correctly - overview card", async ({ - dashboardPage, - automaticRemovePage, - dataBrokersPage, - page, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463625", + await dashboardPage.skipExposureRemoval.click(); + } + + await dashboardPage.continuousProtectionButton.waitFor(); + await expect(dashboardPage.continuousProtectionButton).toBeVisible(); + await dashboardPage.continuousProtectionButton.click(); + await dashboardPage.verifyPremiumUpsellModalOptions(); + // Using toMatch to avoid invisible unicode chars mismatch + expect(await dashboardPage.numExposures.textContent()).toMatch("0"); + await dashboardPage.fixedTab.click(); + const fixedExposures = await dashboardPage.numFixed.textContent(); + expect(fixedExposures as string).toMatch(initialExposuresCount); }); + }, +); - //checking that the user can reach upsell page - await dashboardPage.goToDashboard(); - await expect(dashboardPage.upsellScreenButton).toBeVisible(); - await dashboardPage.upsellScreenButton.click(); - await page.waitForURL(/.*\/fix\/.*\/view-data-brokers\/?/); - await dataBrokersPage.removeThemForMeButton.click(); - await page.waitForURL(/.*\/fix\/.*\/automatic-remove\/?/); - - //checking the bullet points - await expect(automaticRemovePage.ulElement).toBeVisible(); - - for (const itemText of automaticRemovePage.bulletPointsExpected) { - const liElement = automaticRemovePage.liElements.getByText(itemText); - await expect(liElement).toBeVisible(); - } - - //testing that toggles work - await automaticRemovePage.planToggle0.click(); - const price0 = await automaticRemovePage.price.textContent(); - const plan0 = await automaticRemovePage.plan.textContent(); - await automaticRemovePage.planToggle1.click(); - const price1 = await automaticRemovePage.price.textContent(); - const plan1 = await automaticRemovePage.plan.textContent(); - expect(price0).not.toEqual(price1); - expect(plan0).not.toEqual(plan1); - }); +test.describe.skip( + `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Overview Card`, + () => { + test.beforeEach(async ({ dashboardPage, page }) => { + await dashboardPage.open(); - test("Verify that the navigation of the Premium upsell screen works correctly - from overview card", async ({ - dashboardPage, - automaticRemovePage, - dataBrokersPage, - page, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463626", + try { + await checkAuthState(page); + } catch { + console.log("[E2E_LOG] - No fxa auth required, proceeding..."); + } }); - await dashboardPage.open(); - await page.waitForURL("**/dashboard/**"); - - //get the number of exposures count - const overviewCardSummary = - await dashboardPage.overviewCardSummary.textContent(); - const overviewCardFindings = - await dashboardPage.overviewCardFindings.textContent(); - expect(overviewCardFindings).not.toContain("No exposures found"); - expect(overviewCardSummary).not.toBeNull(); - const exposuresCountMatches = overviewCardSummary!.match(/\d+/); - expect(exposuresCountMatches).toBeTruthy(); - expect(exposuresCountMatches!.length).toBeGreaterThan(0); - const exposuresCount = parseInt(exposuresCountMatches![0]); - - //check that premium upsell screen loads - await dashboardPage.upsellScreenButton.click(); - await page.waitForURL(/.*\/fix\/.*\/view-data-brokers\/?/); - await dataBrokersPage.removeThemForMeButton.click(); - await page.waitForURL(/.*\/fix\/.*\/automatic-remove\/?/); - - //check that X returns back to /dashboard - await expect(automaticRemovePage.xButton).toBeVisible(); - - await automaticRemovePage.xButton.click(); - await page.waitForURL(dashboardPage.urlRegex); - - //forward arrow checks - await automaticRemovePage.open(); - await expect(automaticRemovePage.forwardArrowButton).toBeVisible(); - - const breachString0 = "high-risk-data-breaches"; - const breachString1 = "leaked-passwords"; - const breachString2 = "security-recommendations"; - - const breachOrDashboard = (excludeThis: string) => { - const escapedExclude = escapeRegExp(excludeThis); - const pattern = [ - dashboardPage.urlRegex.source, - breachString0, - breachString1, - breachString2, - ] - .map((s) => `.*${s}.*`) - .join("|"); - - return new RegExp(`^(?!.*${escapedExclude})(${pattern})`); - }; - - const checkBreachLink = async () => { - const currentUrl = page.url(); - await automaticRemovePage.forwardArrowButton.click(); - await page.waitForURL(breachOrDashboard(currentUrl)); - const urlToCheck = page.url(); - const breachStringRE = new RegExp( - `.*(${[breachString0, breachString1, breachString2].join("|")}).*`, - ); - return breachStringRE.test(urlToCheck); - }; + test("Verify that the Premium upsell screen is displayed correctly - overview card", async ({ + dashboardPage, + automaticRemovePage, + dataBrokersPage, + page, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463625", + }); - let iter = 0; - while (await checkBreachLink()) iter++; - const visitedBreachPages = iter !== 0; - const exposuresExist = exposuresCount !== 0; - expect(visitedBreachPages).toBe(exposuresExist); + //checking that the user can reach upsell page + await dashboardPage.goToDashboard(); + await expect(dashboardPage.upsellScreenButton).toBeVisible(); + await dashboardPage.upsellScreenButton.click(); + await page.waitForURL(/.*\/fix\/.*\/view-data-brokers\/?/); + await dataBrokersPage.removeThemForMeButton.click(); + await page.waitForURL(/.*\/fix\/.*\/automatic-remove\/?/); - //price&plan toggle checks - await automaticRemovePage.open(); - const subplatRegex = /\/products\/prod_/; + //checking the bullet points + await expect(automaticRemovePage.ulElement).toBeVisible(); - const checkToggleButtonWorks = async (toggleButton: Locator) => { - await automaticRemovePage.open(); - await expect(toggleButton).toBeVisible(); - await toggleButton.click(); - const toggleText = await toggleButton.textContent(); - expect(toggleText).not.toBeNull(); - await automaticRemovePage.subplatButton.click(); - await page.waitForURL(subplatRegex); - return page.url(); - }; - - const subplat0 = await checkToggleButtonWorks( - automaticRemovePage.planToggle0, - ); - const subplat1 = await checkToggleButtonWorks( - automaticRemovePage.planToggle1, - ); - expect(subplat0).not.toBe(subplat1); - }); -}); - -test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Footer`, () => { - test.beforeEach(async ({ dashboardPage, page }) => { - await dashboardPage.open(); - try { - await checkAuthState(page); - } catch { - console.log("[E2E_LOG] - No fxa auth required, proceeding..."); - } - }); + for (const itemText of automaticRemovePage.bulletPointsExpected) { + const liElement = automaticRemovePage.liElements.getByText(itemText); + await expect(liElement).toBeVisible(); + } - test("Verify that the site footer is displayed correctly", async ({ - dashboardPage, - page, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463570", + //testing that toggles work + await automaticRemovePage.planToggle0.click(); + const price0 = await automaticRemovePage.price.textContent(); + const plan0 = await automaticRemovePage.plan.textContent(); + await automaticRemovePage.planToggle1.click(); + const price1 = await automaticRemovePage.price.textContent(); + const plan1 = await automaticRemovePage.plan.textContent(); + expect(price0).not.toEqual(price1); + expect(plan0).not.toEqual(plan1); }); - expect(process.env["E2E_TEST_BASE_URL"]).toBeTruthy(); - const baseUrl = process.env["E2E_TEST_BASE_URL"]!; - await dashboardPage.goToDashboard(); - await expect(page.locator("footer a >> img")).toBeVisible(); - await clickOnATagCheckDomain( - dashboardPage.mozillaLogoFooter, - "www.mozilla.org", - /^(\/en-US\/)?$/, - page, - ); - await clickOnATagCheckDomain( - dashboardPage.allBreachesFooter, - baseUrl, - "/breaches", + test("Verify that the navigation of the Premium upsell screen works correctly - from overview card", async ({ + dashboardPage, + automaticRemovePage, + dataBrokersPage, page, - ); - await clickOnATagCheckDomain( - dashboardPage.faqsFooter, - "support.mozilla.org", - /.*\/kb.*\/mozilla-monitor-faq.*/, - page, - ); - await clickOnATagCheckDomain( - dashboardPage.termsOfServiceFooter, - "www.mozilla.org", - "/about/legal/terms/subscription-services/", - page, - ); - await clickOnATagCheckDomain( - dashboardPage.privacyNoticeFooter, - "www.mozilla.org", - "/privacy/subscription-services/", - page, - ); - await clickOnATagCheckDomain( - dashboardPage.githubFooter, - "github.com", - "/mozilla/blurts-server", + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463626", + }); + + await dashboardPage.open(); + await page.waitForURL("**/dashboard/**"); + + //get the number of exposures count + const overviewCardSummary = + await dashboardPage.overviewCardSummary.textContent(); + const overviewCardFindings = + await dashboardPage.overviewCardFindings.textContent(); + expect(overviewCardFindings).not.toContain("No exposures found"); + expect(overviewCardSummary).not.toBeNull(); + const exposuresCountMatches = overviewCardSummary!.match(/\d+/); + expect(exposuresCountMatches).toBeTruthy(); + expect(exposuresCountMatches!.length).toBeGreaterThan(0); + const exposuresCount = parseInt(exposuresCountMatches![0]); + + //check that premium upsell screen loads + await dashboardPage.upsellScreenButton.click(); + await page.waitForURL(/.*\/fix\/.*\/view-data-brokers\/?/); + await dataBrokersPage.removeThemForMeButton.click(); + await page.waitForURL(/.*\/fix\/.*\/automatic-remove\/?/); + + //check that X returns back to /dashboard + await expect(automaticRemovePage.xButton).toBeVisible(); + + await automaticRemovePage.xButton.click(); + await page.waitForURL(dashboardPage.urlRegex); + + //forward arrow checks + await automaticRemovePage.open(); + await expect(automaticRemovePage.forwardArrowButton).toBeVisible(); + + const breachString0 = "high-risk-data-breaches"; + const breachString1 = "leaked-passwords"; + const breachString2 = "security-recommendations"; + + const breachOrDashboard = (excludeThis: string) => { + const escapedExclude = escapeRegExp(excludeThis); + const pattern = [ + dashboardPage.urlRegex.source, + breachString0, + breachString1, + breachString2, + ] + .map((s) => `.*${s}.*`) + .join("|"); + + return new RegExp(`^(?!.*${escapedExclude})(${pattern})`); + }; + + const checkBreachLink = async () => { + const currentUrl = page.url(); + await automaticRemovePage.forwardArrowButton.click(); + await page.waitForURL(breachOrDashboard(currentUrl)); + const urlToCheck = page.url(); + const breachStringRE = new RegExp( + `.*(${[breachString0, breachString1, breachString2].join("|")}).*`, + ); + return breachStringRE.test(urlToCheck); + }; + + let iter = 0; + while (await checkBreachLink()) iter++; + const visitedBreachPages = iter !== 0; + const exposuresExist = exposuresCount !== 0; + expect(visitedBreachPages).toBe(exposuresExist); + + //price&plan toggle checks + await automaticRemovePage.open(); + const subplatRegex = /\/products\/prod_/; + + const checkToggleButtonWorks = async (toggleButton: Locator) => { + await automaticRemovePage.open(); + await expect(toggleButton).toBeVisible(); + await toggleButton.click(); + const toggleText = await toggleButton.textContent(); + expect(toggleText).not.toBeNull(); + await automaticRemovePage.subplatButton.click(); + await page.waitForURL(subplatRegex); + return page.url(); + }; + + const subplat0 = await checkToggleButtonWorks( + automaticRemovePage.planToggle0, + ); + const subplat1 = await checkToggleButtonWorks( + automaticRemovePage.planToggle1, + ); + expect(subplat0).not.toBe(subplat1); + }); + }, +); + +test.describe.skip( + `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Footer`, + () => { + test.beforeEach(async ({ dashboardPage, page }) => { + await dashboardPage.open(); + try { + await checkAuthState(page); + } catch { + console.log("[E2E_LOG] - No fxa auth required, proceeding..."); + } + }); + + test("Verify that the site footer is displayed correctly", async ({ + dashboardPage, page, - ); - }); -}); + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463570", + }); -test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Navigation @smoke`, () => { - test.beforeEach(async ({ dashboardPage, page }) => { - await dashboardPage.open(); + expect(process.env["E2E_TEST_BASE_URL"]).toBeTruthy(); + const baseUrl = process.env["E2E_TEST_BASE_URL"]!; + await dashboardPage.goToDashboard(); + await expect(page.locator("footer a >> img")).toBeVisible(); + await clickOnATagCheckDomain( + dashboardPage.mozillaLogoFooter, + "www.mozilla.org", + /^(\/en-US\/)?$/, + page, + ); + await clickOnATagCheckDomain( + dashboardPage.allBreachesFooter, + baseUrl, + "/breaches", + page, + ); + await clickOnATagCheckDomain( + dashboardPage.faqsFooter, + "support.mozilla.org", + /.*\/kb.*\/mozilla-monitor-faq.*/, + page, + ); + await clickOnATagCheckDomain( + dashboardPage.termsOfServiceFooter, + "www.mozilla.org", + "/about/legal/terms/subscription-services/", + page, + ); + await clickOnATagCheckDomain( + dashboardPage.privacyNoticeFooter, + "www.mozilla.org", + "/privacy/subscription-services/", + page, + ); + await clickOnATagCheckDomain( + dashboardPage.githubFooter, + "github.com", + "/mozilla/blurts-server", + page, + ); + }); + }, +); - try { - await checkAuthState(page); - } catch { - console.log("[E2E_LOG] - No fxa auth required, proceeding..."); - } - }); +test.describe.skip( + `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Navigation @smoke`, + () => { + test.beforeEach(async ({ dashboardPage, page }) => { + await dashboardPage.open(); - test("Verify that the navigation bar options work correctly", async ({ - dashboardPage, - page, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463568", + try { + await checkAuthState(page); + } catch { + console.log("[E2E_LOG] - No fxa auth required, proceeding..."); + } }); - const goToHrefOf = async (aTag: Locator) => { - const href = await aTag.getAttribute("href"); - expect(href).toBeTruthy(); - await page.goto(href!); - }; - - //testrail's step 1 - await dashboardPage.goToDashboard(); - await goToHrefOf(dashboardPage.settingsPageLink); - await expect(page).toHaveURL(/\/settings$/); - - //testrail's step 2 - await goToHrefOf(dashboardPage.dashboardPageLink); - await expect(page).toHaveURL(/.*\/dashboard.*/); - - // testrail's step 3 - await dashboardPage.goToSettings(); - await goToHrefOf(dashboardPage.fireFoxMonitorLogoAtag); - await expect(page).toHaveURL(/.*\/dashboard.*/); - - //testrail's step 4 - await dashboardPage.goToDashboard(); - await goToHrefOf(dashboardPage.faqsPageLink); - await expect(page).toHaveURL( - /.*support\.mozilla\.org.*\/kb\/.*firefox-monitor-faq.*/, - ); - }); -}); + test("Verify that the navigation bar options work correctly", async ({ + dashboardPage, + page, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463568", + }); + + const goToHrefOf = async (aTag: Locator) => { + const href = await aTag.getAttribute("href"); + expect(href).toBeTruthy(); + await page.goto(href!); + }; + + //testrail's step 1 + await dashboardPage.goToDashboard(); + await goToHrefOf(dashboardPage.settingsPageLink); + await expect(page).toHaveURL(/\/settings$/); + + //testrail's step 2 + await goToHrefOf(dashboardPage.dashboardPageLink); + await expect(page).toHaveURL(/.*\/dashboard.*/); + + // testrail's step 3 + await dashboardPage.goToSettings(); + await goToHrefOf(dashboardPage.fireFoxMonitorLogoAtag); + await expect(page).toHaveURL(/.*\/dashboard.*/); + + //testrail's step 4 + await dashboardPage.goToDashboard(); + await goToHrefOf(dashboardPage.faqsPageLink); + await expect(page).toHaveURL( + /.*support\.mozilla\.org.*\/kb\/.*firefox-monitor-faq.*/, + ); + }); + }, +); // These tests rely heavily on mocks test.skip(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Data Breaches`, () => { diff --git a/src/e2e/specs/landing.spec.ts b/src/e2e/specs/landing.spec.ts index bd453cc7f46..ceed1323585 100644 --- a/src/e2e/specs/landing.spec.ts +++ b/src/e2e/specs/landing.spec.ts @@ -10,379 +10,398 @@ import { } from "../utils/helpers.js"; test.describe.configure({ mode: "parallel" }); -test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, () => { - test.beforeEach(async ({ landingPage }) => { - await landingPage.open(); - }); - - test("Observe page header", async ({ landingPage, page }) => { - // link to testrail case - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", +test.describe.skip( + `${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, + () => { + test.beforeEach(async ({ landingPage }) => { + await landingPage.open(); }); - await expect(landingPage.monitorLandingHeader).toBeVisible(); - await landingPage.signInButton.click(); - await page.waitForURL("**/oauth/**"); - expect(page.url()).toContain("oauth"); - }); - - test('Observe "Find where your private info is exposed and take it back" section', async ({ - landingPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", - }); + test("Observe page header", async ({ landingPage, page }) => { + // link to testrail case + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", + }); - await expect(landingPage.monitorHeroTitle).toBeVisible(); - await expect(landingPage.monitorHeroSubtitle).toHaveText( - "We scan to see if your phone number, passwords or home address have been leaked, and help you make it private again.", - ); - if (await emailInputShouldExist(landingPage)) { - await expect(landingPage.monitorHeroFormEmailInputField).toBeVisible(); - await expect(landingPage.monitorHeroFormInputSubmitButton).toBeVisible(); - } - await expect(landingPage.monitorLandingMidHeading).toBeVisible(); - }); - - test('Observe "We will help you fix your exposures" section', async ({ - landingPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", + await expect(landingPage.monitorLandingHeader).toBeVisible(); + await landingPage.signInButton.click(); + await page.waitForURL("**/oauth/**"); + expect(page.url()).toContain("oauth"); }); - await expect(landingPage.fixExposuresTitle).toBeVisible(); - await expect(landingPage.fixExposuresSubtitle).toBeVisible(); - if (await emailInputShouldExist(landingPage)) { - await expect(landingPage.fixExposuresFormEmailInputField).toBeVisible(); - await expect(landingPage.fixExposuresFormInputSubmitButton).toBeVisible(); - } - await expect(landingPage.fixExposuresGraphic).toBeVisible(); - }); - - test('Observe "What info could be at risk?" section', async ({ - landingPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", - }); + test('Observe "Find where your private info is exposed and take it back" section', async ({ + landingPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", + }); - await expect(landingPage.couldBeAtRiskTitle).toBeVisible(); - await expect(landingPage.couldBeAtRiskSubtitle).toBeVisible(); - if (await emailInputShouldExist(landingPage)) { - await expect(landingPage.couldBeAtRiskFormEmailInputField).toBeVisible(); - } - await expect(landingPage.couldBeAtRiskFormInputSubmitButton).toBeVisible(); - await expect(landingPage.couldBeAtRiskGraphic).toBeVisible(); - }); - - test('Observe "Scan your email to get started" section', async ({ - landingPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", + await expect(landingPage.monitorHeroTitle).toBeVisible(); + await expect(landingPage.monitorHeroSubtitle).toHaveText( + "We scan to see if your phone number, passwords or home address have been leaked, and help you make it private again.", + ); + if (await emailInputShouldExist(landingPage)) { + await expect(landingPage.monitorHeroFormEmailInputField).toBeVisible(); + await expect( + landingPage.monitorHeroFormInputSubmitButton, + ).toBeVisible(); + } + await expect(landingPage.monitorLandingMidHeading).toBeVisible(); }); - await expect(landingPage.getStartedScanTitle).toBeVisible(); - if (await emailInputShouldExist(landingPage)) - await expect(landingPage.getStartedScanFormEmailInputField).toBeVisible(); - await expect(landingPage.getStartedScanFormSubmitButton).toBeVisible(); - }); - - test('Observe "Choose your level of protection" section', async ({ - landingPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", - }); + test('Observe "We will help you fix your exposures" section', async ({ + landingPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", + }); - await expect(landingPage.chooseLevelSection).toHaveScreenshot( - `${process.env.E2E_TEST_ENV}-chooseLevelSection.png`, - defaultScreenshotOpts, - ); - }); - - test("Observe FAQ section", async ({ landingPage }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", + await expect(landingPage.fixExposuresTitle).toBeVisible(); + await expect(landingPage.fixExposuresSubtitle).toBeVisible(); + if (await emailInputShouldExist(landingPage)) { + await expect(landingPage.fixExposuresFormEmailInputField).toBeVisible(); + await expect( + landingPage.fixExposuresFormInputSubmitButton, + ).toBeVisible(); + } + await expect(landingPage.fixExposuresGraphic).toBeVisible(); }); - await expect(landingPage.faqSection).toHaveScreenshot( - `${process.env.E2E_TEST_ENV}-faqSection.png`, - defaultScreenshotOpts, - ); - }); - - test('Observe "Take back control of your data" section', async ({ - landingPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", - }); + test('Observe "What info could be at risk?" section', async ({ + landingPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", + }); - await expect(landingPage.takeBackControlTitle).toBeVisible(); - if (await emailInputShouldExist(landingPage)) { + await expect(landingPage.couldBeAtRiskTitle).toBeVisible(); + await expect(landingPage.couldBeAtRiskSubtitle).toBeVisible(); + if (await emailInputShouldExist(landingPage)) { + await expect( + landingPage.couldBeAtRiskFormEmailInputField, + ).toBeVisible(); + } await expect( - landingPage.takeBackControlFormEmailInputField, + landingPage.couldBeAtRiskFormInputSubmitButton, ).toBeVisible(); - await expect(landingPage.takeBackControlFormSubmitButton).toBeVisible(); - } - }); - - test("Observe footer section", async ({ landingPage }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", + await expect(landingPage.couldBeAtRiskGraphic).toBeVisible(); }); - await expect(landingPage.mozillaFooterLogoLink).toBeVisible(); - await expect(landingPage.faqLink).toBeVisible(); - await expect(landingPage.termsLink).toBeVisible(); - await expect(landingPage.privacyLink).toBeVisible(); - await expect(landingPage.githubLink).toBeVisible(); - }); - - test("Verify the 'Get data removal' button UI and functionality for both yearly and monthly options", async ({ - landingPage, - purchasePage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463525", - }); + test('Observe "Scan your email to get started" section', async ({ + landingPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", + }); - await expect(landingPage.getDataRemoval).toBeVisible(); - await expect(landingPage.getDataRemovalMonthly).toBeVisible(); - await expect(landingPage.getDataRemovalYearly).toBeVisible(); - - // Monthly - await landingPage.getDataRemovalMonthly.click(); - await landingPage.getDataRemoval.click(); - await purchasePage.verifyMonthlyPlanDetails(); - - // Yearly - await landingPage.open(); - await landingPage.getDataRemoval.click(); - await purchasePage.verifyYearlyPlanDetails(); - }); - - test('Verify the "Get free scan" corresponding email fields', async ({ - landingPage, - authPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463504", + await expect(landingPage.getStartedScanTitle).toBeVisible(); + if (await emailInputShouldExist(landingPage)) + await expect( + landingPage.getStartedScanFormEmailInputField, + ).toBeVisible(); + await expect(landingPage.getStartedScanFormSubmitButton).toBeVisible(); }); - if (await emailInputShouldExist(landingPage)) { - ///free-scan-cta experiment is off - await landingPage.monitorHeroFormEmailInputField.fill("invalid"); - await landingPage.monitorHeroFormInputSubmitButton.click(); - await expect(landingPage.monitorHeroFormEmailInputField).toBeVisible(); - - const randomEmail = `_${Date.now()}_tstact@restmail.net`; - await landingPage.monitorHeroFormEmailInputField.fill(randomEmail); - await landingPage.monitorHeroFormInputSubmitButton.click(); - await authPage.passwordInputField.waitFor(); - await expect(authPage.passwordInputField).toBeVisible(); - } else { - ///free-scan-cta experiment is on - await landingPage.monitorHeroFormInputSubmitButton.click(); - await authPage.emailInputField.waitFor({ - state: "visible", - timeout: 10000, + + test('Observe "Choose your level of protection" section', async ({ + landingPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", }); - const randomEmail = `_${Date.now()}_tstact@restmail.net`; - await authPage.emailInputField.fill(randomEmail); - await authPage.continueButton.click(); - await authPage.passwordInputField.waitFor(); - await expect(authPage.passwordInputField).toBeVisible(); - } - }); - - test('Verify manual/automatic removal "more info" tips from "Choose your level of protection" section', async ({ - landingPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463504", + + await expect(landingPage.chooseLevelSection).toHaveScreenshot( + `${process.env.E2E_TEST_ENV}-chooseLevelSection.png`, + defaultScreenshotOpts, + ); }); - await landingPage.freeMonitoringTooltipTrigger.click(); - await expect(landingPage.freeMonitoringTooltipText).toBeVisible(); - await landingPage.closeTooltips.click(); - await landingPage.monitorPlusTooltipTrigger.click(); - await expect(landingPage.monitorPlusTooltipText).toBeVisible(); - }); -}); -test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page Functionality - without existing Account`, () => { - test.beforeEach(async ({ landingPage }) => { - await landingPage.open(); - }); - - test('Verify "Get free scan" buttons functionality without existing account', async ({ - landingPage, - page, - authPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463502", + test("Observe FAQ section", async ({ landingPage }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", + }); + + await expect(landingPage.faqSection).toHaveScreenshot( + `${process.env.E2E_TEST_ENV}-faqSection.png`, + defaultScreenshotOpts, + ); }); - const randomEmail = `${Date.now()}_tstact@restmail.net`; - if (await emailInputShouldExist(landingPage)) { - await landingPage.monitorHeroFormEmailInputField.fill(randomEmail); - await landingPage.monitorHeroFormInputSubmitButton.click(); - await page.waitForURL("**/oauth/**"); - } else { - await landingPage.monitorHeroFormInputSubmitButton.click(); - await authPage.emailInputField.waitFor({ - state: "visible", - timeout: 10000, + test('Observe "Take back control of your data" section', async ({ + landingPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", }); - await authPage.emailInputField.fill(randomEmail); - await authPage.continueButton.click(); - } - // continue with the common steps - await authPage.passwordInputField.fill( - process.env.E2E_TEST_ACCOUNT_PASSWORD as string, - ); - await authPage.passwordConfirmInputField.fill( - process.env.E2E_TEST_ACCOUNT_PASSWORD as string, - ); - await authPage.ageInputField.fill("31"); - await authPage.continueButton.click(); - const vc = await getVerificationCode(randomEmail, page); - await authPage.enterVerificationCode(vc); - const successUrl = process.env.E2E_TEST_BASE_URL + "/user/welcome"; - expect(page.url()).toBe(successUrl); - }); - - test('Verify the "Start free monitoring" button UI and functionality without existing account', async ({ - landingPage, - page, - authPage, - }) => { - test.info().annotations.push( - { - type: "testrail id #1", + + await expect(landingPage.takeBackControlTitle).toBeVisible(); + if (await emailInputShouldExist(landingPage)) { + await expect( + landingPage.takeBackControlFormEmailInputField, + ).toBeVisible(); + await expect(landingPage.takeBackControlFormSubmitButton).toBeVisible(); + } + }); + + test("Observe footer section", async ({ landingPage }) => { + test.info().annotations.push({ + type: "testrail", description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463524", - }, - { - type: "testrail id #2", + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", + }); + + await expect(landingPage.mozillaFooterLogoLink).toBeVisible(); + await expect(landingPage.faqLink).toBeVisible(); + await expect(landingPage.termsLink).toBeVisible(); + await expect(landingPage.privacyLink).toBeVisible(); + await expect(landingPage.githubLink).toBeVisible(); + }); + + test("Verify the 'Get data removal' button UI and functionality for both yearly and monthly options", async ({ + landingPage, + purchasePage, + }) => { + test.info().annotations.push({ + type: "testrail", description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463564", - }, - ); + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463525", + }); - await landingPage.startFreeMonitoringButton.click(); + await expect(landingPage.getDataRemoval).toBeVisible(); + await expect(landingPage.getDataRemovalMonthly).toBeVisible(); + await expect(landingPage.getDataRemovalYearly).toBeVisible(); - const randomEmail = `${Date.now()}_tstact@restmail.net`; - await authPage.signUp(randomEmail, page); + // Monthly + await landingPage.getDataRemovalMonthly.click(); + await landingPage.getDataRemoval.click(); + await purchasePage.verifyMonthlyPlanDetails(); - const successUrl = process.env.E2E_TEST_BASE_URL + "/user/welcome"; - expect(page.url()).toBe(successUrl); - }); -}); + // Yearly + await landingPage.open(); + await landingPage.getDataRemoval.click(); + await purchasePage.verifyYearlyPlanDetails(); + }); -test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page Functionality - with existing account`, () => { - test.beforeEach(async ({ landingPage }) => { - await landingPage.open(); - }); - - test('Verify "Get free scan" buttons functionality with existing account', async ({ - landingPage, - page, - authPage, - }) => { - // link to testrail case - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463503", + test('Verify the "Get free scan" corresponding email fields', async ({ + landingPage, + authPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463504", + }); + if (await emailInputShouldExist(landingPage)) { + ///free-scan-cta experiment is off + await landingPage.monitorHeroFormEmailInputField.fill("invalid"); + await landingPage.monitorHeroFormInputSubmitButton.click(); + await expect(landingPage.monitorHeroFormEmailInputField).toBeVisible(); + + const randomEmail = `_${Date.now()}_tstact@restmail.net`; + await landingPage.monitorHeroFormEmailInputField.fill(randomEmail); + await landingPage.monitorHeroFormInputSubmitButton.click(); + await authPage.passwordInputField.waitFor(); + await expect(authPage.passwordInputField).toBeVisible(); + } else { + ///free-scan-cta experiment is on + await landingPage.monitorHeroFormInputSubmitButton.click(); + await authPage.emailInputField.waitFor({ + state: "visible", + timeout: 10000, + }); + const randomEmail = `_${Date.now()}_tstact@restmail.net`; + await authPage.emailInputField.fill(randomEmail); + await authPage.continueButton.click(); + await authPage.passwordInputField.waitFor(); + await expect(authPage.passwordInputField).toBeVisible(); + } }); - const existingEmail = process.env.E2E_TEST_ACCOUNT_EMAIL as string; + test('Verify manual/automatic removal "more info" tips from "Choose your level of protection" section', async ({ + landingPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463504", + }); + await landingPage.freeMonitoringTooltipTrigger.click(); + await expect(landingPage.freeMonitoringTooltipText).toBeVisible(); + await landingPage.closeTooltips.click(); + await landingPage.monitorPlusTooltipTrigger.click(); + await expect(landingPage.monitorPlusTooltipText).toBeVisible(); + }); + }, +); + +test.describe.skip( + `${process.env.E2E_TEST_ENV} - Verify the Landing Page Functionality - without existing Account`, + () => { + test.beforeEach(async ({ landingPage }) => { + await landingPage.open(); + }); - if (await emailInputShouldExist(landingPage)) { - // Scenario where the form is still used - await landingPage.monitorHeroFormEmailInputField.fill(existingEmail); - await landingPage.monitorHeroFormInputSubmitButton.click(); - await page.waitForURL("**/oauth/**"); - } else { - // Scenario where direct redirection happens - await landingPage.monitorHeroFormInputSubmitButton.click(); - await authPage.emailInputField.waitFor({ - state: "visible", - timeout: 10000, + test('Verify "Get free scan" buttons functionality without existing account', async ({ + landingPage, + page, + authPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463502", }); - await authPage.emailInputField.fill(existingEmail); + + const randomEmail = `${Date.now()}_tstact@restmail.net`; + if (await emailInputShouldExist(landingPage)) { + await landingPage.monitorHeroFormEmailInputField.fill(randomEmail); + await landingPage.monitorHeroFormInputSubmitButton.click(); + await page.waitForURL("**/oauth/**"); + } else { + await landingPage.monitorHeroFormInputSubmitButton.click(); + await authPage.emailInputField.waitFor({ + state: "visible", + timeout: 10000, + }); + await authPage.emailInputField.fill(randomEmail); + await authPage.continueButton.click(); + } + // continue with the common steps + await authPage.passwordInputField.fill( + process.env.E2E_TEST_ACCOUNT_PASSWORD as string, + ); + await authPage.passwordConfirmInputField.fill( + process.env.E2E_TEST_ACCOUNT_PASSWORD as string, + ); + await authPage.ageInputField.fill("31"); await authPage.continueButton.click(); - } - - // complete sign in form - await authPage.enterPassword(); - - // verify dashboard redirect - const successUrl = - process.env.E2E_TEST_BASE_URL + - (process.env.E2E_TEST_ENV === "local" - ? "/user/welcome" - : "/user/dashboard"); - expect(page.url()).toBe(successUrl); - }); - - test('Verify the "Start free monitoring" button UI and functionality with existing account', async ({ - landingPage, - page, - authPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463524", + const vc = await getVerificationCode(randomEmail, page); + await authPage.enterVerificationCode(vc); + const successUrl = process.env.E2E_TEST_BASE_URL + "/user/welcome"; + expect(page.url()).toBe(successUrl); }); - await landingPage.startFreeMonitoringButton.click(); + test('Verify the "Start free monitoring" button UI and functionality without existing account', async ({ + landingPage, + page, + authPage, + }) => { + test.info().annotations.push( + { + type: "testrail id #1", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463524", + }, + { + type: "testrail id #2", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463564", + }, + ); + + await landingPage.startFreeMonitoringButton.click(); + + const randomEmail = `${Date.now()}_tstact@restmail.net`; + await authPage.signUp(randomEmail, page); + + const successUrl = process.env.E2E_TEST_BASE_URL + "/user/welcome"; + expect(page.url()).toBe(successUrl); + }); + }, +); + +test.describe.skip( + `${process.env.E2E_TEST_ENV} - Verify the Landing Page Functionality - with existing account`, + () => { + test.beforeEach(async ({ landingPage }) => { + await landingPage.open(); + }); - await authPage.enterEmail(process.env.E2E_TEST_ACCOUNT_EMAIL as string); - await authPage.enterPassword(); + test('Verify "Get free scan" buttons functionality with existing account', async ({ + landingPage, + page, + authPage, + }) => { + // link to testrail case + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463503", + }); - // verify dashboard redirect - const successUrl = - process.env.E2E_TEST_BASE_URL + - `${ - process.env.E2E_TEST_ENV === "local" + const existingEmail = process.env.E2E_TEST_ACCOUNT_EMAIL as string; + + if (await emailInputShouldExist(landingPage)) { + // Scenario where the form is still used + await landingPage.monitorHeroFormEmailInputField.fill(existingEmail); + await landingPage.monitorHeroFormInputSubmitButton.click(); + await page.waitForURL("**/oauth/**"); + } else { + // Scenario where direct redirection happens + await landingPage.monitorHeroFormInputSubmitButton.click(); + await authPage.emailInputField.waitFor({ + state: "visible", + timeout: 10000, + }); + await authPage.emailInputField.fill(existingEmail); + await authPage.continueButton.click(); + } + + // complete sign in form + await authPage.enterPassword(); + + // verify dashboard redirect + const successUrl = + process.env.E2E_TEST_BASE_URL + + (process.env.E2E_TEST_ENV === "local" ? "/user/welcome" - : "/user/dashboard" - }`; - expect(page.url()).toBe(successUrl); - }); -}); + : "/user/dashboard"); + expect(page.url()).toBe(successUrl); + }); + + test('Verify the "Start free monitoring" button UI and functionality with existing account', async ({ + landingPage, + page, + authPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463524", + }); + + await landingPage.startFreeMonitoringButton.click(); + + await authPage.enterEmail(process.env.E2E_TEST_ACCOUNT_EMAIL as string); + await authPage.enterPassword(); + + // verify dashboard redirect + const successUrl = + process.env.E2E_TEST_BASE_URL + + `${ + process.env.E2E_TEST_ENV === "local" + ? "/user/welcome" + : "/user/dashboard" + }`; + expect(page.url()).toBe(successUrl); + }); + }, +); test("Verify that the 404 page shows up on non-existent pages @smoke", async ({ page, diff --git a/src/e2e/specs/purchase.spec.ts b/src/e2e/specs/purchase.spec.ts index d95242622c8..064d8e2c992 100644 --- a/src/e2e/specs/purchase.spec.ts +++ b/src/e2e/specs/purchase.spec.ts @@ -5,197 +5,200 @@ import { test, expect } from "../fixtures/basePage.js"; import { checkAuthState, setEnvVariables } from "../utils/helpers.js"; -test.describe(`${process.env.E2E_TEST_ENV} - Breach Scan, Monitor Plus Purchase Flow`, () => { - test.beforeEach(async ({ page, authPage, landingPage, welcomePage }) => { - test.info().annotations.push({ - type: "testrail id", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463564", - }); +test.describe.skip( + `${process.env.E2E_TEST_ENV} - Breach Scan, Monitor Plus Purchase Flow`, + () => { + test.beforeEach(async ({ page, authPage, landingPage, welcomePage }) => { + test.info().annotations.push({ + type: "testrail id", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463564", + }); + + test.slow( + true, + "this test runs through the welcome scan flow, increasing timeout to address it", + ); - test.slow( - true, - "this test runs through the welcome scan flow, increasing timeout to address it", - ); + setEnvVariables(process.env.E2E_TEST_ACCOUNT_EMAIL as string); - setEnvVariables(process.env.E2E_TEST_ACCOUNT_EMAIL as string); + // speed up test by ignoring non necessary requests + await page.route(/(analytics)/, async (route) => { + await route.abort(); + }); - // speed up test by ignoring non necessary requests - await page.route(/(analytics)/, async (route) => { - await route.abort(); - }); + // start authentication flow + await landingPage.open(); + await landingPage.goToSignIn(); + + // Fill out sign up form + const randomEmail = `_${Date.now()}@restmail.net`; + await authPage.signUp(randomEmail, page); - // start authentication flow - await landingPage.open(); - await landingPage.goToSignIn(); - - // Fill out sign up form - const randomEmail = `_${Date.now()}@restmail.net`; - await authPage.signUp(randomEmail, page); - - // wait for welcome page - await page.waitForURL("**/user/welcome"); - await welcomePage.goThroughFirstScan(); - expect(page.url()).toContain("/user/dashboard"); - }); - - test("Verify that the user can purchase the plus subscription with a Stripe card - Yearly", async ({ - dashboardPage, - purchasePage, - page, - }) => { - test.skip( - process.env.E2E_TEST_ENV === "production", - "payment method test not available in production", - ); - // link to testrail case - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463627", + // wait for welcome page + await page.waitForURL("**/user/welcome"); + await welcomePage.goThroughFirstScan(); + expect(page.url()).toContain("/user/dashboard"); }); - try { - await checkAuthState(page); - } catch { - console.log( - "[E2E_LOG] - No fxa auth required, proceeding... with stripe yearly", + test("Verify that the user can purchase the plus subscription with a Stripe card - Yearly", async ({ + dashboardPage, + purchasePage, + page, + }) => { + test.skip( + process.env.E2E_TEST_ENV === "production", + "payment method test not available in production", ); - } - - // navigate to subscription - await dashboardPage.open(); - await dashboardPage.subscribeButton.click(); - await dashboardPage.subscribeDialogSelectYearlyPlanLink.click(); - await purchasePage.subscriptionHeader.waitFor(); - - // fill out subscription payment - await purchasePage.authorizationCheckbox.check(); - await purchasePage.fillOutStripeCardInfo(); - await purchasePage.payNowButton.click({ force: true }); - await page.getByText("Subscription confirmation").waitFor(); - // navigate to confirmation - await purchasePage.getStartedButton.click(); - await purchasePage.goToNextStep.waitFor(); - await purchasePage.goToNextStep.click(); - - // confirm successful payment - await dashboardPage.plusSubscription.waitFor(); - await expect(dashboardPage.plusSubscription).toBeVisible(); - }); - - test("Verify that the user can purchase the plus subscription with a Stripe card - Monthly", async ({ - purchasePage, - dashboardPage, - page, - }) => { - test.skip( - process.env.E2E_TEST_ENV === "production", - "payment method test not available in production", - ); - // link to multiple testrail cases - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463627", + // link to testrail case + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463627", + }); + + try { + await checkAuthState(page); + } catch { + console.log( + "[E2E_LOG] - No fxa auth required, proceeding... with stripe yearly", + ); + } + + // navigate to subscription + await dashboardPage.open(); + await dashboardPage.subscribeButton.click(); + await dashboardPage.subscribeDialogSelectYearlyPlanLink.click(); + await purchasePage.subscriptionHeader.waitFor(); + + // fill out subscription payment + await purchasePage.authorizationCheckbox.check(); + await purchasePage.fillOutStripeCardInfo(); + await purchasePage.payNowButton.click({ force: true }); + await page.getByText("Subscription confirmation").waitFor(); + // navigate to confirmation + await purchasePage.getStartedButton.click(); + await purchasePage.goToNextStep.waitFor(); + await purchasePage.goToNextStep.click(); + + // confirm successful payment + await dashboardPage.plusSubscription.waitFor(); + await expect(dashboardPage.plusSubscription).toBeVisible(); }); - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301529", + test("Verify that the user can purchase the plus subscription with a Stripe card - Monthly", async ({ + purchasePage, + dashboardPage, + page, + }) => { + test.skip( + process.env.E2E_TEST_ENV === "production", + "payment method test not available in production", + ); + // link to multiple testrail cases + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463627", + }); + + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301529", + }); + + try { + await checkAuthState(page); + } catch { + console.log( + "[E2E_LOG] - No fxa auth required, proceeding... with stripe monthly", + ); + } + + // navigate to subscription + await dashboardPage.open(); + await dashboardPage.subscribeButton.click(); + + // verify user purchase choices + await expect(dashboardPage.subscribeDialogCloseButton).toBeVisible(); + await expect(dashboardPage.yearlyMonthlyTablist).toBeVisible(); + await dashboardPage.yearlyTab.click(); + await expect( + dashboardPage.subscribeDialogSelectYearlyPlanLink, + ).toBeVisible(); + + await dashboardPage.monthlyTab.click(); + await expect( + dashboardPage.subscribeDialogSelectMonthlyPlanLink, + ).toBeVisible(); + + await dashboardPage.monthlyTab.click(); + await dashboardPage.subscribeDialogSelectMonthlyPlanLink.click(); + await purchasePage.subscriptionHeader.waitFor(); + + // fill out subscription payment + await purchasePage.authorizationCheckbox.waitFor(); + await purchasePage.authorizationCheckbox.check(); + await purchasePage.fillOutStripeCardInfo(); + await purchasePage.payNowButton.click({ force: true }); + await page.getByText("Subscription confirmation").waitFor(); + // navigate to confirmation + await purchasePage.getStartedButton.click(); + await purchasePage.goToNextStep.click(); + + // confirm successful payment + await dashboardPage.plusSubscription.waitFor({ + state: "attached", + timeout: 5000, + }); + await expect(dashboardPage.plusSubscription).toBeVisible(); }); - try { - await checkAuthState(page); - } catch { - console.log( - "[E2E_LOG] - No fxa auth required, proceeding... with stripe monthly", + test("Verify that the user can purchase the plus subscription with a PayPal account - yearly", async ({ + purchasePage, + dashboardPage, + context, + }) => { + test.skip( + process.env.E2E_TEST_ENV === "production", + "payment method test not available in production", ); - } - - // navigate to subscription - await dashboardPage.open(); - await dashboardPage.subscribeButton.click(); - - // verify user purchase choices - await expect(dashboardPage.subscribeDialogCloseButton).toBeVisible(); - await expect(dashboardPage.yearlyMonthlyTablist).toBeVisible(); - await dashboardPage.yearlyTab.click(); - await expect( - dashboardPage.subscribeDialogSelectYearlyPlanLink, - ).toBeVisible(); - - await dashboardPage.monthlyTab.click(); - await expect( - dashboardPage.subscribeDialogSelectMonthlyPlanLink, - ).toBeVisible(); - - await dashboardPage.monthlyTab.click(); - await dashboardPage.subscribeDialogSelectMonthlyPlanLink.click(); - await purchasePage.subscriptionHeader.waitFor(); - - // fill out subscription payment - await purchasePage.authorizationCheckbox.waitFor(); - await purchasePage.authorizationCheckbox.check(); - await purchasePage.fillOutStripeCardInfo(); - await purchasePage.payNowButton.click({ force: true }); - await page.getByText("Subscription confirmation").waitFor(); - // navigate to confirmation - await purchasePage.getStartedButton.click(); - await purchasePage.goToNextStep.click(); - - // confirm successful payment - await dashboardPage.plusSubscription.waitFor({ - state: "attached", - timeout: 5000, - }); - await expect(dashboardPage.plusSubscription).toBeVisible(); - }); - - test("Verify that the user can purchase the plus subscription with a PayPal account - yearly", async ({ - purchasePage, - dashboardPage, - context, - }) => { - test.skip( - process.env.E2E_TEST_ENV === "production", - "payment method test not available in production", - ); - // link to testrail case - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463628", + // link to testrail case + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463628", + }); + + await purchasePage.gotoPurchaseFromDashboard(dashboardPage, true); + // fill out subscription payment + await purchasePage.authorizationCheckbox.check(); + await purchasePage.fillOutPaypalInfo(context); + await purchasePage.postPaymentPageCheck(dashboardPage); }); - await purchasePage.gotoPurchaseFromDashboard(dashboardPage, true); - // fill out subscription payment - await purchasePage.authorizationCheckbox.check(); - await purchasePage.fillOutPaypalInfo(context); - await purchasePage.postPaymentPageCheck(dashboardPage); - }); - - test("Verify that the user can purchase the plus subscription with a PayPal account - monthly", async ({ - purchasePage, - dashboardPage, - context, - }) => { - test.skip( - process.env.E2E_TEST_ENV === "production", - "payment method test not available in production", - ); - // link to testrail case - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463628", + test("Verify that the user can purchase the plus subscription with a PayPal account - monthly", async ({ + purchasePage, + dashboardPage, + context, + }) => { + test.skip( + process.env.E2E_TEST_ENV === "production", + "payment method test not available in production", + ); + // link to testrail case + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463628", + }); + + await purchasePage.gotoPurchaseFromDashboard(dashboardPage, false); + // fill out subscription payment + await purchasePage.authorizationCheckbox.check(); + await purchasePage.fillOutPaypalInfo(context); + await purchasePage.postPaymentPageCheck(dashboardPage); }); - - await purchasePage.gotoPurchaseFromDashboard(dashboardPage, false); - // fill out subscription payment - await purchasePage.authorizationCheckbox.check(); - await purchasePage.fillOutPaypalInfo(context); - await purchasePage.postPaymentPageCheck(dashboardPage); - }); -}); + }, +); diff --git a/src/e2e/specs/settings.spec.ts b/src/e2e/specs/settings.spec.ts index e86390f5616..4d2f7f04dad 100644 --- a/src/e2e/specs/settings.spec.ts +++ b/src/e2e/specs/settings.spec.ts @@ -6,7 +6,7 @@ import { test, expect } from "../fixtures/basePage.js"; // bypass login test.use({ storageState: "./e2e/storageState.json" }); -test.describe(`${process.env.E2E_TEST_ENV} Settings Page`, () => { +test.describe.skip(`${process.env.E2E_TEST_ENV} Settings Page`, () => { test("Verify settings page loads", async ({ settingsPage }) => { // should go directly to data breach page await settingsPage.open(); From e0887924e070f5fbfc5c8a26612a8fa526f0b658 Mon Sep 17 00:00:00 2001 From: Florian Zia Date: Mon, 2 Sep 2024 19:40:40 +0200 Subject: [PATCH 02/10] chore: Run E2E tests in parallel --- .github/workflows/build.yaml | 4 +- .github/workflows/docker_build_deploy.yml | 4 +- .github/workflows/docker_check.yml | 1 + .github/workflows/e2e_pr_full.yml | 2 +- .github/workflows/e2e_pr_smoke.yml | 2 +- .github/workflows/preview_deploy_gcp.yml | 3 +- .github/workflows/reference_linter.yaml | 3 +- .github/workflows/unittests.yaml | 4 +- playwright.config.js | 7 +- src/e2e/specs/auth.spec.ts | 114 +++--- src/e2e/specs/error.spec.ts | 16 + src/e2e/specs/landing.spec.ts | 445 ++++++++++------------ src/e2e/specs/settings.spec.ts | 2 +- 13 files changed, 296 insertions(+), 311 deletions(-) create mode 100644 src/e2e/specs/error.spec.ts diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index b3301191072..88b41611de9 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,6 +1,8 @@ name: Build -on: [push] +on: + pull_request: + types: [closed] jobs: npm-build: diff --git a/.github/workflows/docker_build_deploy.yml b/.github/workflows/docker_build_deploy.yml index b26578fdc68..c235a37807f 100644 --- a/.github/workflows/docker_build_deploy.yml +++ b/.github/workflows/docker_build_deploy.yml @@ -1,8 +1,8 @@ name: Build Docker image and publish on: - push: - branches: [ main ] + pull_request: + types: [closed] jobs: push_to_registry: name: Push Docker image to Docker Hub diff --git a/.github/workflows/docker_check.yml b/.github/workflows/docker_check.yml index ef75f7751bc..214f7667391 100644 --- a/.github/workflows/docker_check.yml +++ b/.github/workflows/docker_check.yml @@ -1,6 +1,7 @@ name: Build Docker image check on: pull_request: + types: [closed] jobs: docker_build: name: Build Docker image diff --git a/.github/workflows/e2e_pr_full.yml b/.github/workflows/e2e_pr_full.yml index b3f2219478c..93174fe9933 100644 --- a/.github/workflows/e2e_pr_full.yml +++ b/.github/workflows/e2e_pr_full.yml @@ -1,4 +1,4 @@ -name: Monitor E2E Full Test Suite +name: Monitor E2E Test Suite (full) on: push jobs: e2e-tests: diff --git a/.github/workflows/e2e_pr_smoke.yml b/.github/workflows/e2e_pr_smoke.yml index 08b33d561a0..361ec7ef7b6 100644 --- a/.github/workflows/e2e_pr_smoke.yml +++ b/.github/workflows/e2e_pr_smoke.yml @@ -1,4 +1,4 @@ -name: Monitor E2E Smoke Test Suite +name: Monitor E2E Test Suite (smoke) on: push: branches: [ main ] diff --git a/.github/workflows/preview_deploy_gcp.yml b/.github/workflows/preview_deploy_gcp.yml index c6fdef23a32..9115a1a72a0 100644 --- a/.github/workflows/preview_deploy_gcp.yml +++ b/.github/workflows/preview_deploy_gcp.yml @@ -1,7 +1,8 @@ name: Deploy Preview -on: +on: pull_request: + types: [closed] env: PROJECT_ID: ${{ secrets.GCP_PROJECT }} diff --git a/.github/workflows/reference_linter.yaml b/.github/workflows/reference_linter.yaml index 173b7180b3d..0355144fb89 100644 --- a/.github/workflows/reference_linter.yaml +++ b/.github/workflows/reference_linter.yaml @@ -1,8 +1,7 @@ name: Lint Reference Files on: - push: pull_request: - workflow_dispatch: + types: [closed] jobs: l10n-lint: runs-on: ubuntu-latest diff --git a/.github/workflows/unittests.yaml b/.github/workflows/unittests.yaml index 83c3a974b96..b8ef110377a 100644 --- a/.github/workflows/unittests.yaml +++ b/.github/workflows/unittests.yaml @@ -1,6 +1,8 @@ name: Unit Tests -on: [push] +on: + pull_request: + types: [closed] jobs: unit-tests: diff --git a/playwright.config.js b/playwright.config.js index bede251a300..7aac2fbf270 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -50,11 +50,14 @@ export default defineConfig({ /* Fail the build on CI if you accidentally left test.only in the source code. */ forbidOnly: !!process.env.CI, + /* Limit the number of failures */ + maxFailures: process.env.CI ? 1 : undefined, + /* Retry on CI only */ retries: process.env.CI ? 1 : 0, - /* Opt out of parallel tests on CI. */ - workers: process.env.CI ? 1 : undefined, + /* Use all of the available wokers in CI and use default locally. */ + workers: process.env.CI ? "100%" : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: process.env.CI ? [['github'], ['html']] : 'html', diff --git a/src/e2e/specs/auth.spec.ts b/src/e2e/specs/auth.spec.ts index 120be8bcc48..a820b367893 100644 --- a/src/e2e/specs/auth.spec.ts +++ b/src/e2e/specs/auth.spec.ts @@ -4,74 +4,68 @@ import { test, expect } from "../fixtures/basePage.js"; -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Authentication flow verification @smoke`, - () => { - test.beforeEach(async ({ landingPage }) => { - await landingPage.open(); +test.describe(`${process.env.E2E_TEST_ENV} - Authentication flow verification @smoke`, () => { + test.beforeEach(async ({ landingPage }) => { + await landingPage.open(); + }); + + test("Verify sign up with new user", async ({ + page, + authPage, + landingPage, + }, testInfo) => { + // speed up test by ignore non necessary requests + await page.route(/(analytics)/, async (route) => { + await route.abort(); }); - test("Verify sign up with new user", async ({ - page, - authPage, - landingPage, - }, testInfo) => { - // speed up test by ignore non necessary requests - await page.route(/(analytics)/, async (route) => { - await route.abort(); - }); + // start authentication flow + await landingPage.goToSignIn(); - // start authentication flow - await landingPage.goToSignIn(); + // Fill out sign up form + const randomEmail = `${Date.now()}_tstact@restmail.net`; + await authPage.signUp(randomEmail, page); - // Fill out sign up form - const randomEmail = `${Date.now()}_tstact@restmail.net`; - await authPage.signUp(randomEmail, page); + // assert successful login + const successUrl = "/user/welcome"; + expect(page.url()).toBe(`${process.env.E2E_TEST_BASE_URL}${successUrl}`); - // assert successful login - const successUrl = - process.env.E2E_TEST_ENV === "local" - ? "/user/dashboard" - : "/user/welcome"; - expect(page.url()).toBe(`${process.env.E2E_TEST_BASE_URL}${successUrl}`); + await testInfo.attach( + `${process.env.E2E_TEST_ENV}-signup-monitor-dashboard.png`, + { + body: await page.screenshot(), + contentType: "image/png", + }, + ); + }); - await testInfo.attach( - `${process.env.E2E_TEST_ENV}-signup-monitor-dashboard.png`, - { - body: await page.screenshot(), - contentType: "image/png", - }, - ); + test("Verify sign in with existing user", async ({ + page, + authPage, + landingPage, + dashboardPage, + }, testInfo) => { + // speed up test by ignore non necessary requests + await page.route(/(analytics)/, async (route) => { + await route.abort(); }); - test("Verify sign in with existing user", async ({ - page, - authPage, - landingPage, - dashboardPage, - }, testInfo) => { - // speed up test by ignore non necessary requests - await page.route(/(analytics)/, async (route) => { - await route.abort(); - }); - - // start authentication flow - await landingPage.goToSignIn(); + // start authentication flow + await landingPage.goToSignIn(); - // sign in - await authPage.signIn(process.env.E2E_TEST_ACCOUNT_EMAIL as string); + // sign in + await authPage.signIn(process.env.E2E_TEST_ACCOUNT_EMAIL as string); - // assert successful login - await expect(dashboardPage.fixedTab).toBeVisible(); - await expect(dashboardPage.actionNeededTab).toBeVisible(); + // assert successful login + await expect(dashboardPage.fixedTab).toBeVisible(); + await expect(dashboardPage.actionNeededTab).toBeVisible(); - await testInfo.attach( - `${process.env.E2E_TEST_ENV}-signin-monitor-dashboard.png`, - { - body: await page.screenshot(), - contentType: "image/png", - }, - ); - }); - }, -); + await testInfo.attach( + `${process.env.E2E_TEST_ENV}-signin-monitor-dashboard.png`, + { + body: await page.screenshot(), + contentType: "image/png", + }, + ); + }); +}); diff --git a/src/e2e/specs/error.spec.ts b/src/e2e/specs/error.spec.ts new file mode 100644 index 00000000000..af490baa60b --- /dev/null +++ b/src/e2e/specs/error.spec.ts @@ -0,0 +1,16 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { test, expect } from "../fixtures/basePage.js"; + +test.describe(`${process.env.E2E_TEST_ENV} - Verify Error Pages Functionality`, () => { + test("Verify that the 404 page shows up on non-existent pages @smoke", async ({ + page, + }) => { + await page.goto("/non-existent-page/"); + await expect( + page.locator("h1").getByText("⁨404⁩ Page not found"), + ).toBeVisible(); + }); +}); diff --git a/src/e2e/specs/landing.spec.ts b/src/e2e/specs/landing.spec.ts index ceed1323585..5cd5edc5518 100644 --- a/src/e2e/specs/landing.spec.ts +++ b/src/e2e/specs/landing.spec.ts @@ -9,245 +9,231 @@ import { getVerificationCode, } from "../utils/helpers.js"; -test.describe.configure({ mode: "parallel" }); -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, - () => { - test.beforeEach(async ({ landingPage }) => { - await landingPage.open(); +test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, () => { + test.beforeEach(async ({ landingPage }) => { + await landingPage.open(); + }); + + test.skip("Observe page header", async ({ landingPage, page }) => { + // link to testrail case + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", }); - test("Observe page header", async ({ landingPage, page }) => { - // link to testrail case - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", - }); - - await expect(landingPage.monitorLandingHeader).toBeVisible(); - await landingPage.signInButton.click(); - await page.waitForURL("**/oauth/**"); - expect(page.url()).toContain("oauth"); + await expect(landingPage.monitorLandingHeader).toBeVisible(); + await landingPage.signInButton.click(); + await page.waitForURL("**/oauth/**"); + expect(page.url()).toContain("oauth"); + }); + + test.skip('Observe "Find where your private info is exposed and take it back" section', async ({ + landingPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", }); - test('Observe "Find where your private info is exposed and take it back" section', async ({ - landingPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", - }); - - await expect(landingPage.monitorHeroTitle).toBeVisible(); - await expect(landingPage.monitorHeroSubtitle).toHaveText( - "We scan to see if your phone number, passwords or home address have been leaked, and help you make it private again.", - ); - if (await emailInputShouldExist(landingPage)) { - await expect(landingPage.monitorHeroFormEmailInputField).toBeVisible(); - await expect( - landingPage.monitorHeroFormInputSubmitButton, - ).toBeVisible(); - } - await expect(landingPage.monitorLandingMidHeading).toBeVisible(); + await expect(landingPage.monitorHeroTitle).toBeVisible(); + await expect(landingPage.monitorHeroSubtitle).toHaveText( + "We scan to see if your phone number, passwords or home address have been leaked, and help you make it private again.", + ); + if (await emailInputShouldExist(landingPage)) { + await expect(landingPage.monitorHeroFormEmailInputField).toBeVisible(); + await expect(landingPage.monitorHeroFormInputSubmitButton).toBeVisible(); + } + await expect(landingPage.monitorLandingMidHeading).toBeVisible(); + }); + + test.skip('Observe "We will help you fix your exposures" section', async ({ + landingPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", }); - test('Observe "We will help you fix your exposures" section', async ({ - landingPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", - }); - - await expect(landingPage.fixExposuresTitle).toBeVisible(); - await expect(landingPage.fixExposuresSubtitle).toBeVisible(); - if (await emailInputShouldExist(landingPage)) { - await expect(landingPage.fixExposuresFormEmailInputField).toBeVisible(); - await expect( - landingPage.fixExposuresFormInputSubmitButton, - ).toBeVisible(); - } - await expect(landingPage.fixExposuresGraphic).toBeVisible(); + await expect(landingPage.fixExposuresTitle).toBeVisible(); + await expect(landingPage.fixExposuresSubtitle).toBeVisible(); + if (await emailInputShouldExist(landingPage)) { + await expect(landingPage.fixExposuresFormEmailInputField).toBeVisible(); + await expect(landingPage.fixExposuresFormInputSubmitButton).toBeVisible(); + } + await expect(landingPage.fixExposuresGraphic).toBeVisible(); + }); + + test.skip('Observe "What info could be at risk?" section', async ({ + landingPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", }); - test('Observe "What info could be at risk?" section', async ({ - landingPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", - }); - - await expect(landingPage.couldBeAtRiskTitle).toBeVisible(); - await expect(landingPage.couldBeAtRiskSubtitle).toBeVisible(); - if (await emailInputShouldExist(landingPage)) { - await expect( - landingPage.couldBeAtRiskFormEmailInputField, - ).toBeVisible(); - } - await expect( - landingPage.couldBeAtRiskFormInputSubmitButton, - ).toBeVisible(); - await expect(landingPage.couldBeAtRiskGraphic).toBeVisible(); - }); - - test('Observe "Scan your email to get started" section', async ({ - landingPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", - }); - - await expect(landingPage.getStartedScanTitle).toBeVisible(); - if (await emailInputShouldExist(landingPage)) - await expect( - landingPage.getStartedScanFormEmailInputField, - ).toBeVisible(); - await expect(landingPage.getStartedScanFormSubmitButton).toBeVisible(); + await expect(landingPage.couldBeAtRiskTitle).toBeVisible(); + await expect(landingPage.couldBeAtRiskSubtitle).toBeVisible(); + if (await emailInputShouldExist(landingPage)) { + await expect(landingPage.couldBeAtRiskFormEmailInputField).toBeVisible(); + } + await expect(landingPage.couldBeAtRiskFormInputSubmitButton).toBeVisible(); + await expect(landingPage.couldBeAtRiskGraphic).toBeVisible(); + }); + + test.skip('Observe "Scan your email to get started" section', async ({ + landingPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", }); - test('Observe "Choose your level of protection" section', async ({ - landingPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", - }); - - await expect(landingPage.chooseLevelSection).toHaveScreenshot( - `${process.env.E2E_TEST_ENV}-chooseLevelSection.png`, - defaultScreenshotOpts, - ); + await expect(landingPage.getStartedScanTitle).toBeVisible(); + if (await emailInputShouldExist(landingPage)) + await expect(landingPage.getStartedScanFormEmailInputField).toBeVisible(); + await expect(landingPage.getStartedScanFormSubmitButton).toBeVisible(); + }); + + test.skip('Observe "Choose your level of protection" section', async ({ + landingPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", }); - test("Observe FAQ section", async ({ landingPage }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", - }); - - await expect(landingPage.faqSection).toHaveScreenshot( - `${process.env.E2E_TEST_ENV}-faqSection.png`, - defaultScreenshotOpts, - ); + await expect(landingPage.chooseLevelSection).toHaveScreenshot( + `${process.env.E2E_TEST_ENV}-chooseLevelSection.png`, + defaultScreenshotOpts, + ); + }); + + test.skip("Observe FAQ section", async ({ landingPage }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", }); - test('Observe "Take back control of your data" section', async ({ - landingPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", - }); - - await expect(landingPage.takeBackControlTitle).toBeVisible(); - if (await emailInputShouldExist(landingPage)) { - await expect( - landingPage.takeBackControlFormEmailInputField, - ).toBeVisible(); - await expect(landingPage.takeBackControlFormSubmitButton).toBeVisible(); - } + await expect(landingPage.faqSection).toHaveScreenshot( + `${process.env.E2E_TEST_ENV}-faqSection.png`, + defaultScreenshotOpts, + ); + }); + + test.skip('Observe "Take back control of your data" section', async ({ + landingPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", }); - test("Observe footer section", async ({ landingPage }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", - }); - - await expect(landingPage.mozillaFooterLogoLink).toBeVisible(); - await expect(landingPage.faqLink).toBeVisible(); - await expect(landingPage.termsLink).toBeVisible(); - await expect(landingPage.privacyLink).toBeVisible(); - await expect(landingPage.githubLink).toBeVisible(); + await expect(landingPage.takeBackControlTitle).toBeVisible(); + if (await emailInputShouldExist(landingPage)) { + await expect( + landingPage.takeBackControlFormEmailInputField, + ).toBeVisible(); + await expect(landingPage.takeBackControlFormSubmitButton).toBeVisible(); + } + }); + + test.skip("Observe footer section", async ({ landingPage }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463517", }); - test("Verify the 'Get data removal' button UI and functionality for both yearly and monthly options", async ({ - landingPage, - purchasePage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463525", - }); - - await expect(landingPage.getDataRemoval).toBeVisible(); - await expect(landingPage.getDataRemovalMonthly).toBeVisible(); - await expect(landingPage.getDataRemovalYearly).toBeVisible(); - - // Monthly - await landingPage.getDataRemovalMonthly.click(); - await landingPage.getDataRemoval.click(); - await purchasePage.verifyMonthlyPlanDetails(); - - // Yearly - await landingPage.open(); - await landingPage.getDataRemoval.click(); - await purchasePage.verifyYearlyPlanDetails(); + await expect(landingPage.mozillaFooterLogoLink).toBeVisible(); + await expect(landingPage.faqLink).toBeVisible(); + await expect(landingPage.termsLink).toBeVisible(); + await expect(landingPage.privacyLink).toBeVisible(); + await expect(landingPage.githubLink).toBeVisible(); + }); + + test("Verify the 'Get data removal' button UI and functionality for both yearly and monthly options", async ({ + landingPage, + purchasePage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463525", }); - test('Verify the "Get free scan" corresponding email fields', async ({ - landingPage, - authPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463504", - }); - if (await emailInputShouldExist(landingPage)) { - ///free-scan-cta experiment is off - await landingPage.monitorHeroFormEmailInputField.fill("invalid"); - await landingPage.monitorHeroFormInputSubmitButton.click(); - await expect(landingPage.monitorHeroFormEmailInputField).toBeVisible(); - - const randomEmail = `_${Date.now()}_tstact@restmail.net`; - await landingPage.monitorHeroFormEmailInputField.fill(randomEmail); - await landingPage.monitorHeroFormInputSubmitButton.click(); - await authPage.passwordInputField.waitFor(); - await expect(authPage.passwordInputField).toBeVisible(); - } else { - ///free-scan-cta experiment is on - await landingPage.monitorHeroFormInputSubmitButton.click(); - await authPage.emailInputField.waitFor({ - state: "visible", - timeout: 10000, - }); - const randomEmail = `_${Date.now()}_tstact@restmail.net`; - await authPage.emailInputField.fill(randomEmail); - await authPage.continueButton.click(); - await authPage.passwordInputField.waitFor(); - await expect(authPage.passwordInputField).toBeVisible(); - } + await expect(landingPage.getDataRemoval).toBeVisible(); + await expect(landingPage.getDataRemovalMonthly).toBeVisible(); + await expect(landingPage.getDataRemovalYearly).toBeVisible(); + + // Monthly + await landingPage.getDataRemovalMonthly.click(); + await landingPage.getDataRemoval.click(); + await purchasePage.verifyMonthlyPlanDetails(); + + // Yearly + await landingPage.open(); + await landingPage.getDataRemoval.click(); + await purchasePage.verifyYearlyPlanDetails(); + }); + + test.skip('Verify the "Get free scan" corresponding email fields', async ({ + landingPage, + authPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463504", }); - - test('Verify manual/automatic removal "more info" tips from "Choose your level of protection" section', async ({ - landingPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463504", + if (await emailInputShouldExist(landingPage)) { + ///free-scan-cta experiment is off + await landingPage.monitorHeroFormEmailInputField.fill("invalid"); + await landingPage.monitorHeroFormInputSubmitButton.click(); + await expect(landingPage.monitorHeroFormEmailInputField).toBeVisible(); + + const randomEmail = `_${Date.now()}_tstact@restmail.net`; + await landingPage.monitorHeroFormEmailInputField.fill(randomEmail); + await landingPage.monitorHeroFormInputSubmitButton.click(); + await authPage.passwordInputField.waitFor(); + await expect(authPage.passwordInputField).toBeVisible(); + } else { + ///free-scan-cta experiment is on + await landingPage.monitorHeroFormInputSubmitButton.click(); + await authPage.emailInputField.waitFor({ + state: "visible", + timeout: 10000, }); - await landingPage.freeMonitoringTooltipTrigger.click(); - await expect(landingPage.freeMonitoringTooltipText).toBeVisible(); - await landingPage.closeTooltips.click(); - await landingPage.monitorPlusTooltipTrigger.click(); - await expect(landingPage.monitorPlusTooltipText).toBeVisible(); + const randomEmail = `_${Date.now()}_tstact@restmail.net`; + await authPage.emailInputField.fill(randomEmail); + await authPage.continueButton.click(); + await authPage.passwordInputField.waitFor(); + await expect(authPage.passwordInputField).toBeVisible(); + } + }); + + test.skip('Verify manual/automatic removal "more info" tips from "Choose your level of protection" section', async ({ + landingPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463504", }); - }, -); + await landingPage.freeMonitoringTooltipTrigger.click(); + await expect(landingPage.freeMonitoringTooltipText).toBeVisible(); + await landingPage.closeTooltips.click(); + await landingPage.monitorPlusTooltipTrigger.click(); + await expect(landingPage.monitorPlusTooltipText).toBeVisible(); + }); +}); test.describe.skip( `${process.env.E2E_TEST_ENV} - Verify the Landing Page Functionality - without existing Account`, @@ -292,7 +278,7 @@ test.describe.skip( await authPage.continueButton.click(); const vc = await getVerificationCode(randomEmail, page); await authPage.enterVerificationCode(vc); - const successUrl = process.env.E2E_TEST_BASE_URL + "/user/welcome"; + const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/welcome`; expect(page.url()).toBe(successUrl); }); @@ -319,7 +305,7 @@ test.describe.skip( const randomEmail = `${Date.now()}_tstact@restmail.net`; await authPage.signUp(randomEmail, page); - const successUrl = process.env.E2E_TEST_BASE_URL + "/user/welcome"; + const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/welcome`; expect(page.url()).toBe(successUrl); }); }, @@ -366,11 +352,7 @@ test.describe.skip( await authPage.enterPassword(); // verify dashboard redirect - const successUrl = - process.env.E2E_TEST_BASE_URL + - (process.env.E2E_TEST_ENV === "local" - ? "/user/welcome" - : "/user/dashboard"); + const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/dashboard`; expect(page.url()).toBe(successUrl); }); @@ -391,23 +373,8 @@ test.describe.skip( await authPage.enterPassword(); // verify dashboard redirect - const successUrl = - process.env.E2E_TEST_BASE_URL + - `${ - process.env.E2E_TEST_ENV === "local" - ? "/user/welcome" - : "/user/dashboard" - }`; + const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/dashboard`; expect(page.url()).toBe(successUrl); }); }, ); - -test("Verify that the 404 page shows up on non-existent pages @smoke", async ({ - page, -}) => { - await page.goto("/non-existent-page/"); - await expect( - page.locator("h1").getByText("⁨404⁩ Page not found"), - ).toBeVisible(); -}); diff --git a/src/e2e/specs/settings.spec.ts b/src/e2e/specs/settings.spec.ts index 4d2f7f04dad..e86390f5616 100644 --- a/src/e2e/specs/settings.spec.ts +++ b/src/e2e/specs/settings.spec.ts @@ -6,7 +6,7 @@ import { test, expect } from "../fixtures/basePage.js"; // bypass login test.use({ storageState: "./e2e/storageState.json" }); -test.describe.skip(`${process.env.E2E_TEST_ENV} Settings Page`, () => { +test.describe(`${process.env.E2E_TEST_ENV} Settings Page`, () => { test("Verify settings page loads", async ({ settingsPage }) => { // should go directly to data breach page await settingsPage.open(); From 7e40cfda8bb3fe2e5010f6d4e4d8354409842394 Mon Sep 17 00:00:00 2001 From: Florian Zia Date: Tue, 3 Sep 2024 13:59:44 +0200 Subject: [PATCH 03/10] chore: Run E2E tests in parallel --- src/e2e/pages/dashBoardPage.ts | 2 +- src/e2e/specs/auth.spec.ts | 7 +- src/e2e/specs/landing.spec.ts | 14 +- src/e2e/specs/purchase.spec.ts | 361 +++++++++++++++++---------------- 4 files changed, 187 insertions(+), 197 deletions(-) diff --git a/src/e2e/pages/dashBoardPage.ts b/src/e2e/pages/dashBoardPage.ts index 262d0986fbf..ea9fc14f6eb 100644 --- a/src/e2e/pages/dashBoardPage.ts +++ b/src/e2e/pages/dashBoardPage.ts @@ -122,7 +122,7 @@ export class DashboardPage { '//a[starts-with(@class, "Shell_mozillaLink")]', ); this.allBreachesFooter = page.locator("footer a", { - hasText: "All Breaches", + hasText: "Recent data breaches", }); this.faqsFooter = page.locator("footer a", { hasText: "FAQs" }); this.termsOfServiceFooter = page.locator("footer a", { diff --git a/src/e2e/specs/auth.spec.ts b/src/e2e/specs/auth.spec.ts index 92959b012d7..ee6a098852e 100644 --- a/src/e2e/specs/auth.spec.ts +++ b/src/e2e/specs/auth.spec.ts @@ -27,11 +27,8 @@ test.describe(`${process.env.E2E_TEST_ENV} - Authentication flow verification @s await authPage.signUp(randomEmail, page); // assert successful login - const successUrl = - process.env.E2E_TEST_ENV === "local" - ? "/user/dashboard" - : "/user/welcome"; - expect(page.url()).toBe(`${process.env.E2E_TEST_BASE_URL}${successUrl}`); + const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/welcome`; + expect(page.url()).toBe(successUrl); await testInfo.attach( `${process.env.E2E_TEST_ENV}-signup-monitor-dashboard.png`, diff --git a/src/e2e/specs/landing.spec.ts b/src/e2e/specs/landing.spec.ts index bd453cc7f46..2127ec3a4db 100644 --- a/src/e2e/specs/landing.spec.ts +++ b/src/e2e/specs/landing.spec.ts @@ -348,11 +348,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page Functionali await authPage.enterPassword(); // verify dashboard redirect - const successUrl = - process.env.E2E_TEST_BASE_URL + - (process.env.E2E_TEST_ENV === "local" - ? "/user/welcome" - : "/user/dashboard"); + const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/dashboard`; expect(page.url()).toBe(successUrl); }); @@ -373,13 +369,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page Functionali await authPage.enterPassword(); // verify dashboard redirect - const successUrl = - process.env.E2E_TEST_BASE_URL + - `${ - process.env.E2E_TEST_ENV === "local" - ? "/user/welcome" - : "/user/dashboard" - }`; + const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/dashboard`; expect(page.url()).toBe(successUrl); }); }); diff --git a/src/e2e/specs/purchase.spec.ts b/src/e2e/specs/purchase.spec.ts index d95242622c8..064d8e2c992 100644 --- a/src/e2e/specs/purchase.spec.ts +++ b/src/e2e/specs/purchase.spec.ts @@ -5,197 +5,200 @@ import { test, expect } from "../fixtures/basePage.js"; import { checkAuthState, setEnvVariables } from "../utils/helpers.js"; -test.describe(`${process.env.E2E_TEST_ENV} - Breach Scan, Monitor Plus Purchase Flow`, () => { - test.beforeEach(async ({ page, authPage, landingPage, welcomePage }) => { - test.info().annotations.push({ - type: "testrail id", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463564", - }); +test.describe.skip( + `${process.env.E2E_TEST_ENV} - Breach Scan, Monitor Plus Purchase Flow`, + () => { + test.beforeEach(async ({ page, authPage, landingPage, welcomePage }) => { + test.info().annotations.push({ + type: "testrail id", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463564", + }); + + test.slow( + true, + "this test runs through the welcome scan flow, increasing timeout to address it", + ); - test.slow( - true, - "this test runs through the welcome scan flow, increasing timeout to address it", - ); + setEnvVariables(process.env.E2E_TEST_ACCOUNT_EMAIL as string); - setEnvVariables(process.env.E2E_TEST_ACCOUNT_EMAIL as string); + // speed up test by ignoring non necessary requests + await page.route(/(analytics)/, async (route) => { + await route.abort(); + }); - // speed up test by ignoring non necessary requests - await page.route(/(analytics)/, async (route) => { - await route.abort(); - }); + // start authentication flow + await landingPage.open(); + await landingPage.goToSignIn(); + + // Fill out sign up form + const randomEmail = `_${Date.now()}@restmail.net`; + await authPage.signUp(randomEmail, page); - // start authentication flow - await landingPage.open(); - await landingPage.goToSignIn(); - - // Fill out sign up form - const randomEmail = `_${Date.now()}@restmail.net`; - await authPage.signUp(randomEmail, page); - - // wait for welcome page - await page.waitForURL("**/user/welcome"); - await welcomePage.goThroughFirstScan(); - expect(page.url()).toContain("/user/dashboard"); - }); - - test("Verify that the user can purchase the plus subscription with a Stripe card - Yearly", async ({ - dashboardPage, - purchasePage, - page, - }) => { - test.skip( - process.env.E2E_TEST_ENV === "production", - "payment method test not available in production", - ); - // link to testrail case - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463627", + // wait for welcome page + await page.waitForURL("**/user/welcome"); + await welcomePage.goThroughFirstScan(); + expect(page.url()).toContain("/user/dashboard"); }); - try { - await checkAuthState(page); - } catch { - console.log( - "[E2E_LOG] - No fxa auth required, proceeding... with stripe yearly", + test("Verify that the user can purchase the plus subscription with a Stripe card - Yearly", async ({ + dashboardPage, + purchasePage, + page, + }) => { + test.skip( + process.env.E2E_TEST_ENV === "production", + "payment method test not available in production", ); - } - - // navigate to subscription - await dashboardPage.open(); - await dashboardPage.subscribeButton.click(); - await dashboardPage.subscribeDialogSelectYearlyPlanLink.click(); - await purchasePage.subscriptionHeader.waitFor(); - - // fill out subscription payment - await purchasePage.authorizationCheckbox.check(); - await purchasePage.fillOutStripeCardInfo(); - await purchasePage.payNowButton.click({ force: true }); - await page.getByText("Subscription confirmation").waitFor(); - // navigate to confirmation - await purchasePage.getStartedButton.click(); - await purchasePage.goToNextStep.waitFor(); - await purchasePage.goToNextStep.click(); - - // confirm successful payment - await dashboardPage.plusSubscription.waitFor(); - await expect(dashboardPage.plusSubscription).toBeVisible(); - }); - - test("Verify that the user can purchase the plus subscription with a Stripe card - Monthly", async ({ - purchasePage, - dashboardPage, - page, - }) => { - test.skip( - process.env.E2E_TEST_ENV === "production", - "payment method test not available in production", - ); - // link to multiple testrail cases - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463627", + // link to testrail case + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463627", + }); + + try { + await checkAuthState(page); + } catch { + console.log( + "[E2E_LOG] - No fxa auth required, proceeding... with stripe yearly", + ); + } + + // navigate to subscription + await dashboardPage.open(); + await dashboardPage.subscribeButton.click(); + await dashboardPage.subscribeDialogSelectYearlyPlanLink.click(); + await purchasePage.subscriptionHeader.waitFor(); + + // fill out subscription payment + await purchasePage.authorizationCheckbox.check(); + await purchasePage.fillOutStripeCardInfo(); + await purchasePage.payNowButton.click({ force: true }); + await page.getByText("Subscription confirmation").waitFor(); + // navigate to confirmation + await purchasePage.getStartedButton.click(); + await purchasePage.goToNextStep.waitFor(); + await purchasePage.goToNextStep.click(); + + // confirm successful payment + await dashboardPage.plusSubscription.waitFor(); + await expect(dashboardPage.plusSubscription).toBeVisible(); }); - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301529", + test("Verify that the user can purchase the plus subscription with a Stripe card - Monthly", async ({ + purchasePage, + dashboardPage, + page, + }) => { + test.skip( + process.env.E2E_TEST_ENV === "production", + "payment method test not available in production", + ); + // link to multiple testrail cases + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463627", + }); + + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301529", + }); + + try { + await checkAuthState(page); + } catch { + console.log( + "[E2E_LOG] - No fxa auth required, proceeding... with stripe monthly", + ); + } + + // navigate to subscription + await dashboardPage.open(); + await dashboardPage.subscribeButton.click(); + + // verify user purchase choices + await expect(dashboardPage.subscribeDialogCloseButton).toBeVisible(); + await expect(dashboardPage.yearlyMonthlyTablist).toBeVisible(); + await dashboardPage.yearlyTab.click(); + await expect( + dashboardPage.subscribeDialogSelectYearlyPlanLink, + ).toBeVisible(); + + await dashboardPage.monthlyTab.click(); + await expect( + dashboardPage.subscribeDialogSelectMonthlyPlanLink, + ).toBeVisible(); + + await dashboardPage.monthlyTab.click(); + await dashboardPage.subscribeDialogSelectMonthlyPlanLink.click(); + await purchasePage.subscriptionHeader.waitFor(); + + // fill out subscription payment + await purchasePage.authorizationCheckbox.waitFor(); + await purchasePage.authorizationCheckbox.check(); + await purchasePage.fillOutStripeCardInfo(); + await purchasePage.payNowButton.click({ force: true }); + await page.getByText("Subscription confirmation").waitFor(); + // navigate to confirmation + await purchasePage.getStartedButton.click(); + await purchasePage.goToNextStep.click(); + + // confirm successful payment + await dashboardPage.plusSubscription.waitFor({ + state: "attached", + timeout: 5000, + }); + await expect(dashboardPage.plusSubscription).toBeVisible(); }); - try { - await checkAuthState(page); - } catch { - console.log( - "[E2E_LOG] - No fxa auth required, proceeding... with stripe monthly", + test("Verify that the user can purchase the plus subscription with a PayPal account - yearly", async ({ + purchasePage, + dashboardPage, + context, + }) => { + test.skip( + process.env.E2E_TEST_ENV === "production", + "payment method test not available in production", ); - } - - // navigate to subscription - await dashboardPage.open(); - await dashboardPage.subscribeButton.click(); - - // verify user purchase choices - await expect(dashboardPage.subscribeDialogCloseButton).toBeVisible(); - await expect(dashboardPage.yearlyMonthlyTablist).toBeVisible(); - await dashboardPage.yearlyTab.click(); - await expect( - dashboardPage.subscribeDialogSelectYearlyPlanLink, - ).toBeVisible(); - - await dashboardPage.monthlyTab.click(); - await expect( - dashboardPage.subscribeDialogSelectMonthlyPlanLink, - ).toBeVisible(); - - await dashboardPage.monthlyTab.click(); - await dashboardPage.subscribeDialogSelectMonthlyPlanLink.click(); - await purchasePage.subscriptionHeader.waitFor(); - - // fill out subscription payment - await purchasePage.authorizationCheckbox.waitFor(); - await purchasePage.authorizationCheckbox.check(); - await purchasePage.fillOutStripeCardInfo(); - await purchasePage.payNowButton.click({ force: true }); - await page.getByText("Subscription confirmation").waitFor(); - // navigate to confirmation - await purchasePage.getStartedButton.click(); - await purchasePage.goToNextStep.click(); - - // confirm successful payment - await dashboardPage.plusSubscription.waitFor({ - state: "attached", - timeout: 5000, - }); - await expect(dashboardPage.plusSubscription).toBeVisible(); - }); - - test("Verify that the user can purchase the plus subscription with a PayPal account - yearly", async ({ - purchasePage, - dashboardPage, - context, - }) => { - test.skip( - process.env.E2E_TEST_ENV === "production", - "payment method test not available in production", - ); - // link to testrail case - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463628", + // link to testrail case + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463628", + }); + + await purchasePage.gotoPurchaseFromDashboard(dashboardPage, true); + // fill out subscription payment + await purchasePage.authorizationCheckbox.check(); + await purchasePage.fillOutPaypalInfo(context); + await purchasePage.postPaymentPageCheck(dashboardPage); }); - await purchasePage.gotoPurchaseFromDashboard(dashboardPage, true); - // fill out subscription payment - await purchasePage.authorizationCheckbox.check(); - await purchasePage.fillOutPaypalInfo(context); - await purchasePage.postPaymentPageCheck(dashboardPage); - }); - - test("Verify that the user can purchase the plus subscription with a PayPal account - monthly", async ({ - purchasePage, - dashboardPage, - context, - }) => { - test.skip( - process.env.E2E_TEST_ENV === "production", - "payment method test not available in production", - ); - // link to testrail case - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463628", + test("Verify that the user can purchase the plus subscription with a PayPal account - monthly", async ({ + purchasePage, + dashboardPage, + context, + }) => { + test.skip( + process.env.E2E_TEST_ENV === "production", + "payment method test not available in production", + ); + // link to testrail case + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463628", + }); + + await purchasePage.gotoPurchaseFromDashboard(dashboardPage, false); + // fill out subscription payment + await purchasePage.authorizationCheckbox.check(); + await purchasePage.fillOutPaypalInfo(context); + await purchasePage.postPaymentPageCheck(dashboardPage); }); - - await purchasePage.gotoPurchaseFromDashboard(dashboardPage, false); - // fill out subscription payment - await purchasePage.authorizationCheckbox.check(); - await purchasePage.fillOutPaypalInfo(context); - await purchasePage.postPaymentPageCheck(dashboardPage); - }); -}); + }, +); From 7ee1006441318244722e342d3aed512c5b510b4a Mon Sep 17 00:00:00 2001 From: Florian Zia Date: Wed, 4 Sep 2024 15:59:37 +0200 Subject: [PATCH 04/10] wip: Debug E2E test failures in CI --- .env | 4 +- .github/workflows/build.yaml | 4 +- .github/workflows/docker_build_deploy.yml | 4 +- .github/workflows/docker_check.yml | 1 - .github/workflows/e2e_cron.yml | 8 +- .github/workflows/e2e_pr_full.yml | 20 +- .github/workflows/e2e_pr_smoke.yml | 6 +- .github/workflows/preview_deploy_gcp.yml | 3 +- .github/workflows/reference_linter.yaml | 3 +- .github/workflows/unittests.yaml | 4 +- playwright.config.js | 5 +- src/app/functions/server/isPrePlusUser.ts | 22 +- src/app/functions/universal/isPrePlusDate.ts | 27 + src/e2e/pages/purchasePage.ts | 2 +- src/e2e/pages/welcomeScanPage.ts | 15 +- src/e2e/specs/auth.spec.ts | 17 +- src/e2e/specs/breachResolution.spec.ts | 228 ++-- src/e2e/specs/dashboard.spec.ts | 1250 +++++++++--------- src/e2e/specs/landing.spec.ts | 274 ++-- src/e2e/specs/purchase.spec.ts | 362 ++--- 20 files changed, 1146 insertions(+), 1113 deletions(-) create mode 100644 src/app/functions/universal/isPrePlusDate.ts diff --git a/.env b/.env index 1ab1f6628ca..a86e9a734f9 100755 --- a/.env +++ b/.env @@ -115,8 +115,8 @@ E2E_TEST_ACCOUNT_EMAIL_ZERO_BROKERS= E2E_TEST_ACCOUNT_EMAIL_ZERO_BREACHES_ZERO_BROKERS= E2E_TEST_ACCOUNT_EMAIL_EXPOSURES_STARTED= -E2E_TEST_PAYPAL_LOGIN = -E2E_TEST_PAYPAL_PASSWORD = +E2E_TEST_PAYPAL_LOGIN= +E2E_TEST_PAYPAL_PASSWORD= # Monitor Premium features # Link to start user on the subscription process. PREMIUM_ENABLED must be set to `true`. diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 88b41611de9..b3301191072 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,8 +1,6 @@ name: Build -on: - pull_request: - types: [closed] +on: [push] jobs: npm-build: diff --git a/.github/workflows/docker_build_deploy.yml b/.github/workflows/docker_build_deploy.yml index c235a37807f..b26578fdc68 100644 --- a/.github/workflows/docker_build_deploy.yml +++ b/.github/workflows/docker_build_deploy.yml @@ -1,8 +1,8 @@ name: Build Docker image and publish on: - pull_request: - types: [closed] + push: + branches: [ main ] jobs: push_to_registry: name: Push Docker image to Docker Hub diff --git a/.github/workflows/docker_check.yml b/.github/workflows/docker_check.yml index 214f7667391..ef75f7751bc 100644 --- a/.github/workflows/docker_check.yml +++ b/.github/workflows/docker_check.yml @@ -1,7 +1,6 @@ name: Build Docker image check on: pull_request: - types: [closed] jobs: docker_build: name: Build Docker image diff --git a/.github/workflows/e2e_cron.yml b/.github/workflows/e2e_cron.yml index fd6b763836d..fa7e6074e24 100644 --- a/.github/workflows/e2e_cron.yml +++ b/.github/workflows/e2e_cron.yml @@ -48,7 +48,7 @@ jobs: run: npm run e2e timeout-minutes: 40 env: - E2E_TEST_ENV: ${{ inputs.environment != null && inputs.environment || 'local' }} + E2E_TEST_ENV: ${{ inputs.environment != null && inputs.environment || 'stage' }} E2E_TEST_BASE_URL: ${{ secrets.E2E_TEST_BASE_URL }} E2E_TEST_ACCOUNT_EMAIL: ${{ secrets.E2E_TEST_ACCOUNT_EMAIL }} E2E_TEST_ACCOUNT_PASSWORD: ${{ secrets.E2E_TEST_ACCOUNT_PASSWORD }} @@ -76,9 +76,10 @@ jobs: name: test-results path: src/e2e/test-results/ retention-days: 30 + - name: Send GitHub Action trigger data to Slack workflow id: slack - uses: slackapi/slack-github-action@v1.27.0 + uses: slackapi/slack-github-action@v1.26.0 if: failure() && github.ref == 'refs/heads/main' with: # For posting a message using Block Kit @@ -89,7 +90,7 @@ jobs: "type": "section", "text": { "type": "mrkdwn", - "text": "*Link to job:* **" + "text": "*Link to job:* **" } }, { @@ -126,3 +127,4 @@ jobs: env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_GHA_FAILURES_WEBHOOK }} SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK + \ No newline at end of file diff --git a/.github/workflows/e2e_pr_full.yml b/.github/workflows/e2e_pr_full.yml index ac99044c264..69e6b78f158 100644 --- a/.github/workflows/e2e_pr_full.yml +++ b/.github/workflows/e2e_pr_full.yml @@ -42,7 +42,6 @@ jobs: PLAYWRIGHT_VERSION=$(npx playwright --version | sed 's/Version //') echo "Playwright Version: $PLAYWRIGHT_VERSION" echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV - - name: Cache Playwright Browsers for Playwright's Version id: cache-playwright-browsers uses: actions/cache@v4 @@ -56,24 +55,31 @@ jobs: - name: Run Playwright tests if: github.actor != 'dependabot[bot]' - run: npm run e2e + run: npm run e2e -- --update-snapshots timeout-minutes: 40 env: - E2E_TEST_ENV: ${{ inputs.environment != null && inputs.environment || 'local' }} - E2E_TEST_BASE_URL: ${{ secrets.E2E_TEST_BASE_URL }} + E2E_TEST_ENV: local + E2E_TEST_BASE_URL: http://localhost:6060 E2E_TEST_ACCOUNT_EMAIL: ${{ secrets.E2E_TEST_ACCOUNT_EMAIL }} - E2E_TEST_ACCOUNT_PASSWORD: ${{ secrets.E2E_TEST_ACCOUNT_PASSWORD }} E2E_TEST_ACCOUNT_EMAIL_ZERO_BREACHES: ${{ secrets.E2E_TEST_ACCOUNT_EMAIL_ZERO_BREACHES }} E2E_TEST_ACCOUNT_EMAIL_EXPOSURES_STARTED: ${{ secrets.E2E_TEST_ACCOUNT_EMAIL_EXPOSURES_STARTED }} - E2E_TEST_PAYPAL_LOGIN: ${{ secrets.E2E_TEST_PAYPAL_LOGIN }} + E2E_TEST_ACCOUNT_PASSWORD: ${{ secrets.E2E_TEST_ACCOUNT_PASSWORD }} + E2E_TEST_PAYPAL_LOGIN: ${{ secrets.E2E_TEST_PAYPAL_LOGIN }} E2E_TEST_PAYPAL_PASSWORD: ${{ secrets.E2E_TEST_PAYPAL_PASSWORD }} ADMINS: ${{ secrets.ADMINS }} - OAUTH_CLIENT_SECRET: ${{ secrets.OAUTH_CLIENT_SECRET }} + OAUTH_CLIENT_SECRET: ${{ secrets.OAUTH_CLIENT_SECRET_LOCAL }} + OAUTH_ACCOUNT_URI: ${{ secrets.OAUTH_ACCOUNT_URI }} ONEREP_API_KEY: ${{ secrets.ONEREP_API_KEY }} NEXTAUTH_SECRET: ${{ secrets.NEXTAUTH_SECRET }} NEXTAUTH_URL: ${{ secrets.NEXTAUTH_URL }} + DATABASE_URL: postgres://postgres:postgres@localhost:5432/blurts HIBP_KANON_API_TOKEN: ${{ secrets.HIBP_KANON_API_TOKEN }} HIBP_API_TOKEN: ${{ secrets.HIBP_API_TOKEN }} + HIBP_KANON_API_ROOT: "http://localhost:6060/api/mock/hibp" + ONEREP_API_BASE: "http://localhost:6060/api/mock/onerep/" + PREMIUM_PRODUCT_ID: ${{ secrets.STAGE_PREMIUM_PRODUCT_ID }} + PREMIUM_PLAN_ID_MONTHLY_US: ${{ secrets.STAGE_PREMIUM_PLAN_ID_MONTHLY_US }} + PREMIUM_PLAN_ID_YEARLY_US: ${{ secrets.STAGE_PREMIUM_PLAN_ID_YEARLY_US }} REDIS_URL: "redis://redis.mock" - uses: actions/upload-artifact@v4 if: always() diff --git a/.github/workflows/e2e_pr_smoke.yml b/.github/workflows/e2e_pr_smoke.yml index 35df9fef3b9..6b5ae439c77 100644 --- a/.github/workflows/e2e_pr_smoke.yml +++ b/.github/workflows/e2e_pr_smoke.yml @@ -42,7 +42,6 @@ jobs: PLAYWRIGHT_VERSION=$(npx playwright --version | sed 's/Version //') echo "Playwright Version: $PLAYWRIGHT_VERSION" echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV - - name: Cache Playwright Browsers for Playwright's Version id: cache-playwright-browsers uses: actions/cache@v4 @@ -65,7 +64,7 @@ jobs: E2E_TEST_ACCOUNT_EMAIL_ZERO_BREACHES: ${{ secrets.E2E_TEST_ACCOUNT_EMAIL_ZERO_BREACHES }} E2E_TEST_ACCOUNT_EMAIL_EXPOSURES_STARTED: ${{ secrets.E2E_TEST_ACCOUNT_EMAIL_EXPOSURES_STARTED }} E2E_TEST_ACCOUNT_PASSWORD: ${{ secrets.E2E_TEST_ACCOUNT_PASSWORD }} - E2E_TEST_PAYPAL_LOGIN: ${{ secrets.E2E_TEST_PAYPAL_LOGIN }} + E2E_TEST_PAYPAL_LOGIN: ${{ secrets.E2E_TEST_PAYPAL_LOGIN }} E2E_TEST_PAYPAL_PASSWORD: ${{ secrets.E2E_TEST_PAYPAL_PASSWORD }} ADMINS: ${{ secrets.ADMINS }} OAUTH_CLIENT_SECRET: ${{ secrets.OAUTH_CLIENT_SECRET_LOCAL }} @@ -78,9 +77,6 @@ jobs: HIBP_API_TOKEN: ${{ secrets.HIBP_API_TOKEN }} HIBP_KANON_API_ROOT: "http://localhost:6060/api/mock/hibp" ONEREP_API_BASE: "http://localhost:6060/api/mock/onerep/" - # MNTOR-3516: Our tests are currently set up to expect accounts to act like - # old user accounts, so let's pretend they all are: - BROKER_SCAN_RELEASE_DATE: "3000-12-31" REDIS_URL: "redis://redis.mock" - uses: actions/upload-artifact@v4 if: always() diff --git a/.github/workflows/preview_deploy_gcp.yml b/.github/workflows/preview_deploy_gcp.yml index 9115a1a72a0..c6fdef23a32 100644 --- a/.github/workflows/preview_deploy_gcp.yml +++ b/.github/workflows/preview_deploy_gcp.yml @@ -1,8 +1,7 @@ name: Deploy Preview -on: +on: pull_request: - types: [closed] env: PROJECT_ID: ${{ secrets.GCP_PROJECT }} diff --git a/.github/workflows/reference_linter.yaml b/.github/workflows/reference_linter.yaml index 0355144fb89..173b7180b3d 100644 --- a/.github/workflows/reference_linter.yaml +++ b/.github/workflows/reference_linter.yaml @@ -1,7 +1,8 @@ name: Lint Reference Files on: + push: pull_request: - types: [closed] + workflow_dispatch: jobs: l10n-lint: runs-on: ubuntu-latest diff --git a/.github/workflows/unittests.yaml b/.github/workflows/unittests.yaml index b8ef110377a..83c3a974b96 100644 --- a/.github/workflows/unittests.yaml +++ b/.github/workflows/unittests.yaml @@ -1,8 +1,6 @@ name: Unit Tests -on: - pull_request: - types: [closed] +on: [push] jobs: unit-tests: diff --git a/playwright.config.js b/playwright.config.js index 1c3039b2b66..f400189f150 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -51,7 +51,7 @@ export default defineConfig({ forbidOnly: !!process.env.CI, /* Limit the number of failures */ - maxFailures: process.env.CI ? 1 : undefined, + maxFailures: 1, /* Retry on CI only */ retries: process.env.CI ? 1 : 0, @@ -68,8 +68,7 @@ export default defineConfig({ actionTimeout: 0, /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: process.env.E2E_TEST_BASE_URL ?? 'https://stage.firefoxmonitor.nonprod.cloudops.mozgcp.net', - // baseURL: 'http://localhost:6060', + baseURL: process.env.E2E_TEST_BASE_URL, /* automatically take screenshot only on failures */ screenshot: 'only-on-failure', diff --git a/src/app/functions/server/isPrePlusUser.ts b/src/app/functions/server/isPrePlusUser.ts index 149d0010d53..7d085867be7 100644 --- a/src/app/functions/server/isPrePlusUser.ts +++ b/src/app/functions/server/isPrePlusUser.ts @@ -4,7 +4,7 @@ import "server-only"; import { Session } from "next-auth"; -import { parseIso8601Datetime } from "../../../utils/parse"; +import { isPrePlusDate } from "../universal/isPrePlusDate"; /** * Determine whether the user's account predates Monitor Plus @@ -20,22 +20,8 @@ export function isPrePlusUser(user: Session["user"]): boolean { return false; } - const brokerScanReleaseDateParts = ( - process.env.BROKER_SCAN_RELEASE_DATE ?? "" - ).split("-"); - if (brokerScanReleaseDateParts[0] === "") { - brokerScanReleaseDateParts[0] = "2023"; - } - const brokerScanReleaseDate = new Date( - Date.UTC( - Number.parseInt(brokerScanReleaseDateParts[0], 10), - Number.parseInt(brokerScanReleaseDateParts[1] ?? "12", 10) - 1, - Number.parseInt(brokerScanReleaseDateParts[2] ?? "05", 10), - ), - ); - - return ( - (parseIso8601Datetime(user.subscriber.created_at)?.getTime() ?? 0) < - brokerScanReleaseDate.getTime() + return isPrePlusDate( + process.env.BROKER_SCAN_RELEASE_DATE ?? "", + user.subscriber.created_at, ); } diff --git a/src/app/functions/universal/isPrePlusDate.ts b/src/app/functions/universal/isPrePlusDate.ts new file mode 100644 index 00000000000..3ade92ea07a --- /dev/null +++ b/src/app/functions/universal/isPrePlusDate.ts @@ -0,0 +1,27 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { parseIso8601Datetime } from "../../../utils/parse"; + +export function isPrePlusDate( + plusReleaseDateString: string, + dateStringToCompare: string, +) { + const brokerScanReleaseDateParts = plusReleaseDateString.split("-"); + if (brokerScanReleaseDateParts[0] === "") { + brokerScanReleaseDateParts[0] = "2023"; + } + const brokerScanReleaseDate = new Date( + Date.UTC( + Number.parseInt(brokerScanReleaseDateParts[0], 10), + Number.parseInt(brokerScanReleaseDateParts[1] ?? "12", 10) - 1, + Number.parseInt(brokerScanReleaseDateParts[2] ?? "05", 10), + ), + ); + + return ( + (parseIso8601Datetime(dateStringToCompare)?.getTime() ?? 0) < + brokerScanReleaseDate.getTime() + ); +} diff --git a/src/e2e/pages/purchasePage.ts b/src/e2e/pages/purchasePage.ts index 2892c736f75..64ba48aad49 100644 --- a/src/e2e/pages/purchasePage.ts +++ b/src/e2e/pages/purchasePage.ts @@ -124,7 +124,7 @@ export class PurchasePage { (await this.planDetails.textContent()) as string, ); expect(planDetails).toContain( - `${process.env.E2E_TEST_ENV === "prod" ? "yearly" : "every 2 months"}`, + `${process.env.E2E_TEST_ENV !== "production" ? "every 2 months" : "yearly"}`, ); } diff --git a/src/e2e/pages/welcomeScanPage.ts b/src/e2e/pages/welcomeScanPage.ts index 2368ef638e0..c840c42adb7 100644 --- a/src/e2e/pages/welcomeScanPage.ts +++ b/src/e2e/pages/welcomeScanPage.ts @@ -28,6 +28,8 @@ export class WelcomePage { readonly modalConfirmButton: Locator; readonly modalEditButton: Locator; + readonly findExposuresTitle: Locator; + constructor(page: Page) { this.page = page; @@ -67,9 +69,11 @@ export class WelcomePage { this.isThisCorrectModal = page.getByLabel("Is this correct?"); this.modalConfirmButton = page.getByRole("button", { name: "Confirm" }); this.modalEditButton = page.getByRole("button", { name: "Edit" }); + + this.findExposuresTitle = page.getByText("Scanning for exposures…"); } - async goThroughFirstScan() { + async goThroughFirstScan(options: { skipLoader: boolean }) { // confirm get started step elements expect(await this.getStartedStep.count()).toEqual(3); await expect(this.page.getByText("Get started")).toBeVisible(); @@ -88,6 +92,15 @@ export class WelcomePage { await this.findExposuresButton.click(); await this.modalConfirmButton.click(); + await this.findExposuresTitle.waitFor(); + + // reloading page skips the loader and routes directly to the dashboard + if (options.skipLoader) { + // wait for scan to be finished before reloading the page + await this.page.waitForTimeout(10000); + await this.page.reload(); + } + // Waiting for scan to complete const dashboardPage = new DashboardPage(this.page); await dashboardPage.actionNeededTab.waitFor(); diff --git a/src/e2e/specs/auth.spec.ts b/src/e2e/specs/auth.spec.ts index ee6a098852e..3e80f08d62d 100644 --- a/src/e2e/specs/auth.spec.ts +++ b/src/e2e/specs/auth.spec.ts @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +import { isPrePlusDate } from "../../app/functions/universal/isPrePlusDate.js"; import { test, expect } from "../fixtures/basePage.js"; test.describe(`${process.env.E2E_TEST_ENV} - Authentication flow verification @smoke`, () => { @@ -14,7 +15,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Authentication flow verification @s authPage, landingPage, }, testInfo) => { - // speed up test by ignore non necessary requests + // speed up test by ignoring non-necessary requests await page.route(/(analytics)/, async (route) => { await route.abort(); }); @@ -23,12 +24,20 @@ test.describe(`${process.env.E2E_TEST_ENV} - Authentication flow verification @s await landingPage.goToSignIn(); // Fill out sign up form - const randomEmail = `${Date.now()}_tstact@restmail.net`; + const currentTimestamp = Date.now(); + const randomEmail = `${currentTimestamp}_tstact@restmail.net`; await authPage.signUp(randomEmail, page); // assert successful login - const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/welcome`; - expect(page.url()).toBe(successUrl); + const successUrlSlugs = isPrePlusDate( + process.env.BROKER_SCAN_RELEASE_DATE ?? "", + new Date(currentTimestamp).toUTCString(), + ) + ? "/user/dashboard" + : "/user/welcome"; + expect(page.url()).toBe( + `${process.env.E2E_TEST_BASE_URL}${successUrlSlugs}`, + ); await testInfo.attach( `${process.env.E2E_TEST_ENV}-signup-monitor-dashboard.png`, diff --git a/src/e2e/specs/breachResolution.spec.ts b/src/e2e/specs/breachResolution.spec.ts index 16bcd0a4a7e..b754364156b 100644 --- a/src/e2e/specs/breachResolution.spec.ts +++ b/src/e2e/specs/breachResolution.spec.ts @@ -3,118 +3,132 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { test, expect } from "../fixtures/basePage.js"; +import { checkAuthState } from "../utils/helpers.js"; // bypass login test.use({ storageState: "./e2e/storageState.json" }); -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Headers`, - () => { - test("Verify that the site header is displayed correctly for signed in users", async ({ - dataBreachPage, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2095101", - }); - - // should go directly to data breach page - await dataBreachPage.open(); - - // verify logo and profile button - await expect(dataBreachPage.dataBreachesLogo).toBeVisible(); - await expect(dataBreachPage.dataBreachesNavbarProfile).toBeVisible(); +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Headers`, () => { + test.beforeEach(async ({ dashboardPage, welcomePage, page }) => { + await dashboardPage.open(); + + try { + await checkAuthState(page); + } catch { + console.log("[E2E_LOG] - No fxa auth required, proceeding..."); + } + + // if we landed on the welcome flow a new user who is eligible for premium + // and needs to go through their first scan + const isWelcomeFlow = + page.url() === `${process.env.E2E_TEST_BASE_URL}/user/welcome`; + if (isWelcomeFlow) { + expect(page.url()).toContain("/user/welcome"); + await welcomePage.goThroughFirstScan({ skipLoader: true }); + } + }); + + test("Verify that the site header is displayed correctly for signed in users", async ({ + dataBreachPage, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2095101", }); - // skip as settings dropdown menu is currently wip for redesign TODO: update for redesign when its done - test.skip("Verify that the site header options work correctly for a signed in user", async ({ - dataBreachPage, - settingsPage, - page, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2095102", - }); - - // should go directly to data breach page - await settingsPage.open(); - - // verify logo and profile button - expect( - await dataBreachPage.dataBreachesLogoLink.first().getAttribute("href"), - ).toBe("/user/breaches"); - - await page.waitForLoadState("networkidle"); - await dataBreachPage.dataBreachesNavbarProfile.click(); - - // verify manage your Mozilla account link, settings option, help and support option, sign out option - // menu is open - expect(await dataBreachPage.profileMenuExpanded()).toBe(true); - - // menu header - await expect( - dataBreachPage.dataBreachesNavbarProfileMenuHeader, - ).toBeVisible(); - - // head text - await expect( - dataBreachPage.dataBreachesNavbarProfileMenuHeaderSubtitle, - ).toHaveText("Manage your Mozilla account"); - - // check settings - await expect( - dataBreachPage.dataBreachesNavbarProfileMenuSettings, - ).toBeVisible(); - - // help and support - await expect( - dataBreachPage.dataBreachesNavbarProfileMenuHelpAndSupport, - ).toBeVisible(); - - // sign out - await expect( - dataBreachPage.dataBreachesNavbarProfileMenuSignOut, - ).toBeVisible(); + // should go directly to data breach page + await dataBreachPage.open(); + + // verify logo and profile button + await expect(dataBreachPage.dataBreachesLogo).toBeVisible(); + await expect(dataBreachPage.dataBreachesNavbarProfile).toBeVisible(); + }); + + // skip as settings dropdown menu is currently wip for redesign TODO: update for redesign when its done + test.skip("Verify that the site header options work correctly for a signed in user", async ({ + dataBreachPage, + settingsPage, + page, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2095102", }); - test(" Verify that the user can navigate through the Monitor dashboard", async ({ - dashboardPage, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2095103", - }); - - // open dashboard page - await dashboardPage.open(); - - // get expected links - const links = dashboardPage.dashboardLinks(); - - // verify the navigation within monitor - // settings button redirects the user to "Settings" tab - await expect(dashboardPage.settingsPageLink).toHaveAttribute( - "href", - links.settingsNavButtonLink, - ); - - // redirects the user to the "Resolve data breaches (dashboard)" tab - await expect(dashboardPage.dashboardPageLink).toHaveAttribute( - "href", - links.resolveDataBreachesNavButtonLink, - ); - - // opens a new tab in which user is redirected to the "Monitor Help (FAQs)" page - await expect(dashboardPage.faqsPageLink).toHaveAttribute( - "href", - links.helpAndSupportNavButtonLink, - ); + // should go directly to data breach page + await settingsPage.open(); + + // verify logo and profile button + expect( + await dataBreachPage.dataBreachesLogoLink.first().getAttribute("href"), + ).toBe("/user/breaches"); + + await page.waitForLoadState("networkidle"); + await dataBreachPage.dataBreachesNavbarProfile.click(); + + // verify manage your Mozilla account link, settings option, help and support option, sign out option + // menu is open + expect(await dataBreachPage.profileMenuExpanded()).toBe(true); + + // menu header + await expect( + dataBreachPage.dataBreachesNavbarProfileMenuHeader, + ).toBeVisible(); + + // head text + await expect( + dataBreachPage.dataBreachesNavbarProfileMenuHeaderSubtitle, + ).toHaveText("Manage your Mozilla account"); + + // check settings + await expect( + dataBreachPage.dataBreachesNavbarProfileMenuSettings, + ).toBeVisible(); + + // help and support + await expect( + dataBreachPage.dataBreachesNavbarProfileMenuHelpAndSupport, + ).toBeVisible(); + + // sign out + await expect( + dataBreachPage.dataBreachesNavbarProfileMenuSignOut, + ).toBeVisible(); + }); + + test(" Verify that the user can navigate through the Monitor dashboard", async ({ + dashboardPage, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2095103", }); - }, -); + + // get expected links + const links = dashboardPage.dashboardLinks(); + + // verify the navigation within monitor + // settings button redirects the user to "Settings" tab + await expect(dashboardPage.settingsPageLink).toHaveAttribute( + "href", + links.settingsNavButtonLink, + ); + + // redirects the user to the "Resolve data breaches (dashboard)" tab + await expect(dashboardPage.dashboardPageLink).toHaveAttribute( + "href", + links.resolveDataBreachesNavButtonLink, + ); + + // opens a new tab in which user is redirected to the "Monitor Help (FAQs)" page + await expect(dashboardPage.faqsPageLink).toHaveAttribute( + "href", + links.helpAndSupportNavButtonLink, + ); + }); +}); diff --git a/src/e2e/specs/dashboard.spec.ts b/src/e2e/specs/dashboard.spec.ts index d30c1745e3b..b3f5e46d115 100644 --- a/src/e2e/specs/dashboard.spec.ts +++ b/src/e2e/specs/dashboard.spec.ts @@ -20,216 +20,222 @@ import { // bypass login test.use({ storageState: "./e2e/storageState.json" }); -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Headers @smoke`, - () => { - test.beforeEach(async ({ dashboardPage, page }) => { - await dashboardPage.open(); - - try { - await checkAuthState(page); - } catch { - console.log("[E2E_LOG] - No fxa auth required, proceeding..."); - } - }); +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Headers @smoke`, () => { + test.beforeEach(async ({ dashboardPage, welcomePage, page }) => { + await dashboardPage.open(); - test("Verify that the site header is displayed correctly for signed in users", async ({ - dashboardPage, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301512", - }); + try { + await checkAuthState(page); + } catch { + console.log("[E2E_LOG] - No fxa auth required, proceeding..."); + } + + // if we landed on the welcome flow a new user who is eligible for premium + // and needs to go through their first scan + const isWelcomeFlow = + page.url() === `${process.env.E2E_TEST_BASE_URL}/user/welcome`; + if (isWelcomeFlow) { + expect(page.url()).toContain("/user/welcome"); + await welcomePage.goThroughFirstScan({ skipLoader: true }); + } + }); - await expect(dashboardPage.dashboardNavButton).toHaveAttribute( - "href", - "/user/dashboard", - ); - await expect(dashboardPage.FAQsNavButton).toHaveAttribute( - "href", - "https://support.mozilla.org/kb/firefox-monitor-faq", - ); + test("Verify that the site header is displayed correctly for signed in users", async ({ + dashboardPage, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301512", }); - test("Verify that the site header and navigation bar is displayed correctly", async ({ - dashboardPage, - }) => { - // link to testrail - test.info().annotations.push( - { - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301511", - }, - { - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463567", - }, - ); - - // verify the navigation bar left side elements - await expect(dashboardPage.fireFoxMonitorLogoImgButton).toBeVisible(); - await expect(dashboardPage.dashboardNavButton).toBeVisible(); - await expect(dashboardPage.exposuresHeading).toBeVisible(); - await expect(dashboardPage.settingsPageLink).toBeVisible(); - await expect(dashboardPage.FAQsNavButton).toBeVisible(); - - // verify the site header elements - await expect(dashboardPage.actionNeededTab).toBeVisible(); - await expect(dashboardPage.fixedTab).toBeVisible(); - - // auto data removal button - await expect(dashboardPage.subscribeButton).toBeVisible(); - - // apps and services - await expect(dashboardPage.appsAndServices).toBeVisible(); - await dashboardPage.appsAndServices.click(); - await expect(dashboardPage.servicesVpn).toBeVisible(); - await expect(dashboardPage.servicesRelay).toBeVisible(); - await expect(dashboardPage.servicesPocket).toBeVisible(); - await expect(dashboardPage.servicesFirefoxDesktop).toBeVisible(); - await expect(dashboardPage.servicesFirefoxMobile).toBeVisible(); - - // profile button - await dashboardPage.closeAppsAndServices.click(); - await expect(dashboardPage.profileButton).toBeVisible(); - await dashboardPage.profileButton.click(); - await expect(dashboardPage.profileEmail).toBeVisible(); - await expect(dashboardPage.manageProfile).toBeVisible(); - await expect(dashboardPage.settingsPageLink).toBeVisible(); - await expect(dashboardPage.helpAndSupport).toBeVisible(); - await expect(dashboardPage.signOut).toBeVisible(); - }); + await expect(dashboardPage.dashboardNavButton).toHaveAttribute( + "href", + "/user/dashboard", + ); + await expect(dashboardPage.FAQsNavButton).toHaveAttribute( + "href", + "https://support.mozilla.org/kb/firefox-monitor-faq", + ); + }); - test("Verify that the correct message is displayed on the Action Needed tab when all the exposures are fixed", async ({ - dashboardPage, - }) => { - // link to testrail - test.info().annotations.push({ + test("Verify that the site header and navigation bar is displayed correctly", async ({ + dashboardPage, + }) => { + // link to testrail + test.info().annotations.push( + { type: "testrail", description: "https://testrail.stage.mozaws.net/index.php?/cases/view/2301511", - }); + }, + { + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463567", + }, + ); - // verify overview card - await expect(dashboardPage.dashboardMozLogo).toBeVisible(); + // verify the navigation bar left side elements + await expect(dashboardPage.fireFoxMonitorLogoImgButton).toBeVisible(); + await expect(dashboardPage.dashboardNavButton).toBeVisible(); + await expect(dashboardPage.exposuresHeading).toBeVisible(); + await expect(dashboardPage.settingsPageLink).toBeVisible(); + await expect(dashboardPage.FAQsNavButton).toBeVisible(); + + // verify the site header elements + await expect(dashboardPage.actionNeededTab).toBeVisible(); + await expect(dashboardPage.fixedTab).toBeVisible(); + + // auto data removal button + await expect(dashboardPage.subscribeButton).toBeVisible(); + + // apps and services + await expect(dashboardPage.appsAndServices).toBeVisible(); + await dashboardPage.appsAndServices.click(); + await expect(dashboardPage.servicesVpn).toBeVisible(); + await expect(dashboardPage.servicesRelay).toBeVisible(); + await expect(dashboardPage.servicesPocket).toBeVisible(); + await expect(dashboardPage.servicesFirefoxDesktop).toBeVisible(); + await expect(dashboardPage.servicesFirefoxMobile).toBeVisible(); + + // profile button + await dashboardPage.closeAppsAndServices.click(); + await expect(dashboardPage.profileButton).toBeVisible(); + await dashboardPage.profileButton.click(); + await expect(dashboardPage.profileEmail).toBeVisible(); + await expect(dashboardPage.manageProfile).toBeVisible(); + await expect(dashboardPage.settingsPageLink).toBeVisible(); + await expect(dashboardPage.helpAndSupport).toBeVisible(); + await expect(dashboardPage.signOut).toBeVisible(); + }); - // TODO: add verifications for all fixed exposures state + test("Verify that the correct message is displayed on the Action Needed tab when all the exposures are fixed", async ({ + dashboardPage, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301511", }); - test("Verify that the Fixed tab layout and tooltips are displayed correctly", async ({ - dashboardPage, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301532", - }); + // verify overview card + await expect(dashboardPage.dashboardMozLogo).toBeVisible(); - // verify fixed tab's tooltips and popups - await dashboardPage.fixedTab.click(); + // TODO: add verifications for all fixed exposures state + }); - // verify tooltip - await expect(dashboardPage.fixedHeading).toBeVisible(); - await dashboardPage.chartTooltip.click(); - await expect(dashboardPage.aboutFixedExposuresPopup).toBeVisible(); - await dashboardPage.popupCloseButton.click(); - await expect(dashboardPage.aboutFixedExposuresPopup).toBeHidden(); + test("Verify that the Fixed tab layout and tooltips are displayed correctly", async ({ + dashboardPage, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301532", }); - test("Verify that the Apps and Services header options work correctly.", async ({ - dashboardPage, - page, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463569", - }); + // verify fixed tab's tooltips and popups + await dashboardPage.fixedTab.click(); - await dashboardPage.fixedTab.click(); - expect(page.url()).toMatch(/.*dashboard\/fixed\/?/); - await dashboardPage.actionNeededTab.click(); - expect(page.url()).toMatch(/.*dashboard\/action-needed\/?/); - - //apps and services button check - const clickOnLinkAndGoBack = async ( - aTag: Locator, - host: string | RegExp = /.*/, - path: string | RegExp = /.*/, - ) => { - await expect(dashboardPage.appsAndServices).toBeVisible(); - await dashboardPage.appsAndServices.click(); - await expect(dashboardPage.appsAndServicesMenu).toBeVisible(); - await clickOnATagCheckDomain(aTag, host, path, page); - }; - - await clickOnLinkAndGoBack( - dashboardPage.servicesVpn, - "www.mozilla.org", - /.*\/products\/vpn\/?.*/, - ); - await clickOnLinkAndGoBack( - dashboardPage.servicesRelay, - "relay.firefox.com", - ); - await clickOnLinkAndGoBack( - dashboardPage.servicesPocket, - /getpocket\.com|apps\.apple\.com|app\.adjust\.com/, - /.*(\/pocket-and-firefox\/?).*|.*about.*|.*pocket-stay-informed.*/, - ); - await clickOnLinkAndGoBack( - dashboardPage.servicesFirefoxDesktop, - "www.mozilla.org", - /.*\/firefox\/new\/?.*/, - ); - await clickOnLinkAndGoBack( - dashboardPage.servicesFirefoxMobile, - "www.mozilla.org", - /.*\/browsers\/mobile\/?.*/, - ); - await clickOnLinkAndGoBack( - dashboardPage.servicesMozilla, - "www.mozilla.org", - ); + // verify tooltip + await expect(dashboardPage.fixedHeading).toBeVisible(); + await dashboardPage.chartTooltip.click(); + await expect(dashboardPage.aboutFixedExposuresPopup).toBeVisible(); + await dashboardPage.popupCloseButton.click(); + await expect(dashboardPage.aboutFixedExposuresPopup).toBeHidden(); + }); - const openProfileMenuItem = async ( - what: Locator, - whatUrl: string | RegExp, - ) => { - await dashboardPage.open(); - await dashboardPage.profileButton.click(); - await expect(what).toBeVisible(); - if (await what.evaluate((e) => e.hasAttribute("href"))) { - const href = await what.getAttribute("href"); - expect(href).not.toBeNull(); - await page.goto(href!); - } else { - await what.click(); - } - await page.waitForURL(whatUrl); - }; + test("Verify that the Apps and Services header options work correctly.", async ({ + dashboardPage, + page, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463569", + }); - await openProfileMenuItem( - dashboardPage.manageProfile, - /.*accounts.*settings.*/, - ); - await openProfileMenuItem( - dashboardPage.profileSettings, - /.*\/user\/settings.*/, - ); + await dashboardPage.fixedTab.click(); + expect(page.url()).toMatch(/.*dashboard\/fixed.*/); + await dashboardPage.actionNeededTab.click(); + expect(page.url()).toMatch(/.*dashboard\/action-needed.*/); + + //apps and services button check + const clickOnLinkAndGoBack = async ( + aTag: Locator, + host: string | RegExp = /.*/, + path: string | RegExp = /.*/, + ) => { + await expect(dashboardPage.appsAndServices).toBeVisible(); + await dashboardPage.appsAndServices.click(); + await expect(dashboardPage.appsAndServicesMenu).toBeVisible(); + await clickOnATagCheckDomain(aTag, host, path, page); + }; + + await clickOnLinkAndGoBack( + dashboardPage.servicesVpn, + "www.mozilla.org", + /.*\/products\/vpn\/?.*/, + ); + await clickOnLinkAndGoBack( + dashboardPage.servicesRelay, + "relay.firefox.com", + ); + await clickOnLinkAndGoBack( + dashboardPage.servicesPocket, + /getpocket\.com|apps\.apple\.com|app\.adjust\.com/, + /.*(\/pocket-and-firefox\/?).*|.*about.*|.*pocket-stay-informed.*/, + ); + await clickOnLinkAndGoBack( + dashboardPage.servicesFirefoxDesktop, + "www.mozilla.org", + /.*\/firefox\/new\/?.*/, + ); + await clickOnLinkAndGoBack( + dashboardPage.servicesFirefoxMobile, + "www.mozilla.org", + /.*\/browsers\/mobile\/?.*/, + ); + await clickOnLinkAndGoBack( + dashboardPage.servicesMozilla, + "www.mozilla.org", + ); - const base_url = process.env["E2E_TEST_BASE_URL"]; - expect(base_url).toBeTruthy(); - await openProfileMenuItem(dashboardPage.profileSignOut, base_url!); - }); - }, -); + const openProfileMenuItem = async ( + what: Locator, + whatUrl: string | RegExp, + ) => { + await dashboardPage.open(); + await dashboardPage.profileButton.click(); + await expect(what).toBeVisible(); + if (await what.evaluate((e) => e.hasAttribute("href"))) { + const href = await what.getAttribute("href"); + expect(href).not.toBeNull(); + await page.goto(href!); + } else { + await what.click(); + } + await page.waitForURL(whatUrl); + }; + + await openProfileMenuItem( + dashboardPage.manageProfile, + /.*accounts.*settings.*/, + ); + await openProfileMenuItem( + dashboardPage.profileSettings, + /.*\/user\/settings.*/, + ); + + const base_url = process.env["E2E_TEST_BASE_URL"]; + expect(base_url).toBeTruthy(); + await openProfileMenuItem(dashboardPage.profileSignOut, base_url!); + }); +}); // fix coming - playwright does not currently have access to the aws headers, skipping for now test.describe.skip( @@ -264,487 +270,469 @@ test.describe.skip( }, ); -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Content @smoke`, - () => { - test.beforeEach(async ({ dashboardPage, page }) => { - await dashboardPage.open(); +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Content @smoke`, () => { + test.beforeEach(async ({ dashboardPage, page }) => { + await dashboardPage.open(); - try { - await checkAuthState(page); - } catch { - console.log("[E2E_LOG] - No fxa auth required, proceeding..."); - } + try { + await checkAuthState(page); + } catch { + console.log("[E2E_LOG] - No fxa auth required, proceeding..."); + } + }); + + test("Verify that the exposure list contains action needed", async ({ + dashboardPage, + page, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301533", }); - test("Verify that the exposure list contains action needed", async ({ - dashboardPage, - page, - }) => { - // link to testrail - test.info().annotations.push({ + await expect(dashboardPage.exposuresHeading).toBeVisible(); + const listCount = await page + .locator('//div[starts-with(@class, "StatusPill_pill")]') + .count(); + + // verify exposure list conatins only exposures that need to be fixed + if (listCount > 0) { + for (let i = 0; i < listCount; i++) { + await expect( + page.locator( + `(//div[starts-with(@class, 'StatusPill_pill')])[${i + 1}]`, + ), + ).toHaveText("Action needed"); + } + } + }); + + test("Verify that the exposure list contains only fixed and in progress cards", async ({ + dashboardPage, + page, + }) => { + // link to testrail + test.info().annotations.push( + { type: "testrail", description: "https://testrail.stage.mozaws.net/index.php?/cases/view/2301533", - }); - - await expect(dashboardPage.exposuresHeading).toBeVisible(); - const listCount = await page - .locator('//div[starts-with(@class, "StatusPill_pill")]') - .count(); - - // verify exposure list conatins only exposures that need to be fixed - if (listCount > 0) { - for (let i = 0; i < listCount; i++) { - await expect( - page.locator( - `(//div[starts-with(@class, 'StatusPill_pill')])[${i + 1}]`, - ), - ).toHaveText("Action needed"); - } - } - }); - - test("Verify that the exposure list contains only fixed and in progress cards", async ({ - dashboardPage, - page, - }) => { - // link to testrail - test.info().annotations.push( - { - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301533", - }, - { - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2546463", - }, - ); + }, + { + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2546463", + }, + ); - await expect(dashboardPage.exposuresHeading).toBeVisible(); - await dashboardPage.fixedTab.click(); - - // verify fixed or in-progress - await expect(dashboardPage.fixedHeading).toBeVisible(); - - // TODO: add stub to fill in fixed/in-progress items - const listCount = await page - .locator('//div[starts-with(@class, "StatusPill_pill")]') - .count(); - // verify exposure list contains only exposures that need to be fixed - if (listCount > 0) { - for (let i = 0; i < listCount; i++) { - await expect( - page.locator( - `(//div[starts-with(@class, "StatusPill_pill")])[${i + 1}]`, - ), - ).toHaveText(/In progress|Fixed/); - } + await expect(dashboardPage.exposuresHeading).toBeVisible(); + await dashboardPage.fixedTab.click(); + + // verify fixed or in-progress + await expect(dashboardPage.fixedHeading).toBeVisible(); + + // TODO: add stub to fill in fixed/in-progress items + const listCount = await page + .locator('//div[starts-with(@class, "StatusPill_pill")]') + .count(); + // verify exposure list contains only exposures that need to be fixed + if (listCount > 0) { + for (let i = 0; i < listCount; i++) { + await expect( + page.locator( + `(//div[starts-with(@class, "StatusPill_pill")])[${i + 1}]`, + ), + ).toHaveText(/In progress|Fixed/); } - }); - }, -); + } + }); +}); -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Payment`, - () => { - test.beforeEach(async ({ dashboardPage, page }) => { - await dashboardPage.open(); +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Payment`, () => { + test.beforeEach(async ({ dashboardPage, page }) => { + await dashboardPage.open(); - try { - await checkAuthState(page); - } catch { - console.log("[E2E_LOG] - No fxa auth required, proceeding..."); - } - }); + try { + await checkAuthState(page); + } catch { + console.log("[E2E_LOG] - No fxa auth required, proceeding..."); + } + }); - test("Verify that the user can select what type of plan they want, verify that the Premium upsell modal is displayed correctly", async ({ - dashboardPage, - }) => { - test.info().annotations.push( - { - type: "testrail id #1", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301529", - }, - { - type: "testrail id #2", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463623", - }, - { - type: "testrail id #3", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463624", - }, - ); + test("Verify that the user can select what type of plan they want, verify that the Premium upsell modal is displayed correctly", async ({ + dashboardPage, + }) => { + test.info().annotations.push( + { + type: "testrail id #1", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301529", + }, + { + type: "testrail id #2", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463623", + }, + { + type: "testrail id #3", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463624", + }, + ); - await dashboardPage.subscribeButton.click(); - await dashboardPage.verifyPremiumUpsellModalOptions(); - }); - }, -); + await dashboardPage.subscribeButton.click(); + await dashboardPage.verifyPremiumUpsellModalOptions(); + }); +}); -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Breaches Scan, Continuous Protection, Data Profile Actions`, - () => { - test.use({ storageState: { cookies: [], origins: [] } }); +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Breaches Scan, Continuous Protection, Data Profile Actions`, () => { + test.use({ storageState: { cookies: [], origins: [] } }); - test.beforeEach(async ({ landingPage, page, authPage, welcomePage }) => { - test.slow( - true, - "this test runs through the welcome scan flow, increasing timeout to address it", - ); + test.beforeEach(async ({ landingPage, page, authPage, welcomePage }) => { + test.slow( + true, + "this test runs through the welcome scan flow, increasing timeout to address it", + ); - // speed up test by ignoring non necessary requests - await page.route(/(analytics)/, async (route) => { - await route.abort(); - }); + // speed up test by ignoring non necessary requests + await page.route(/(analytics)/, async (route) => { + await route.abort(); + }); - await landingPage.open(); - await landingPage.goToSignIn(); + await landingPage.open(); + await landingPage.goToSignIn(); - const randomEmail = `_${Date.now()}@restmail.net`; - await authPage.signUp(randomEmail, page); + const randomEmail = `_${Date.now()}@restmail.net`; + await authPage.signUp(randomEmail, page); - await page.waitForURL("**/user/welcome"); - await welcomePage.goThroughFirstScan(); - expect(page.url()).toContain("/user/dashboard"); - }); + await page.waitForURL("**/user/welcome"); + await welcomePage.goThroughFirstScan({ skipLoader: true }); + expect(page.url()).toContain("/user/dashboard"); + }); - test("Verify that the Premium upsell modal is displayed correctly - Continuous Protection, verify that the user can mark Data broker profiles as fixed", async ({ - dashboardPage, - }) => { - test.info().annotations.push( - { - type: "testrail id #1", - description: - "(continuous protection step) https://testrail.stage.mozaws.net/index.php?/cases/view/2463623", - }, - { - type: "testrail id #2", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463591", - }, - ); - let initialExposuresCount = - (await dashboardPage.numExposures.textContent()) as string; - initialExposuresCount = removeUnicodeChars(initialExposuresCount); - - if (initialExposuresCount !== "0") { - await dashboardPage.allExposures.first().click(); - await dashboardPage.fixExposureButton.click(); - await dashboardPage.removeExposuresManually.click(); - await dashboardPage.reviewAndRemoveProfiles.waitFor(); - - const count = await dashboardPage.allExposures.count(); - // Fix first exposure - await dashboardPage.markAsFixed.click(); - - for (let i = 1; i < count; i++) { - const exposure = dashboardPage.allExposures.nth(i); - await exposure.click(); - - if (await dashboardPage.markAsFixed.isVisible()) { - await dashboardPage.markAsFixed.click(); - } + test("Verify that the Premium upsell modal is displayed correctly - Continuous Protection, verify that the user can mark Data broker profiles as fixed", async ({ + dashboardPage, + }) => { + test.info().annotations.push( + { + type: "testrail id #1", + description: + "(continuous protection step) https://testrail.stage.mozaws.net/index.php?/cases/view/2463623", + }, + { + type: "testrail id #2", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463591", + }, + ); + let initialExposuresCount = + (await dashboardPage.numExposures.textContent()) as string; + initialExposuresCount = removeUnicodeChars(initialExposuresCount); + + if (initialExposuresCount !== "0") { + await dashboardPage.allExposures.first().click(); + await dashboardPage.fixExposureButton.click(); + await dashboardPage.removeExposuresManually.click(); + await dashboardPage.reviewAndRemoveProfiles.waitFor(); + + const count = await dashboardPage.allExposures.count(); + // Fix first exposure + await dashboardPage.markAsFixed.click(); + + for (let i = 1; i < count; i++) { + const exposure = dashboardPage.allExposures.nth(i); + await exposure.click(); + + if (await dashboardPage.markAsFixed.isVisible()) { + await dashboardPage.markAsFixed.click(); } - - await dashboardPage.skipExposureRemoval.click(); } - await dashboardPage.continuousProtectionButton.waitFor(); - await expect(dashboardPage.continuousProtectionButton).toBeVisible(); - await dashboardPage.continuousProtectionButton.click(); - await dashboardPage.verifyPremiumUpsellModalOptions(); - // Using toMatch to avoid invisible unicode chars mismatch - expect(await dashboardPage.numExposures.textContent()).toMatch("0"); - await dashboardPage.fixedTab.click(); - const fixedExposures = await dashboardPage.numFixed.textContent(); - expect(fixedExposures as string).toMatch(initialExposuresCount); - }); - }, -); + await dashboardPage.skipExposureRemoval.click(); + } + + await dashboardPage.continuousProtectionButton.waitFor(); + await expect(dashboardPage.continuousProtectionButton).toBeVisible(); + await dashboardPage.continuousProtectionButton.click(); + await dashboardPage.verifyPremiumUpsellModalOptions(); + // Using toMatch to avoid invisible unicode chars mismatch + expect(await dashboardPage.numExposures.textContent()).toMatch("0"); + await dashboardPage.fixedTab.click(); + const fixedExposures = await dashboardPage.numFixed.textContent(); + expect(fixedExposures as string).toMatch(initialExposuresCount); + }); +}); -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Overview Card`, - () => { - test.beforeEach(async ({ dashboardPage, page }) => { - await dashboardPage.open(); +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Overview Card`, () => { + test.beforeEach(async ({ dashboardPage, page }) => { + await dashboardPage.open(); - try { - await checkAuthState(page); - } catch { - console.log("[E2E_LOG] - No fxa auth required, proceeding..."); - } - }); + try { + await checkAuthState(page); + } catch { + console.log("[E2E_LOG] - No fxa auth required, proceeding..."); + } + }); - test("Verify that the Premium upsell screen is displayed correctly - overview card", async ({ - dashboardPage, - automaticRemovePage, - dataBrokersPage, - page, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463625", - }); + test("Verify that the Premium upsell screen is displayed correctly - overview card", async ({ + dashboardPage, + automaticRemovePage, + dataBrokersPage, + page, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463625", + }); - //checking that the user can reach upsell page - await dashboardPage.goToDashboard(); - await expect(dashboardPage.upsellScreenButton).toBeVisible(); - await dashboardPage.upsellScreenButton.click(); - await page.waitForURL(/.*\/fix\/.*\/view-data-brokers\/?/); - await dataBrokersPage.removeThemForMeButton.click(); - await page.waitForURL(/.*\/fix\/.*\/automatic-remove\/?/); + //checking that the user can reach upsell page + await dashboardPage.goToDashboard(); + await expect(dashboardPage.upsellScreenButton).toBeVisible(); + await dashboardPage.upsellScreenButton.click(); + await page.waitForURL(/.*\/fix\/.*\/view-data-brokers.*/); + await dataBrokersPage.removeThemForMeButton.click(); + await page.waitForURL(/.*\/fix\/.*\/automatic-remove.*/); + + //checking the bullet points + await expect(automaticRemovePage.ulElement).toBeVisible(); + + for (const itemText of automaticRemovePage.bulletPointsExpected) { + const liElement = automaticRemovePage.liElements.getByText(itemText); + await expect(liElement).toBeVisible(); + } + + //testing that toggles work + await automaticRemovePage.planToggle0.click(); + const price0 = await automaticRemovePage.price.textContent(); + const plan0 = await automaticRemovePage.plan.textContent(); + await automaticRemovePage.planToggle1.click(); + const price1 = await automaticRemovePage.price.textContent(); + const plan1 = await automaticRemovePage.plan.textContent(); + expect(price0).not.toEqual(price1); + expect(plan0).not.toEqual(plan1); + }); - //checking the bullet points - await expect(automaticRemovePage.ulElement).toBeVisible(); + test("Verify that the navigation of the Premium upsell screen works correctly - from overview card", async ({ + dashboardPage, + automaticRemovePage, + dataBrokersPage, + page, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463626", + }); - for (const itemText of automaticRemovePage.bulletPointsExpected) { - const liElement = automaticRemovePage.liElements.getByText(itemText); - await expect(liElement).toBeVisible(); - } + await dashboardPage.open(); + await page.waitForURL("**/dashboard/**"); + + //get the number of exposures count + const overviewCardSummary = + await dashboardPage.overviewCardSummary.textContent(); + const overviewCardFindings = + await dashboardPage.overviewCardFindings.textContent(); + expect(overviewCardFindings).not.toContain("No exposures found"); + expect(overviewCardSummary).not.toBeNull(); + const exposuresCountMatches = overviewCardSummary!.match(/\d+/); + expect(exposuresCountMatches).toBeTruthy(); + expect(exposuresCountMatches!.length).toBeGreaterThan(0); + const exposuresCount = parseInt(exposuresCountMatches![0]); + + //check that premium upsell screen loads + await dashboardPage.upsellScreenButton.click(); + await page.waitForURL(/.*\/fix\/.*\/view-data-brokers.*/); + await dataBrokersPage.removeThemForMeButton.click(); + await page.waitForURL(/.*\/fix\/.*\/automatic-remove.*/); + + //check that X returns back to /dashboard + await expect(automaticRemovePage.xButton).toBeVisible(); + + await automaticRemovePage.xButton.click(); + await page.waitForURL(dashboardPage.urlRegex); + + //forward arrow checks + await automaticRemovePage.open(); + await expect(automaticRemovePage.forwardArrowButton).toBeVisible(); + + const breachString0 = "high-risk-data-breaches"; + const breachString1 = "leaked-passwords"; + const breachString2 = "security-recommendations"; + + const breachOrDashboard = (excludeThis: string) => { + const escapedExclude = escapeRegExp(excludeThis); + const pattern = [ + dashboardPage.urlRegex.source, + breachString0, + breachString1, + breachString2, + ] + .map((s) => `.*${s}.*`) + .join("|"); + + return new RegExp(`^(?!.*${escapedExclude})(${pattern})`); + }; + + const checkBreachLink = async () => { + const currentUrl = page.url(); + await automaticRemovePage.forwardArrowButton.click(); + await page.waitForURL(breachOrDashboard(currentUrl)); + const urlToCheck = page.url(); + const breachStringRE = new RegExp( + `.*(${[breachString0, breachString1, breachString2].join("|")}).*`, + ); + return breachStringRE.test(urlToCheck); + }; - //testing that toggles work - await automaticRemovePage.planToggle0.click(); - const price0 = await automaticRemovePage.price.textContent(); - const plan0 = await automaticRemovePage.plan.textContent(); - await automaticRemovePage.planToggle1.click(); - const price1 = await automaticRemovePage.price.textContent(); - const plan1 = await automaticRemovePage.plan.textContent(); - expect(price0).not.toEqual(price1); - expect(plan0).not.toEqual(plan1); - }); + let iter = 0; + while (await checkBreachLink()) iter++; + const visitedBreachPages = iter !== 0; + const exposuresExist = exposuresCount !== 0; + expect(visitedBreachPages).toBe(exposuresExist); - test("Verify that the navigation of the Premium upsell screen works correctly - from overview card", async ({ - dashboardPage, - automaticRemovePage, - dataBrokersPage, - page, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463626", - }); + //price&plan toggle checks + await automaticRemovePage.open(); + const subplatRegex = /\/products\/prod_/; - await dashboardPage.open(); - await page.waitForURL("**/dashboard/**"); - - //get the number of exposures count - const overviewCardSummary = - await dashboardPage.overviewCardSummary.textContent(); - const overviewCardFindings = - await dashboardPage.overviewCardFindings.textContent(); - expect(overviewCardFindings).not.toContain("No exposures found"); - expect(overviewCardSummary).not.toBeNull(); - const exposuresCountMatches = overviewCardSummary!.match(/\d+/); - expect(exposuresCountMatches).toBeTruthy(); - expect(exposuresCountMatches!.length).toBeGreaterThan(0); - const exposuresCount = parseInt(exposuresCountMatches![0]); - - //check that premium upsell screen loads - await dashboardPage.upsellScreenButton.click(); - await page.waitForURL(/.*\/fix\/.*\/view-data-brokers\/?/); - await dataBrokersPage.removeThemForMeButton.click(); - await page.waitForURL(/.*\/fix\/.*\/automatic-remove\/?/); - - //check that X returns back to /dashboard - await expect(automaticRemovePage.xButton).toBeVisible(); - - await automaticRemovePage.xButton.click(); - await page.waitForURL(dashboardPage.urlRegex); - - //forward arrow checks - await automaticRemovePage.open(); - await expect(automaticRemovePage.forwardArrowButton).toBeVisible(); - - const breachString0 = "high-risk-data-breaches"; - const breachString1 = "leaked-passwords"; - const breachString2 = "security-recommendations"; - - const breachOrDashboard = (excludeThis: string) => { - const escapedExclude = escapeRegExp(excludeThis); - const pattern = [ - dashboardPage.urlRegex.source, - breachString0, - breachString1, - breachString2, - ] - .map((s) => `.*${s}.*`) - .join("|"); - - return new RegExp(`^(?!.*${escapedExclude})(${pattern})`); - }; - - const checkBreachLink = async () => { - const currentUrl = page.url(); - await automaticRemovePage.forwardArrowButton.click(); - await page.waitForURL(breachOrDashboard(currentUrl)); - const urlToCheck = page.url(); - const breachStringRE = new RegExp( - `.*(${[breachString0, breachString1, breachString2].join("|")}).*`, - ); - return breachStringRE.test(urlToCheck); - }; - - let iter = 0; - while (await checkBreachLink()) iter++; - const visitedBreachPages = iter !== 0; - const exposuresExist = exposuresCount !== 0; - expect(visitedBreachPages).toBe(exposuresExist); - - //price&plan toggle checks + const checkToggleButtonWorks = async (toggleButton: Locator) => { await automaticRemovePage.open(); - const subplatRegex = /\/products\/prod_/; - - const checkToggleButtonWorks = async (toggleButton: Locator) => { - await automaticRemovePage.open(); - await expect(toggleButton).toBeVisible(); - await toggleButton.click(); - const toggleText = await toggleButton.textContent(); - expect(toggleText).not.toBeNull(); - await automaticRemovePage.subplatButton.click(); - await page.waitForURL(subplatRegex); - return page.url(); - }; - - const subplat0 = await checkToggleButtonWorks( - automaticRemovePage.planToggle0, - ); - const subplat1 = await checkToggleButtonWorks( - automaticRemovePage.planToggle1, - ); - expect(subplat0).not.toBe(subplat1); - }); - }, -); + await expect(toggleButton).toBeVisible(); + await toggleButton.click(); + const toggleText = await toggleButton.textContent(); + expect(toggleText).not.toBeNull(); + await automaticRemovePage.subplatButton.click(); + await page.waitForURL(subplatRegex); + return page.url(); + }; + + const subplat0 = await checkToggleButtonWorks( + automaticRemovePage.planToggle0, + ); + const subplat1 = await checkToggleButtonWorks( + automaticRemovePage.planToggle1, + ); + expect(subplat0).not.toBe(subplat1); + }); +}); -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Footer`, - () => { - test.beforeEach(async ({ dashboardPage, page }) => { - await dashboardPage.open(); - try { - await checkAuthState(page); - } catch { - console.log("[E2E_LOG] - No fxa auth required, proceeding..."); - } +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Footer`, () => { + test.beforeEach(async ({ dashboardPage, page }) => { + await dashboardPage.open(); + try { + await checkAuthState(page); + } catch { + console.log("[E2E_LOG] - No fxa auth required, proceeding..."); + } + }); + + test("Verify that the site footer is displayed correctly", async ({ + dashboardPage, + page, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463570", }); - test("Verify that the site footer is displayed correctly", async ({ - dashboardPage, + expect(process.env["E2E_TEST_BASE_URL"]).toBeTruthy(); + const baseUrl = process.env["E2E_TEST_BASE_URL"]!; + await dashboardPage.goToDashboard(); + await expect(page.locator("footer a >> img")).toBeVisible(); + await clickOnATagCheckDomain( + dashboardPage.mozillaLogoFooter, + "www.mozilla.org", + /^(\/en-US\/)?$/, page, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463570", - }); + ); + await clickOnATagCheckDomain( + dashboardPage.allBreachesFooter, + baseUrl, + "/breaches", + page, + ); + await clickOnATagCheckDomain( + dashboardPage.faqsFooter, + "support.mozilla.org", + /.*\/kb.*\/mozilla-monitor-faq.*/, + page, + ); + await clickOnATagCheckDomain( + dashboardPage.termsOfServiceFooter, + "www.mozilla.org", + "/about/legal/terms/subscription-services/", + page, + ); + await clickOnATagCheckDomain( + dashboardPage.privacyNoticeFooter, + "www.mozilla.org", + "/privacy/subscription-services/", + page, + ); + await clickOnATagCheckDomain( + dashboardPage.githubFooter, + "github.com", + "/mozilla/blurts-server", + page, + ); + }); +}); - expect(process.env["E2E_TEST_BASE_URL"]).toBeTruthy(); - const baseUrl = process.env["E2E_TEST_BASE_URL"]!; - await dashboardPage.goToDashboard(); - await expect(page.locator("footer a >> img")).toBeVisible(); - await clickOnATagCheckDomain( - dashboardPage.mozillaLogoFooter, - "www.mozilla.org", - /^(\/en-US\/)?$/, - page, - ); - await clickOnATagCheckDomain( - dashboardPage.allBreachesFooter, - baseUrl, - "/breaches", - page, - ); - await clickOnATagCheckDomain( - dashboardPage.faqsFooter, - "support.mozilla.org", - /.*\/kb.*\/mozilla-monitor-faq.*/, - page, - ); - await clickOnATagCheckDomain( - dashboardPage.termsOfServiceFooter, - "www.mozilla.org", - "/about/legal/terms/subscription-services/", - page, - ); - await clickOnATagCheckDomain( - dashboardPage.privacyNoticeFooter, - "www.mozilla.org", - "/privacy/subscription-services/", - page, - ); - await clickOnATagCheckDomain( - dashboardPage.githubFooter, - "github.com", - "/mozilla/blurts-server", - page, - ); - }); - }, -); +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Navigation @smoke`, () => { + test.beforeEach(async ({ dashboardPage, page }) => { + await dashboardPage.open(); -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Navigation @smoke`, - () => { - test.beforeEach(async ({ dashboardPage, page }) => { - await dashboardPage.open(); + try { + await checkAuthState(page); + } catch { + console.log("[E2E_LOG] - No fxa auth required, proceeding..."); + } + }); - try { - await checkAuthState(page); - } catch { - console.log("[E2E_LOG] - No fxa auth required, proceeding..."); - } + test("Verify that the navigation bar options work correctly", async ({ + dashboardPage, + page, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463568", }); - test("Verify that the navigation bar options work correctly", async ({ - dashboardPage, - page, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463568", - }); - - const goToHrefOf = async (aTag: Locator) => { - const href = await aTag.getAttribute("href"); - expect(href).toBeTruthy(); - await page.goto(href!); - }; - - //testrail's step 1 - await dashboardPage.goToDashboard(); - await goToHrefOf(dashboardPage.settingsPageLink); - await expect(page).toHaveURL(/\/settings$/); - - //testrail's step 2 - await goToHrefOf(dashboardPage.dashboardPageLink); - await expect(page).toHaveURL(/.*\/dashboard.*/); - - // testrail's step 3 - await dashboardPage.goToSettings(); - await goToHrefOf(dashboardPage.fireFoxMonitorLogoAtag); - await expect(page).toHaveURL(/.*\/dashboard.*/); - - //testrail's step 4 - await dashboardPage.goToDashboard(); - await goToHrefOf(dashboardPage.faqsPageLink); - await expect(page).toHaveURL( - /.*support\.mozilla\.org.*\/kb\/.*firefox-monitor-faq.*/, - ); - }); - }, -); + const goToHrefOf = async (aTag: Locator) => { + const href = await aTag.getAttribute("href"); + expect(href).toBeTruthy(); + await page.goto(href!); + }; + + //testrail's step 1 + await dashboardPage.goToDashboard(); + await goToHrefOf(dashboardPage.settingsPageLink); + await expect(page).toHaveURL(/\/settings$/); + + //testrail's step 2 + await goToHrefOf(dashboardPage.dashboardPageLink); + await expect(page).toHaveURL(/.*\/dashboard.*/); + + // testrail's step 3 + await dashboardPage.goToSettings(); + await goToHrefOf(dashboardPage.fireFoxMonitorLogoAtag); + await expect(page).toHaveURL(/.*\/dashboard.*/); + + //testrail's step 4 + await dashboardPage.goToDashboard(); + await goToHrefOf(dashboardPage.faqsPageLink); + await expect(page).toHaveURL( + /.*support\.mozilla\.org.*\/kb\/.*firefox-monitor-faq.*/, + ); + }); +}); // These tests rely heavily on mocks test.skip(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Data Breaches`, () => { @@ -774,7 +762,7 @@ test.skip(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Data Breaches`, () await expect(dashboardPage.upsellScreenButton).toBeVisible(); await dashboardPage.upsellScreenButton.click(); - await page.waitForURL(/.*\/data-broker-profiles\/view-data-brokers\/?/); + await page.waitForURL(/.*\/data-broker-profiles\/view-data-brokers.*/); await expect(dataBrokersPage.forwardArrowButton).toBeVisible(); await dataBrokersPage.forwardArrowButton.click(); await page.waitForURL(/.*\/high-risk-data-breaches.*/); diff --git a/src/e2e/specs/landing.spec.ts b/src/e2e/specs/landing.spec.ts index 5cd5edc5518..ddfa51ddc40 100644 --- a/src/e2e/specs/landing.spec.ts +++ b/src/e2e/specs/landing.spec.ts @@ -14,7 +14,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( await landingPage.open(); }); - test.skip("Observe page header", async ({ landingPage, page }) => { + test("Observe page header", async ({ landingPage, page }) => { // link to testrail case test.info().annotations.push({ type: "testrail", @@ -28,7 +28,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( expect(page.url()).toContain("oauth"); }); - test.skip('Observe "Find where your private info is exposed and take it back" section', async ({ + test('Observe "Find where your private info is exposed and take it back" section', async ({ landingPage, }) => { test.info().annotations.push({ @@ -48,7 +48,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( await expect(landingPage.monitorLandingMidHeading).toBeVisible(); }); - test.skip('Observe "We will help you fix your exposures" section', async ({ + test('Observe "We will help you fix your exposures" section', async ({ landingPage, }) => { test.info().annotations.push({ @@ -66,7 +66,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( await expect(landingPage.fixExposuresGraphic).toBeVisible(); }); - test.skip('Observe "What info could be at risk?" section', async ({ + test('Observe "What info could be at risk?" section', async ({ landingPage, }) => { test.info().annotations.push({ @@ -84,7 +84,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( await expect(landingPage.couldBeAtRiskGraphic).toBeVisible(); }); - test.skip('Observe "Scan your email to get started" section', async ({ + test('Observe "Scan your email to get started" section', async ({ landingPage, }) => { test.info().annotations.push({ @@ -99,7 +99,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( await expect(landingPage.getStartedScanFormSubmitButton).toBeVisible(); }); - test.skip('Observe "Choose your level of protection" section', async ({ + test('Observe "Choose your level of protection" section', async ({ landingPage, }) => { test.info().annotations.push({ @@ -114,7 +114,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( ); }); - test.skip("Observe FAQ section", async ({ landingPage }) => { + test("Observe FAQ section", async ({ landingPage }) => { test.info().annotations.push({ type: "testrail", description: @@ -127,7 +127,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( ); }); - test.skip('Observe "Take back control of your data" section', async ({ + test('Observe "Take back control of your data" section', async ({ landingPage, }) => { test.info().annotations.push({ @@ -145,7 +145,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( } }); - test.skip("Observe footer section", async ({ landingPage }) => { + test("Observe footer section", async ({ landingPage }) => { test.info().annotations.push({ type: "testrail", description: @@ -184,7 +184,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( await purchasePage.verifyYearlyPlanDetails(); }); - test.skip('Verify the "Get free scan" corresponding email fields', async ({ + test('Verify the "Get free scan" corresponding email fields', async ({ landingPage, authPage, }) => { @@ -219,7 +219,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( } }); - test.skip('Verify manual/automatic removal "more info" tips from "Choose your level of protection" section', async ({ + test('Verify manual/automatic removal "more info" tips from "Choose your level of protection" section', async ({ landingPage, }) => { test.info().annotations.push({ @@ -235,146 +235,140 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( }); }); -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Verify the Landing Page Functionality - without existing Account`, - () => { - test.beforeEach(async ({ landingPage }) => { - await landingPage.open(); +test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page Functionality - without existing Account`, () => { + test.beforeEach(async ({ landingPage }) => { + await landingPage.open(); + }); + + test('Verify "Get free scan" buttons functionality without existing account', async ({ + landingPage, + page, + authPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463502", }); - test('Verify "Get free scan" buttons functionality without existing account', async ({ - landingPage, - page, - authPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463502", + const randomEmail = `${Date.now()}_tstact@restmail.net`; + if (await emailInputShouldExist(landingPage)) { + await landingPage.monitorHeroFormEmailInputField.fill(randomEmail); + await landingPage.monitorHeroFormInputSubmitButton.click(); + await page.waitForURL("**/oauth/**"); + } else { + await landingPage.monitorHeroFormInputSubmitButton.click(); + await authPage.emailInputField.waitFor({ + state: "visible", + timeout: 10000, }); - - const randomEmail = `${Date.now()}_tstact@restmail.net`; - if (await emailInputShouldExist(landingPage)) { - await landingPage.monitorHeroFormEmailInputField.fill(randomEmail); - await landingPage.monitorHeroFormInputSubmitButton.click(); - await page.waitForURL("**/oauth/**"); - } else { - await landingPage.monitorHeroFormInputSubmitButton.click(); - await authPage.emailInputField.waitFor({ - state: "visible", - timeout: 10000, - }); - await authPage.emailInputField.fill(randomEmail); - await authPage.continueButton.click(); - } - // continue with the common steps - await authPage.passwordInputField.fill( - process.env.E2E_TEST_ACCOUNT_PASSWORD as string, - ); - await authPage.passwordConfirmInputField.fill( - process.env.E2E_TEST_ACCOUNT_PASSWORD as string, - ); - await authPage.ageInputField.fill("31"); + await authPage.emailInputField.fill(randomEmail); await authPage.continueButton.click(); - const vc = await getVerificationCode(randomEmail, page); - await authPage.enterVerificationCode(vc); - const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/welcome`; - expect(page.url()).toBe(successUrl); - }); - - test('Verify the "Start free monitoring" button UI and functionality without existing account', async ({ - landingPage, - page, - authPage, - }) => { - test.info().annotations.push( - { - type: "testrail id #1", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463524", - }, - { - type: "testrail id #2", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463564", - }, - ); - - await landingPage.startFreeMonitoringButton.click(); - - const randomEmail = `${Date.now()}_tstact@restmail.net`; - await authPage.signUp(randomEmail, page); - - const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/welcome`; - expect(page.url()).toBe(successUrl); - }); - }, -); - -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Verify the Landing Page Functionality - with existing account`, - () => { - test.beforeEach(async ({ landingPage }) => { - await landingPage.open(); - }); + } + // continue with the common steps + await authPage.passwordInputField.fill( + process.env.E2E_TEST_ACCOUNT_PASSWORD as string, + ); + await authPage.passwordConfirmInputField.fill( + process.env.E2E_TEST_ACCOUNT_PASSWORD as string, + ); + await authPage.ageInputField.fill("31"); + await authPage.continueButton.click(); + const vc = await getVerificationCode(randomEmail, page); + await authPage.enterVerificationCode(vc); + const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/welcome`; + expect(page.url()).toBe(successUrl); + }); - test('Verify "Get free scan" buttons functionality with existing account', async ({ - landingPage, - page, - authPage, - }) => { - // link to testrail case - test.info().annotations.push({ - type: "testrail", + test('Verify the "Start free monitoring" button UI and functionality without existing account', async ({ + landingPage, + page, + authPage, + }) => { + test.info().annotations.push( + { + type: "testrail id #1", description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463503", - }); + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463524", + }, + { + type: "testrail id #2", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463564", + }, + ); + + await landingPage.startFreeMonitoringButton.click(); + + const randomEmail = `${Date.now()}_tstact@restmail.net`; + await authPage.signUp(randomEmail, page); - const existingEmail = process.env.E2E_TEST_ACCOUNT_EMAIL as string; - - if (await emailInputShouldExist(landingPage)) { - // Scenario where the form is still used - await landingPage.monitorHeroFormEmailInputField.fill(existingEmail); - await landingPage.monitorHeroFormInputSubmitButton.click(); - await page.waitForURL("**/oauth/**"); - } else { - // Scenario where direct redirection happens - await landingPage.monitorHeroFormInputSubmitButton.click(); - await authPage.emailInputField.waitFor({ - state: "visible", - timeout: 10000, - }); - await authPage.emailInputField.fill(existingEmail); - await authPage.continueButton.click(); - } - - // complete sign in form - await authPage.enterPassword(); - - // verify dashboard redirect - const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/dashboard`; - expect(page.url()).toBe(successUrl); + const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/welcome`; + expect(page.url()).toBe(successUrl); + }); +}); + +test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page Functionality - with existing account`, () => { + test.beforeEach(async ({ landingPage }) => { + await landingPage.open(); + }); + + test('Verify "Get free scan" buttons functionality with existing account', async ({ + landingPage, + page, + authPage, + }) => { + // link to testrail case + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463503", }); - test('Verify the "Start free monitoring" button UI and functionality with existing account', async ({ - landingPage, - page, - authPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463524", + const existingEmail = process.env.E2E_TEST_ACCOUNT_EMAIL as string; + + if (await emailInputShouldExist(landingPage)) { + // Scenario where the form is still used + await landingPage.monitorHeroFormEmailInputField.fill(existingEmail); + await landingPage.monitorHeroFormInputSubmitButton.click(); + await page.waitForURL("**/oauth/**"); + } else { + // Scenario where direct redirection happens + await landingPage.monitorHeroFormInputSubmitButton.click(); + await authPage.emailInputField.waitFor({ + state: "visible", + timeout: 10000, }); + await authPage.emailInputField.fill(existingEmail); + await authPage.continueButton.click(); + } - await landingPage.startFreeMonitoringButton.click(); + // complete sign in form + await authPage.enterPassword(); - await authPage.enterEmail(process.env.E2E_TEST_ACCOUNT_EMAIL as string); - await authPage.enterPassword(); + // verify dashboard redirect + const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/dashboard`; + expect(page.url()).toBe(successUrl); + }); - // verify dashboard redirect - const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/dashboard`; - expect(page.url()).toBe(successUrl); + test('Verify the "Start free monitoring" button UI and functionality with existing account', async ({ + landingPage, + page, + authPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463524", }); - }, -); + + await landingPage.startFreeMonitoringButton.click(); + + await authPage.enterEmail(process.env.E2E_TEST_ACCOUNT_EMAIL as string); + await authPage.enterPassword(); + + // verify dashboard redirect + const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/dashboard`; + expect(page.url()).toBe(successUrl); + }); +}); diff --git a/src/e2e/specs/purchase.spec.ts b/src/e2e/specs/purchase.spec.ts index d95242622c8..90d23f61d1a 100644 --- a/src/e2e/specs/purchase.spec.ts +++ b/src/e2e/specs/purchase.spec.ts @@ -5,197 +5,201 @@ import { test, expect } from "../fixtures/basePage.js"; import { checkAuthState, setEnvVariables } from "../utils/helpers.js"; -test.describe(`${process.env.E2E_TEST_ENV} - Breach Scan, Monitor Plus Purchase Flow`, () => { - test.beforeEach(async ({ page, authPage, landingPage, welcomePage }) => { - test.info().annotations.push({ - type: "testrail id", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463564", - }); +test.describe.skip( + `${process.env.E2E_TEST_ENV} - Breach Scan, Monitor Plus Purchase Flow`, + () => { + test.beforeEach(async ({ page, authPage, landingPage, welcomePage }) => { + test.info().annotations.push({ + type: "testrail id", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463564", + }); + + test.slow( + true, + "this test runs through the welcome scan flow, increasing timeout to address it", + ); - test.slow( - true, - "this test runs through the welcome scan flow, increasing timeout to address it", - ); + setEnvVariables(process.env.E2E_TEST_ACCOUNT_EMAIL as string); - setEnvVariables(process.env.E2E_TEST_ACCOUNT_EMAIL as string); + // speed up test by ignoring non necessary requests + await page.route(/(analytics)/, async (route) => { + await route.abort(); + }); - // speed up test by ignoring non necessary requests - await page.route(/(analytics)/, async (route) => { - await route.abort(); - }); + // start authentication flow + await landingPage.open(); + await landingPage.goToSignIn(); + + // Fill out sign up form + const randomEmail = `_${Date.now()}@restmail.net`; + await authPage.signUp(randomEmail, page); + + // wait for welcome page + await page.waitForURL("**/user/welcome"); + await welcomePage.goThroughFirstScan({ skipLoader: true }); - // start authentication flow - await landingPage.open(); - await landingPage.goToSignIn(); - - // Fill out sign up form - const randomEmail = `_${Date.now()}@restmail.net`; - await authPage.signUp(randomEmail, page); - - // wait for welcome page - await page.waitForURL("**/user/welcome"); - await welcomePage.goThroughFirstScan(); - expect(page.url()).toContain("/user/dashboard"); - }); - - test("Verify that the user can purchase the plus subscription with a Stripe card - Yearly", async ({ - dashboardPage, - purchasePage, - page, - }) => { - test.skip( - process.env.E2E_TEST_ENV === "production", - "payment method test not available in production", - ); - // link to testrail case - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463627", + expect(page.url()).toContain("/user/dashboard"); }); - try { - await checkAuthState(page); - } catch { - console.log( - "[E2E_LOG] - No fxa auth required, proceeding... with stripe yearly", + test("Verify that the user can purchase the plus subscription with a Stripe card - Yearly", async ({ + dashboardPage, + purchasePage, + page, + }) => { + test.skip( + process.env.E2E_TEST_ENV === "production", + "payment method test not available in production", ); - } - - // navigate to subscription - await dashboardPage.open(); - await dashboardPage.subscribeButton.click(); - await dashboardPage.subscribeDialogSelectYearlyPlanLink.click(); - await purchasePage.subscriptionHeader.waitFor(); - - // fill out subscription payment - await purchasePage.authorizationCheckbox.check(); - await purchasePage.fillOutStripeCardInfo(); - await purchasePage.payNowButton.click({ force: true }); - await page.getByText("Subscription confirmation").waitFor(); - // navigate to confirmation - await purchasePage.getStartedButton.click(); - await purchasePage.goToNextStep.waitFor(); - await purchasePage.goToNextStep.click(); - - // confirm successful payment - await dashboardPage.plusSubscription.waitFor(); - await expect(dashboardPage.plusSubscription).toBeVisible(); - }); - - test("Verify that the user can purchase the plus subscription with a Stripe card - Monthly", async ({ - purchasePage, - dashboardPage, - page, - }) => { - test.skip( - process.env.E2E_TEST_ENV === "production", - "payment method test not available in production", - ); - // link to multiple testrail cases - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463627", + // link to testrail case + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463627", + }); + + try { + await checkAuthState(page); + } catch { + console.log( + "[E2E_LOG] - No fxa auth required, proceeding... with stripe yearly", + ); + } + + // navigate to subscription + await dashboardPage.open(); + await dashboardPage.subscribeButton.click(); + await dashboardPage.subscribeDialogSelectYearlyPlanLink.click(); + await purchasePage.subscriptionHeader.waitFor(); + + // fill out subscription payment + await purchasePage.authorizationCheckbox.check(); + await purchasePage.fillOutStripeCardInfo(); + await purchasePage.payNowButton.click({ force: true }); + await page.getByText("Subscription confirmation").waitFor(); + // navigate to confirmation + await purchasePage.getStartedButton.click(); + await purchasePage.goToNextStep.waitFor(); + await purchasePage.goToNextStep.click(); + + // confirm successful payment + await dashboardPage.plusSubscription.waitFor(); + await expect(dashboardPage.plusSubscription).toBeVisible(); }); - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301529", + test("Verify that the user can purchase the plus subscription with a Stripe card - Monthly", async ({ + purchasePage, + dashboardPage, + page, + }) => { + test.skip( + process.env.E2E_TEST_ENV === "production", + "payment method test not available in production", + ); + // link to multiple testrail cases + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463627", + }); + + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301529", + }); + + try { + await checkAuthState(page); + } catch { + console.log( + "[E2E_LOG] - No fxa auth required, proceeding... with stripe monthly", + ); + } + + // navigate to subscription + await dashboardPage.open(); + await dashboardPage.subscribeButton.click(); + + // verify user purchase choices + await expect(dashboardPage.subscribeDialogCloseButton).toBeVisible(); + await expect(dashboardPage.yearlyMonthlyTablist).toBeVisible(); + await dashboardPage.yearlyTab.click(); + await expect( + dashboardPage.subscribeDialogSelectYearlyPlanLink, + ).toBeVisible(); + + await dashboardPage.monthlyTab.click(); + await expect( + dashboardPage.subscribeDialogSelectMonthlyPlanLink, + ).toBeVisible(); + + await dashboardPage.monthlyTab.click(); + await dashboardPage.subscribeDialogSelectMonthlyPlanLink.click(); + await purchasePage.subscriptionHeader.waitFor(); + + // fill out subscription payment + await purchasePage.authorizationCheckbox.waitFor(); + await purchasePage.authorizationCheckbox.check(); + await purchasePage.fillOutStripeCardInfo(); + await purchasePage.payNowButton.click({ force: true }); + await page.getByText("Subscription confirmation").waitFor(); + // navigate to confirmation + await purchasePage.getStartedButton.click(); + await purchasePage.goToNextStep.click(); + + // confirm successful payment + await dashboardPage.plusSubscription.waitFor({ + state: "attached", + timeout: 5000, + }); + await expect(dashboardPage.plusSubscription).toBeVisible(); }); - try { - await checkAuthState(page); - } catch { - console.log( - "[E2E_LOG] - No fxa auth required, proceeding... with stripe monthly", + test("Verify that the user can purchase the plus subscription with a PayPal account - yearly", async ({ + purchasePage, + dashboardPage, + context, + }) => { + test.skip( + process.env.E2E_TEST_ENV === "production", + "payment method test not available in production", ); - } - - // navigate to subscription - await dashboardPage.open(); - await dashboardPage.subscribeButton.click(); - - // verify user purchase choices - await expect(dashboardPage.subscribeDialogCloseButton).toBeVisible(); - await expect(dashboardPage.yearlyMonthlyTablist).toBeVisible(); - await dashboardPage.yearlyTab.click(); - await expect( - dashboardPage.subscribeDialogSelectYearlyPlanLink, - ).toBeVisible(); - - await dashboardPage.monthlyTab.click(); - await expect( - dashboardPage.subscribeDialogSelectMonthlyPlanLink, - ).toBeVisible(); - - await dashboardPage.monthlyTab.click(); - await dashboardPage.subscribeDialogSelectMonthlyPlanLink.click(); - await purchasePage.subscriptionHeader.waitFor(); - - // fill out subscription payment - await purchasePage.authorizationCheckbox.waitFor(); - await purchasePage.authorizationCheckbox.check(); - await purchasePage.fillOutStripeCardInfo(); - await purchasePage.payNowButton.click({ force: true }); - await page.getByText("Subscription confirmation").waitFor(); - // navigate to confirmation - await purchasePage.getStartedButton.click(); - await purchasePage.goToNextStep.click(); - - // confirm successful payment - await dashboardPage.plusSubscription.waitFor({ - state: "attached", - timeout: 5000, - }); - await expect(dashboardPage.plusSubscription).toBeVisible(); - }); - - test("Verify that the user can purchase the plus subscription with a PayPal account - yearly", async ({ - purchasePage, - dashboardPage, - context, - }) => { - test.skip( - process.env.E2E_TEST_ENV === "production", - "payment method test not available in production", - ); - // link to testrail case - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463628", + // link to testrail case + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463628", + }); + + await purchasePage.gotoPurchaseFromDashboard(dashboardPage, true); + // fill out subscription payment + await purchasePage.authorizationCheckbox.check(); + await purchasePage.fillOutPaypalInfo(context); + await purchasePage.postPaymentPageCheck(dashboardPage); }); - await purchasePage.gotoPurchaseFromDashboard(dashboardPage, true); - // fill out subscription payment - await purchasePage.authorizationCheckbox.check(); - await purchasePage.fillOutPaypalInfo(context); - await purchasePage.postPaymentPageCheck(dashboardPage); - }); - - test("Verify that the user can purchase the plus subscription with a PayPal account - monthly", async ({ - purchasePage, - dashboardPage, - context, - }) => { - test.skip( - process.env.E2E_TEST_ENV === "production", - "payment method test not available in production", - ); - // link to testrail case - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463628", + test("Verify that the user can purchase the plus subscription with a PayPal account - monthly", async ({ + purchasePage, + dashboardPage, + context, + }) => { + test.skip( + process.env.E2E_TEST_ENV === "production", + "payment method test not available in production", + ); + // link to testrail case + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463628", + }); + + await purchasePage.gotoPurchaseFromDashboard(dashboardPage, false); + // fill out subscription payment + await purchasePage.authorizationCheckbox.check(); + await purchasePage.fillOutPaypalInfo(context); + await purchasePage.postPaymentPageCheck(dashboardPage); }); - - await purchasePage.gotoPurchaseFromDashboard(dashboardPage, false); - // fill out subscription payment - await purchasePage.authorizationCheckbox.check(); - await purchasePage.fillOutPaypalInfo(context); - await purchasePage.postPaymentPageCheck(dashboardPage); - }); -}); + }, +); From fd6bc55dd825fb31cca985b57cbf881c65221be5 Mon Sep 17 00:00:00 2001 From: Florian Zia Date: Thu, 5 Sep 2024 23:01:28 +0200 Subject: [PATCH 05/10] chore: Run purchase E2E tests only on stage for now --- src/e2e/specs/purchase.spec.ts | 352 ++++++++++++++++----------------- 1 file changed, 169 insertions(+), 183 deletions(-) diff --git a/src/e2e/specs/purchase.spec.ts b/src/e2e/specs/purchase.spec.ts index 90d23f61d1a..d530d094bea 100644 --- a/src/e2e/specs/purchase.spec.ts +++ b/src/e2e/specs/purchase.spec.ts @@ -5,201 +5,187 @@ import { test, expect } from "../fixtures/basePage.js"; import { checkAuthState, setEnvVariables } from "../utils/helpers.js"; -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Breach Scan, Monitor Plus Purchase Flow`, - () => { - test.beforeEach(async ({ page, authPage, landingPage, welcomePage }) => { - test.info().annotations.push({ - type: "testrail id", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463564", - }); - - test.slow( - true, - "this test runs through the welcome scan flow, increasing timeout to address it", - ); - - setEnvVariables(process.env.E2E_TEST_ACCOUNT_EMAIL as string); - - // speed up test by ignoring non necessary requests - await page.route(/(analytics)/, async (route) => { - await route.abort(); - }); +test.describe(`${process.env.E2E_TEST_ENV} - Breach Scan, Monitor Plus Purchase Flow`, () => { + test.skip( + process.env.E2E_TEST_ENV !== "stage", + "Skip: Testing payment methods is only available on stage", + ); + + test.beforeEach(async ({ page, authPage, landingPage, welcomePage }) => { + test.info().annotations.push({ + type: "testrail id", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463564", + }); - // start authentication flow - await landingPage.open(); - await landingPage.goToSignIn(); + test.slow( + true, + "this test runs through the welcome scan flow, increasing timeout to address it", + ); - // Fill out sign up form - const randomEmail = `_${Date.now()}@restmail.net`; - await authPage.signUp(randomEmail, page); + setEnvVariables(process.env.E2E_TEST_ACCOUNT_EMAIL as string); - // wait for welcome page - await page.waitForURL("**/user/welcome"); - await welcomePage.goThroughFirstScan({ skipLoader: true }); + // speed up test by ignoring non necessary requests + await page.route(/(analytics)/, async (route) => { + await route.abort(); + }); - expect(page.url()).toContain("/user/dashboard"); + // start authentication flow + await landingPage.open(); + await landingPage.goToSignIn(); + + // Fill out sign up form + const randomEmail = `_${Date.now()}@restmail.net`; + await authPage.signUp(randomEmail, page); + + // wait for welcome page + await page.waitForURL("**/user/welcome"); + await welcomePage.goThroughFirstScan({ skipLoader: true }); + + expect(page.url()).toContain("/user/dashboard"); + }); + + test("Verify that the user can purchase the plus subscription with a Stripe card - Yearly", async ({ + dashboardPage, + purchasePage, + page, + }) => { + // link to testrail case + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463627", }); - test("Verify that the user can purchase the plus subscription with a Stripe card - Yearly", async ({ - dashboardPage, - purchasePage, - page, - }) => { - test.skip( - process.env.E2E_TEST_ENV === "production", - "payment method test not available in production", + try { + await checkAuthState(page); + } catch { + console.log( + "[E2E_LOG] - No fxa auth required, proceeding... with stripe yearly", ); - // link to testrail case - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463627", - }); - - try { - await checkAuthState(page); - } catch { - console.log( - "[E2E_LOG] - No fxa auth required, proceeding... with stripe yearly", - ); - } - - // navigate to subscription - await dashboardPage.open(); - await dashboardPage.subscribeButton.click(); - await dashboardPage.subscribeDialogSelectYearlyPlanLink.click(); - await purchasePage.subscriptionHeader.waitFor(); - - // fill out subscription payment - await purchasePage.authorizationCheckbox.check(); - await purchasePage.fillOutStripeCardInfo(); - await purchasePage.payNowButton.click({ force: true }); - await page.getByText("Subscription confirmation").waitFor(); - // navigate to confirmation - await purchasePage.getStartedButton.click(); - await purchasePage.goToNextStep.waitFor(); - await purchasePage.goToNextStep.click(); - - // confirm successful payment - await dashboardPage.plusSubscription.waitFor(); - await expect(dashboardPage.plusSubscription).toBeVisible(); + } + + // navigate to subscription + await dashboardPage.open(); + await dashboardPage.subscribeButton.click(); + await dashboardPage.subscribeDialogSelectYearlyPlanLink.click(); + await purchasePage.subscriptionHeader.waitFor(); + + // fill out subscription payment + await purchasePage.authorizationCheckbox.check(); + await purchasePage.fillOutStripeCardInfo(); + await purchasePage.payNowButton.click({ force: true }); + await page.getByText("Subscription confirmation").waitFor(); + // navigate to confirmation + await purchasePage.getStartedButton.click(); + await purchasePage.goToNextStep.waitFor(); + await purchasePage.goToNextStep.click(); + + // confirm successful payment + await dashboardPage.plusSubscription.waitFor(); + await expect(dashboardPage.plusSubscription).toBeVisible(); + }); + + test("Verify that the user can purchase the plus subscription with a Stripe card - Monthly", async ({ + purchasePage, + dashboardPage, + page, + }) => { + // link to multiple testrail cases + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463627", }); - test("Verify that the user can purchase the plus subscription with a Stripe card - Monthly", async ({ - purchasePage, - dashboardPage, - page, - }) => { - test.skip( - process.env.E2E_TEST_ENV === "production", - "payment method test not available in production", - ); - // link to multiple testrail cases - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463627", - }); - - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301529", - }); - - try { - await checkAuthState(page); - } catch { - console.log( - "[E2E_LOG] - No fxa auth required, proceeding... with stripe monthly", - ); - } - - // navigate to subscription - await dashboardPage.open(); - await dashboardPage.subscribeButton.click(); - - // verify user purchase choices - await expect(dashboardPage.subscribeDialogCloseButton).toBeVisible(); - await expect(dashboardPage.yearlyMonthlyTablist).toBeVisible(); - await dashboardPage.yearlyTab.click(); - await expect( - dashboardPage.subscribeDialogSelectYearlyPlanLink, - ).toBeVisible(); - - await dashboardPage.monthlyTab.click(); - await expect( - dashboardPage.subscribeDialogSelectMonthlyPlanLink, - ).toBeVisible(); - - await dashboardPage.monthlyTab.click(); - await dashboardPage.subscribeDialogSelectMonthlyPlanLink.click(); - await purchasePage.subscriptionHeader.waitFor(); - - // fill out subscription payment - await purchasePage.authorizationCheckbox.waitFor(); - await purchasePage.authorizationCheckbox.check(); - await purchasePage.fillOutStripeCardInfo(); - await purchasePage.payNowButton.click({ force: true }); - await page.getByText("Subscription confirmation").waitFor(); - // navigate to confirmation - await purchasePage.getStartedButton.click(); - await purchasePage.goToNextStep.click(); - - // confirm successful payment - await dashboardPage.plusSubscription.waitFor({ - state: "attached", - timeout: 5000, - }); - await expect(dashboardPage.plusSubscription).toBeVisible(); + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301529", }); - test("Verify that the user can purchase the plus subscription with a PayPal account - yearly", async ({ - purchasePage, - dashboardPage, - context, - }) => { - test.skip( - process.env.E2E_TEST_ENV === "production", - "payment method test not available in production", + try { + await checkAuthState(page); + } catch { + console.log( + "[E2E_LOG] - No fxa auth required, proceeding... with stripe monthly", ); - // link to testrail case - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463628", - }); - - await purchasePage.gotoPurchaseFromDashboard(dashboardPage, true); - // fill out subscription payment - await purchasePage.authorizationCheckbox.check(); - await purchasePage.fillOutPaypalInfo(context); - await purchasePage.postPaymentPageCheck(dashboardPage); + } + + // navigate to subscription + await dashboardPage.open(); + await dashboardPage.subscribeButton.click(); + + // verify user purchase choices + await expect(dashboardPage.subscribeDialogCloseButton).toBeVisible(); + await expect(dashboardPage.yearlyMonthlyTablist).toBeVisible(); + await dashboardPage.yearlyTab.click(); + await expect( + dashboardPage.subscribeDialogSelectYearlyPlanLink, + ).toBeVisible(); + + await dashboardPage.monthlyTab.click(); + await expect( + dashboardPage.subscribeDialogSelectMonthlyPlanLink, + ).toBeVisible(); + + await dashboardPage.monthlyTab.click(); + await dashboardPage.subscribeDialogSelectMonthlyPlanLink.click(); + await purchasePage.subscriptionHeader.waitFor(); + + // fill out subscription payment + await purchasePage.authorizationCheckbox.waitFor(); + await purchasePage.authorizationCheckbox.check(); + await purchasePage.fillOutStripeCardInfo(); + await purchasePage.payNowButton.click({ force: true }); + await page.getByText("Subscription confirmation").waitFor(); + // navigate to confirmation + await purchasePage.getStartedButton.click(); + await purchasePage.goToNextStep.click(); + + // confirm successful payment + await dashboardPage.plusSubscription.waitFor({ + state: "attached", + timeout: 5000, + }); + await expect(dashboardPage.plusSubscription).toBeVisible(); + }); + + test("Verify that the user can purchase the plus subscription with a PayPal account - yearly", async ({ + purchasePage, + dashboardPage, + context, + }) => { + // link to testrail case + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463628", }); - test("Verify that the user can purchase the plus subscription with a PayPal account - monthly", async ({ - purchasePage, - dashboardPage, - context, - }) => { - test.skip( - process.env.E2E_TEST_ENV === "production", - "payment method test not available in production", - ); - // link to testrail case - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463628", - }); - - await purchasePage.gotoPurchaseFromDashboard(dashboardPage, false); - // fill out subscription payment - await purchasePage.authorizationCheckbox.check(); - await purchasePage.fillOutPaypalInfo(context); - await purchasePage.postPaymentPageCheck(dashboardPage); + await purchasePage.gotoPurchaseFromDashboard(dashboardPage, true); + // fill out subscription payment + await purchasePage.authorizationCheckbox.check(); + await purchasePage.fillOutPaypalInfo(context); + await purchasePage.postPaymentPageCheck(dashboardPage); + }); + + test("Verify that the user can purchase the plus subscription with a PayPal account - monthly", async ({ + purchasePage, + dashboardPage, + context, + }) => { + // link to testrail case + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463628", }); - }, -); + + await purchasePage.gotoPurchaseFromDashboard(dashboardPage, false); + // fill out subscription payment + await purchasePage.authorizationCheckbox.check(); + await purchasePage.fillOutPaypalInfo(context); + await purchasePage.postPaymentPageCheck(dashboardPage); + }); +}); From f68bda31146cbeda33b457860bc9e72479572823 Mon Sep 17 00:00:00 2001 From: Florian Zia Date: Tue, 17 Sep 2024 13:55:28 +0200 Subject: [PATCH 06/10] chore: Only run E2E test for PR opened agains main --- .github/workflows/e2e_pr_full.yml | 6 +++++- .github/workflows/e2e_pr_smoke.yml | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2e_pr_full.yml b/.github/workflows/e2e_pr_full.yml index 69e6b78f158..53fc16d181c 100644 --- a/.github/workflows/e2e_pr_full.yml +++ b/.github/workflows/e2e_pr_full.yml @@ -1,5 +1,9 @@ name: Monitor E2E Test Suite (full) -on: push +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] jobs: e2e-tests: timeout-minutes: 60 diff --git a/.github/workflows/e2e_pr_smoke.yml b/.github/workflows/e2e_pr_smoke.yml index b42151a4f55..3b225a11419 100644 --- a/.github/workflows/e2e_pr_smoke.yml +++ b/.github/workflows/e2e_pr_smoke.yml @@ -1,5 +1,9 @@ name: Monitor E2E Test Suite (smoke) -on: push +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] jobs: e2e-tests: timeout-minutes: 60 From 8d3813b8b61dc084693352995e210f4f945b909e Mon Sep 17 00:00:00 2001 From: Florian Zia Date: Tue, 17 Sep 2024 14:05:51 +0200 Subject: [PATCH 07/10] fix: Update node version for full E2E test suite --- .github/workflows/e2e_pr_full.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e_pr_full.yml b/.github/workflows/e2e_pr_full.yml index 53fc16d181c..cc2fa2ccb30 100644 --- a/.github/workflows/e2e_pr_full.yml +++ b/.github/workflows/e2e_pr_full.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: 22.6.x + node-version: 20.9.x - name: Install dependencies run: npm ci From 52d8b8f9e3c04fc83dfa89d6acfa8f0651628b44 Mon Sep 17 00:00:00 2001 From: Florian Zia Date: Wed, 25 Sep 2024 14:05:17 +0200 Subject: [PATCH 08/10] chore: Lower timeout for full E2E test suite --- .github/workflows/e2e_cron.yml | 2 +- .github/workflows/e2e_pr_full.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2e_cron.yml b/.github/workflows/e2e_cron.yml index 9d0be2dfb78..33750b7dcf8 100644 --- a/.github/workflows/e2e_cron.yml +++ b/.github/workflows/e2e_cron.yml @@ -46,7 +46,7 @@ jobs: - name: Run Playwright tests - ${{ inputs.environment != null && inputs.environment || 'stage' }} if: github.actor != 'dependabot[bot]' run: npm run e2e - timeout-minutes: 40 + timeout-minutes: 20 env: E2E_TEST_ENV: ${{ inputs.environment != null && inputs.environment || 'stage' }} E2E_TEST_BASE_URL: ${{ secrets.E2E_TEST_BASE_URL }} diff --git a/.github/workflows/e2e_pr_full.yml b/.github/workflows/e2e_pr_full.yml index cc2fa2ccb30..74187799c35 100644 --- a/.github/workflows/e2e_pr_full.yml +++ b/.github/workflows/e2e_pr_full.yml @@ -60,7 +60,7 @@ jobs: - name: Run Playwright tests if: github.actor != 'dependabot[bot]' run: npm run e2e -- --update-snapshots - timeout-minutes: 40 + timeout-minutes: 20 env: E2E_TEST_ENV: local E2E_TEST_BASE_URL: http://localhost:6060 From 319fc47be50bdcec6761df1eaade75989e25c3c4 Mon Sep 17 00:00:00 2001 From: Florian Zia Date: Thu, 26 Sep 2024 14:37:17 +0200 Subject: [PATCH 09/10] chore: Remove auth path for pre Plus users in E2E --- src/e2e/specs/auth.spec.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/e2e/specs/auth.spec.ts b/src/e2e/specs/auth.spec.ts index 3e80f08d62d..deeb03664bf 100644 --- a/src/e2e/specs/auth.spec.ts +++ b/src/e2e/specs/auth.spec.ts @@ -2,7 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { isPrePlusDate } from "../../app/functions/universal/isPrePlusDate.js"; import { test, expect } from "../fixtures/basePage.js"; test.describe(`${process.env.E2E_TEST_ENV} - Authentication flow verification @smoke`, () => { @@ -29,15 +28,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Authentication flow verification @s await authPage.signUp(randomEmail, page); // assert successful login - const successUrlSlugs = isPrePlusDate( - process.env.BROKER_SCAN_RELEASE_DATE ?? "", - new Date(currentTimestamp).toUTCString(), - ) - ? "/user/dashboard" - : "/user/welcome"; - expect(page.url()).toBe( - `${process.env.E2E_TEST_BASE_URL}${successUrlSlugs}`, - ); + expect(page.url()).toBe(`${process.env.E2E_TEST_BASE_URL}/user/welcome`); await testInfo.attach( `${process.env.E2E_TEST_ENV}-signup-monitor-dashboard.png`, From bc7962cbee7692d3516cec4aa35c4cd92b9db715 Mon Sep 17 00:00:00 2001 From: Florian Zia Date: Thu, 26 Sep 2024 14:54:03 +0200 Subject: [PATCH 10/10] chore: Rename E2E test workflows --- .github/workflows/e2e_pr_full.yml | 2 +- .github/workflows/e2e_pr_smoke.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2e_pr_full.yml b/.github/workflows/e2e_pr_full.yml index 74187799c35..7bb713cbace 100644 --- a/.github/workflows/e2e_pr_full.yml +++ b/.github/workflows/e2e_pr_full.yml @@ -5,7 +5,7 @@ on: pull_request: branches: [ main ] jobs: - e2e-tests: + e2e-tests-full: timeout-minutes: 60 runs-on: ubuntu-latest # Service containers to run with `container-job` diff --git a/.github/workflows/e2e_pr_smoke.yml b/.github/workflows/e2e_pr_smoke.yml index 3b225a11419..1f905c1ccef 100644 --- a/.github/workflows/e2e_pr_smoke.yml +++ b/.github/workflows/e2e_pr_smoke.yml @@ -5,7 +5,7 @@ on: pull_request: branches: [ main ] jobs: - e2e-tests: + e2e-tests-smoke: timeout-minutes: 60 runs-on: ubuntu-latest # Service containers to run with `container-job`