From eba7c51701410432c087da8a7e7c50b0c8705d22 Mon Sep 17 00:00:00 2001 From: Mukhamediyar Kudaikulov Date: Thu, 25 Jul 2024 18:23:20 -0700 Subject: [PATCH 1/4] added more tests to smoke job, added tests for specific breach cases --- .github/workflows/e2e_pr.yml | 2 + src/e2e/pages/dashBoardPage.ts | 3 + src/e2e/specs/dashboard.spec.ts | 210 +++++++++++++++++++++++++------- src/e2e/utils/helpers.ts | 20 ++- 4 files changed, 187 insertions(+), 48 deletions(-) diff --git a/.github/workflows/e2e_pr.yml b/.github/workflows/e2e_pr.yml index b2264bbcb6b..0d8da17d3be 100644 --- a/.github/workflows/e2e_pr.yml +++ b/.github/workflows/e2e_pr.yml @@ -80,6 +80,8 @@ jobs: 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/" # 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" diff --git a/src/e2e/pages/dashBoardPage.ts b/src/e2e/pages/dashBoardPage.ts index 80cd54082bb..262d0986fbf 100644 --- a/src/e2e/pages/dashBoardPage.ts +++ b/src/e2e/pages/dashBoardPage.ts @@ -82,6 +82,7 @@ export class DashboardPage { readonly overviewCard: Locator; readonly overviewCardSummary: Locator; readonly overviewCardFindings: Locator; + readonly chartSvgExposuresCount: Locator; readonly upsellScreenButton: Locator; readonly urlRegex: RegExp; @@ -251,6 +252,8 @@ export class DashboardPage { this.overviewCardFindings = page.locator( "[aria-label='Dashboard summary'] > div > h3", ); + this.chartSvgExposuresCount = + this.overviewCard.locator("figure > div > svg"); //regex this.urlRegex = /\/dashboard\/(fixed|action-needed)\/?/; diff --git a/src/e2e/specs/dashboard.spec.ts b/src/e2e/specs/dashboard.spec.ts index 34908776270..5ac0a3e47fc 100644 --- a/src/e2e/specs/dashboard.spec.ts +++ b/src/e2e/specs/dashboard.spec.ts @@ -11,11 +11,16 @@ import { clickOnATagCheckDomain, escapeRegExp, forceLoginAs, + resetTestData, } from "../utils/helpers.js"; +import { + isUsingMockHIBPEndpoint, + isUsingMockONEREPEndpoint, +} from "../../app/functions/universal/mock.js"; // bypass login test.use({ storageState: "./e2e/storageState.json" }); -test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Headers`, () => { +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Headers @smoke`, () => { test.beforeEach(async ({ dashboardPage, page }) => { await dashboardPage.open(); @@ -256,7 +261,7 @@ test.describe.skip( }, ); -test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Content`, () => { +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Content @smoke`, () => { test.beforeEach(async ({ dashboardPage, page }) => { await dashboardPage.open(); @@ -336,7 +341,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Content`, () = }); }); -test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Payment`, () => { +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Payment`, () => { test.beforeEach(async ({ dashboardPage, page }) => { await dashboardPage.open(); @@ -451,7 +456,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Breaches Scan, }); }); -test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Overview Card`, () => { +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Overview Card @smoke`, () => { test.beforeEach(async ({ dashboardPage, page }) => { await dashboardPage.open(); @@ -669,7 +674,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Footer`, () => }); }); -test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Navigation`, () => { +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Navigation @smoke`, () => { test.beforeEach(async ({ dashboardPage, page }) => { await dashboardPage.open(); @@ -720,49 +725,160 @@ test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Navigation`, ( }); }); -// This test has inconsistent results - may need to rely on mocks. -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Data Breaches`, - () => { - test.beforeEach(async ({ landingPage, page, authPage }) => { - const emailToUse = process.env - .E2E_TEST_ACCOUNT_EMAIL_EXPOSURES_STARTED as string; - const pwdToUse = process.env.E2E_TEST_ACCOUNT_PASSWORD as string; - expect(emailToUse).not.toBeUndefined(); - expect(pwdToUse).not.toBeUndefined(); - await forceLoginAs(emailToUse, pwdToUse, page, landingPage, authPage); +// These tests rely heavily on mocks +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Data Breaches`, () => { + test.use({ storageState: { cookies: [], origins: [] } }); + + test("Verify that the High risk data breaches step is displayed correctly", async ({ + dashboardPage, + dataBrokersPage, + page, + landingPage, + authPage, + }) => { + const emailToUse = process.env.E2E_TEST_ACCOUNT_EMAIL_EXPOSURES_STARTED!; + const pwdToUse = process.env.E2E_TEST_ACCOUNT_PASSWORD!; + expect(emailToUse).not.toBeUndefined(); + expect(pwdToUse).not.toBeUndefined(); + await forceLoginAs(emailToUse, pwdToUse, page, landingPage, authPage); + + if (isUsingMockHIBPEndpoint()) await resetTestData(page, true, false); + if (isUsingMockONEREPEndpoint()) await resetTestData(page, false, true); + + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463592", }); - test("Verify that the High risk data breaches step is displayed correctly", async ({ - dashboardPage, - dataBrokersPage, - page, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463592", - }); + await expect(dashboardPage.upsellScreenButton).toBeVisible(); + await dashboardPage.upsellScreenButton.click(); + 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.*/); + const highRiskDataBreachLi = page.locator( + 'li:has(div:has-text("High risk data breaches"))', + ); + await expect(highRiskDataBreachLi).toBeVisible(); + await expect(highRiskDataBreachLi).toHaveAttribute("aria-current", "step"); + await expect( + highRiskDataBreachLi.locator("div").getByText("High risk data breaches"), + ).toBeVisible(); + }); - await expect(dashboardPage.upsellScreenButton).toBeVisible(); - await dashboardPage.upsellScreenButton.click(); - 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.*/); - const highRiskDataBreachLi = page.locator( - 'li:has(div:has-text("High risk data breaches"))', - ); - await expect(highRiskDataBreachLi).toBeVisible(); - await expect(highRiskDataBreachLi).toHaveAttribute( - "aria-current", - "step", - ); - await expect( - highRiskDataBreachLi - .locator("div") - .getByText("High risk data breaches"), - ).toBeVisible(); + test("Verify that the dashboard is displayed correctly for users with no scan results and no breaches", async ({ + dashboardPage, + page, + authPage, + landingPage, + }) => { + if (!isUsingMockHIBPEndpoint() || !isUsingMockONEREPEndpoint()) return; + + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463610", }); - }, -); + + const emailToUse = + process.env.E2E_TEST_ACCOUNT_EMAIL_ZERO_BREACHES_ZERO_BROKERS!; + const pwdToUse = process.env.E2E_TEST_ACCOUNT_PASSWORD!; + expect(emailToUse).not.toBeUndefined(); + expect(pwdToUse).not.toBeUndefined(); + await forceLoginAs(emailToUse, pwdToUse, page, landingPage, authPage); + await resetTestData(page, true, true); + await dashboardPage.open(); + + await expect(dashboardPage.overviewCard).toBeVisible(); + const textArea = dashboardPage.overviewCard.locator("section"); + await expect(textArea.getByText(/No exposures found/)).toBeVisible(); + await expect( + textArea.getByText( + /Great news! We searched all known data breaches and .\d+. data broker sites that sell personal info and found no exposures\./, + ), + ).toBeVisible(); + await expect(textArea.getByRole("button")).toBeVisible(); + expect(await dashboardPage.overviewCard.locator("svg").count()).toBe(5); + expect(await dashboardPage.overviewCard.locator("circle").count()).toBe(4); + await expect( + dashboardPage.chartSvgExposuresCount.getByText("Exposures"), + ).toBeVisible(); + await expect( + dashboardPage.chartSvgExposuresCount.getByText("0"), + ).toBeVisible(); + + await expect(dashboardPage.exposuresHeading).toBeVisible(); + expect(await dashboardPage.exposuresHeading.textContent()).toBe( + "View all sites where your info is exposed", + ); + + const noExpFoundMsg = page + .locator("div > strong") + .getByText("No exposures found"); + await expect(noExpFoundMsg).toBeVisible(); + }); + + test("Verify that the dashboard is displayed correctly for users with no scan results and with data breaches", async ({ + dashboardPage, + page, + authPage, + landingPage, + }) => { + if (!isUsingMockHIBPEndpoint() || !isUsingMockONEREPEndpoint()) return; + + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463611", + }); + + const emailToUse = process.env.E2E_TEST_ACCOUNT_EMAIL_ZERO_BROKERS!; + const pwdToUse = process.env.E2E_TEST_ACCOUNT_PASSWORD!; + expect(emailToUse).not.toBeUndefined(); + expect(pwdToUse).not.toBeUndefined(); + await forceLoginAs(emailToUse, pwdToUse, page, landingPage, authPage); + await resetTestData(page, true, true); + await dashboardPage.open(); + + // Assertions for the overview card + await expect(dashboardPage.overviewCard).toBeVisible(); + await expect( + page.getByText( + /You still have .\d+. exposures left to fix. Keep going and protect yourself\. We.ll guide you step-by-step\./, + ), + ).toBeVisible(); + await expect(dashboardPage.upsellScreenButton).toBeVisible(); + + // Chart reflecting results + await expect( + dashboardPage.chartSvgExposuresCount.getByText("Exposures"), + ).toBeVisible(); + await expect( + dashboardPage.chartSvgExposuresCount.getByText(/\d+/), + ).toBeVisible(); + + // Text above exposures list + await expect( + page.getByText("View all sites where your info is exposed"), + ).toBeVisible(); + await expect( + page.getByText( + /We found your information exposed .\d+. times over .\d+. data breaches and .0. data broker sites that are selling your personal info\./, + ), + ).toBeVisible(); + + // Exposures list + const exposureList = page.locator('[class*="exposureList"]'); + await expect(exposureList).toBeVisible(); + expect(await exposureList.locator("li").count()).toBeGreaterThan(0); + + // Click the "Let's keep going" button and check the redirection + await dashboardPage.upsellScreenButton.click(); + await page.waitForURL(/.*\/user\/dashboard\/fix.*/); + const dataBrokerFixed = page + .locator('[class*="FixNavigation"][class*="isCompleted"]') + .getByText("Data broker profiles"); + await expect(dataBrokerFixed).toBeVisible(); + }); +}); diff --git a/src/e2e/utils/helpers.ts b/src/e2e/utils/helpers.ts index 406bec589c4..0f081423dc1 100644 --- a/src/e2e/utils/helpers.ts +++ b/src/e2e/utils/helpers.ts @@ -170,7 +170,9 @@ export const clickOnATagCheckDomain = async ( page: Page, ) => { if (typeof host === "string") - host = new RegExp(escapeRegExp(host.replace(/^(https?:\/\/)/, ""))); + host = new RegExp( + escapeRegExp(host.replace(/^(https?:\/\/)/, "").replace(/:\d+$/, "")), + ); if (typeof path === "string") path = new RegExp(".*" + path + ".*"); const href = await aTag.getAttribute("href"); @@ -224,3 +226,19 @@ export const forceLoginAs = async ( export async function emailInputShouldExist(landingPage: LandingPage) { return 0 < (await landingPage.emailInputPrompt.count()); } + +export const resetTestData = async ( + page: Page, + hibp: boolean, + onerep: boolean, +) => { + const baseUrl = process.env.SERVER_URL!; + const param1 = `${hibp ? "hibp=true" : ""}`; + const param2 = `${onerep ? "onerep=true" : ""}`; + let delim = ""; + if (param1 && param2) delim = "&"; + const params = param1 + delim + param2; + const completeUrl = baseUrl + "/api/mock/resetTestData?" + params; + const res = await page.request.get(completeUrl); + expect(res.ok()).toBeTruthy(); +}; From af8fbb9439e34707117ab10d77946304e4efba34 Mon Sep 17 00:00:00 2001 From: Mukhamediyar Kudaikulov Date: Fri, 26 Jul 2024 17:29:26 -0700 Subject: [PATCH 2/4] removed smoke mark for overview card tests --- src/e2e/specs/dashboard.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/e2e/specs/dashboard.spec.ts b/src/e2e/specs/dashboard.spec.ts index 5ac0a3e47fc..b1cfc097d79 100644 --- a/src/e2e/specs/dashboard.spec.ts +++ b/src/e2e/specs/dashboard.spec.ts @@ -456,7 +456,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Breaches Scan, }); }); -test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Overview Card @smoke`, () => { +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Overview Card`, () => { test.beforeEach(async ({ dashboardPage, page }) => { await dashboardPage.open(); From f692db7f728ced372d29f6cd633aa403b27bef7a Mon Sep 17 00:00:00 2001 From: Mukhamediyar Kudaikulov Date: Wed, 31 Jul 2024 09:50:35 -0700 Subject: [PATCH 3/4] skips all data breach tests if not using mock --- src/e2e/specs/dashboard.spec.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/e2e/specs/dashboard.spec.ts b/src/e2e/specs/dashboard.spec.ts index b1cfc097d79..4461a0219a8 100644 --- a/src/e2e/specs/dashboard.spec.ts +++ b/src/e2e/specs/dashboard.spec.ts @@ -742,8 +742,9 @@ test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Data Breaches` expect(pwdToUse).not.toBeUndefined(); await forceLoginAs(emailToUse, pwdToUse, page, landingPage, authPage); - if (isUsingMockHIBPEndpoint()) await resetTestData(page, true, false); - if (isUsingMockONEREPEndpoint()) await resetTestData(page, false, true); + if (!isUsingMockHIBPEndpoint() || !isUsingMockONEREPEndpoint()) return; + await resetTestData(page, true, true); + await dashboardPage.open(); test.info().annotations.push({ type: "testrail", From 61f79860e1e0e568584102760eef11da86af44a4 Mon Sep 17 00:00:00 2001 From: Mukhamediyar Kudaikulov Date: Wed, 31 Jul 2024 11:47:15 -0700 Subject: [PATCH 4/4] skipping tests that rely on mocks --- src/e2e/specs/dashboard.spec.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/e2e/specs/dashboard.spec.ts b/src/e2e/specs/dashboard.spec.ts index 4461a0219a8..db28297f81e 100644 --- a/src/e2e/specs/dashboard.spec.ts +++ b/src/e2e/specs/dashboard.spec.ts @@ -726,7 +726,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Navigation @sm }); // These tests rely heavily on mocks -test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Data Breaches`, () => { +test.skip(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Data Breaches`, () => { test.use({ storageState: { cookies: [], origins: [] } }); test("Verify that the High risk data breaches step is displayed correctly", async ({ @@ -736,13 +736,12 @@ test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Data Breaches` landingPage, authPage, }) => { + if (!isUsingMockHIBPEndpoint() || !isUsingMockONEREPEndpoint()) return; const emailToUse = process.env.E2E_TEST_ACCOUNT_EMAIL_EXPOSURES_STARTED!; const pwdToUse = process.env.E2E_TEST_ACCOUNT_PASSWORD!; expect(emailToUse).not.toBeUndefined(); expect(pwdToUse).not.toBeUndefined(); await forceLoginAs(emailToUse, pwdToUse, page, landingPage, authPage); - - if (!isUsingMockHIBPEndpoint() || !isUsingMockONEREPEndpoint()) return; await resetTestData(page, true, true); await dashboardPage.open();