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..ad8eb8de7b5 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" ? "yearly" : "every 2 months"}`, ); } 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); - }); -}); + }, +);