Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add E2E tests for silent authentication #5150

Draft
wants to merge 20 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions src/db/tables/featureFlags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import createDbConnection from "../connect";
import { logger } from "../../app/functions/server/logging";
import { FeatureFlagRow } from "knex/types/tables";
import { headers } from "next/headers";

const knex = createDbConnection();

Expand Down Expand Up @@ -76,11 +77,26 @@ export async function getEnabledFeatureFlags(
return void subQuery;
});

const enabledFlagNames = await query;

return enabledFlagNames.map(
const enabledFlagNames = (await query).map(
(row: { name: string }) => row.name as FeatureFlagName,
);

// Force feature flags for E2E tests via URL query params
if (process.env.E2E_TEST_ENV === "local") {
const forcedFeatureFlags = headers().get("x-forced-feature-flags");
if (forcedFeatureFlags) {
const forcedFeatureFlagsFiltered = forcedFeatureFlags
.split(",")
.filter((forcedFeatureFlag) =>
featureFlagNames.includes(forcedFeatureFlag as FeatureFlagName),
);
return [
...new Set([...enabledFlagNames, ...forcedFeatureFlagsFiltered]),
] as FeatureFlagName[];
}
}

return enabledFlagNames;
}

/**
Expand Down
33 changes: 33 additions & 0 deletions src/e2e/pages/authPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,37 @@
expect(verificationCode).toBeDefined();
await this.enterVerificationCode(verificationCode as string);
}

async signInToFxA(email: string, password: string) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear to me (because I'm not terribly familiar with our existing e2e tests) why this extra method is needed - don't we already have methods to sign in?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is for logging explicitly in to the Monitor Accounts application and not Monitor.

await this.page.goto(process.env.FXA_SETTINGS_URL as string);

Check failure on line 76 in src/e2e/pages/authPage.ts

View workflow job for this annotation

GitHub Actions / e2e-tests-full

[chromium] › auth.spec.ts:72:3 › local - Authentication flow verification @smoke › Verify successful silent authentication with existing user

2) [chromium] › auth.spec.ts:72:3 › local - Authentication flow verification @smoke › Verify successful silent authentication with existing user Error: page.goto: Test timeout of 60000ms exceeded. Call log: - navigating to "https://accounts.stage.mozaws.net/settings", waiting until "load" at ../pages/authPage.ts:76 74 | 75 | async signInToFxA(email: string, password: string) { > 76 | await this.page.goto(process.env.FXA_SETTINGS_URL as string); | ^ 77 | await this.page.context().clearCookies(); 78 | await this.page 79 | .locator("//input[@type='password'] | //div/input[@type='email']") at AuthPage.signInToFxA (/home/runner/work/blurts-server/blurts-server/src/e2e/pages/authPage.ts:76:21) at /home/runner/work/blurts-server/blurts-server/src/e2e/specs/auth.spec.ts:82:20
await this.page.context().clearCookies();
await this.page
.locator("//input[@type='password'] | //div/input[@type='email']")
.waitFor({ state: "visible" });

Check failure on line 80 in src/e2e/pages/authPage.ts

View workflow job for this annotation

GitHub Actions / e2e-tests-full

[firefox] › auth.spec.ts:72:3 › local - Authentication flow verification @smoke › Verify successful silent authentication with existing user

3) [firefox] › auth.spec.ts:72:3 › local - Authentication flow verification @smoke › Verify successful silent authentication with existing user Error: locator.waitFor: Test timeout of 60000ms exceeded. Call log: - waiting for locator('//input[@type=\'password\'] | //div/input[@type=\'email\']') to be visible at ../pages/authPage.ts:80 78 | await this.page 79 | .locator("//input[@type='password'] | //div/input[@type='email']") > 80 | .waitFor({ state: "visible" }); | ^ 81 | const visible = await this.useDifferentEmailButton.isVisible(); 82 | if (visible) { 83 | await this.useDifferentEmailButton.click(); at AuthPage.signInToFxA (/home/runner/work/blurts-server/blurts-server/src/e2e/pages/authPage.ts:80:8) at /home/runner/work/blurts-server/blurts-server/src/e2e/specs/auth.spec.ts:82:5

Check failure on line 80 in src/e2e/pages/authPage.ts

View workflow job for this annotation

GitHub Actions / e2e-tests-smoke

[firefox] › auth.spec.ts:72:3 › local - Authentication flow verification @smoke › Verify successful silent authentication with existing user

3) [firefox] › auth.spec.ts:72:3 › local - Authentication flow verification @smoke › Verify successful silent authentication with existing user Error: locator.waitFor: Test timeout of 60000ms exceeded. Call log: - waiting for locator('//input[@type=\'password\'] | //div/input[@type=\'email\']') to be visible at ../pages/authPage.ts:80 78 | await this.page 79 | .locator("//input[@type='password'] | //div/input[@type='email']") > 80 | .waitFor({ state: "visible" }); | ^ 81 | const visible = await this.useDifferentEmailButton.isVisible(); 82 | if (visible) { 83 | await this.useDifferentEmailButton.click(); at AuthPage.signInToFxA (/home/runner/work/blurts-server/blurts-server/src/e2e/pages/authPage.ts:80:8) at /home/runner/work/blurts-server/blurts-server/src/e2e/specs/auth.spec.ts:82:5
const visible = await this.useDifferentEmailButton.isVisible();
if (visible) {
await this.useDifferentEmailButton.click();
await this.page.waitForURL(/^(?!.*signin).*/);
}

// enter email
await this.emailInputField.fill(email);
await this.continueButton.click();
await this.page.waitForURL(/^(?!.*signin).*/);

// enter password
await this.passwordInputField.fill(password);
await this.continue({ waitForURL: process.env.FXA_SETTINGS_URL });
}

async initSilentAuth() {
await this.page.setExtraHTTPHeaders({
"x-forced-feature-flags": "PromptNoneAuthFlow",
});
await this.page.goto(
`${process.env.E2E_TEST_BASE_URL as string}/?utm_source=moz-account&utm_campaign=settings-promo&utm_content=monitor-free`,
);
// FxA can take a while to load on stage:
await this.page.waitForURL("**/authorization?**");
}
}
60 changes: 59 additions & 1 deletion src/e2e/specs/auth.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* This Source Code Form is subject to the terms of the Mozilla Public

Check failure on line 1 in src/e2e/specs/auth.spec.ts

View workflow job for this annotation

GitHub Actions / e2e-tests-full

[chromium] › auth.spec.ts:72:3 › local - Authentication flow verification @smoke › Verify successful silent authentication with existing user

2) [chromium] › auth.spec.ts:72:3 › local - Authentication flow verification @smoke › Verify successful silent authentication with existing user Test timeout of 60000ms exceeded.

Check failure on line 1 in src/e2e/specs/auth.spec.ts

View workflow job for this annotation

GitHub Actions / e2e-tests-full

[firefox] › auth.spec.ts:72:3 › local - Authentication flow verification @smoke › Verify successful silent authentication with existing user

3) [firefox] › auth.spec.ts:72:3 › local - Authentication flow verification @smoke › Verify successful silent authentication with existing user Test timeout of 60000ms exceeded.

Check failure on line 1 in src/e2e/specs/auth.spec.ts

View workflow job for this annotation

GitHub Actions / e2e-tests-smoke

[chromium] › auth.spec.ts:72:3 › local - Authentication flow verification @smoke › Verify successful silent authentication with existing user

2) [chromium] › auth.spec.ts:72:3 › local - Authentication flow verification @smoke › Verify successful silent authentication with existing user Test timeout of 60000ms exceeded.

Check failure on line 1 in src/e2e/specs/auth.spec.ts

View workflow job for this annotation

GitHub Actions / e2e-tests-smoke

[firefox] › auth.spec.ts:72:3 › local - Authentication flow verification @smoke › Verify successful silent authentication with existing user

3) [firefox] › auth.spec.ts:72:3 › local - Authentication flow verification @smoke › Verify successful silent authentication with existing user Test timeout of 60000ms exceeded.
* 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/. */

Expand Down Expand Up @@ -45,7 +45,7 @@
landingPage,
dashboardPage,
}, 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();
});
Expand All @@ -57,7 +57,7 @@
await authPage.signIn(process.env.E2E_TEST_ACCOUNT_EMAIL as string);

// assert successful login
await expect(dashboardPage.fixedTab).toBeVisible();

Check failure on line 60 in src/e2e/specs/auth.spec.ts

View workflow job for this annotation

GitHub Actions / e2e-tests-full

[chromium] › auth.spec.ts:42:3 › local - Authentication flow verification @smoke › Verify sign in with existing user

1) [chromium] › auth.spec.ts:42:3 › local - Authentication flow verification @smoke › Verify sign in with existing user Error: Timed out 2000ms waiting for expect(locator).toBeVisible() Locator: getByRole('tab', { name: 'Fixed' }) Expected: visible Received: <element(s) not found> Call log: - expect.toBeVisible with timeout 2000ms - waiting for getByRole('tab', { name: 'Fixed' }) 58 | 59 | // assert successful login > 60 | await expect(dashboardPage.fixedTab).toBeVisible(); | ^ 61 | await expect(dashboardPage.actionNeededTab).toBeVisible(); 62 | 63 | await testInfo.attach( at /home/runner/work/blurts-server/blurts-server/src/e2e/specs/auth.spec.ts:60:42

Check failure on line 60 in src/e2e/specs/auth.spec.ts

View workflow job for this annotation

GitHub Actions / e2e-tests-full

[chromium] › auth.spec.ts:42:3 › local - Authentication flow verification @smoke › Verify sign in with existing user

1) [chromium] › auth.spec.ts:42:3 › local - Authentication flow verification @smoke › Verify sign in with existing user Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── Error: Timed out 2000ms waiting for expect(locator).toBeVisible() Locator: getByRole('tab', { name: 'Fixed' }) Expected: visible Received: <element(s) not found> Call log: - expect.toBeVisible with timeout 2000ms - waiting for getByRole('tab', { name: 'Fixed' }) 58 | 59 | // assert successful login > 60 | await expect(dashboardPage.fixedTab).toBeVisible(); | ^ 61 | await expect(dashboardPage.actionNeededTab).toBeVisible(); 62 | 63 | await testInfo.attach( at /home/runner/work/blurts-server/blurts-server/src/e2e/specs/auth.spec.ts:60:42

Check failure on line 60 in src/e2e/specs/auth.spec.ts

View workflow job for this annotation

GitHub Actions / e2e-tests-smoke

[chromium] › auth.spec.ts:42:3 › local - Authentication flow verification @smoke › Verify sign in with existing user

1) [chromium] › auth.spec.ts:42:3 › local - Authentication flow verification @smoke › Verify sign in with existing user Error: Timed out 2000ms waiting for expect(locator).toBeVisible() Locator: getByRole('tab', { name: 'Fixed' }) Expected: visible Received: <element(s) not found> Call log: - expect.toBeVisible with timeout 2000ms - waiting for getByRole('tab', { name: 'Fixed' }) 58 | 59 | // assert successful login > 60 | await expect(dashboardPage.fixedTab).toBeVisible(); | ^ 61 | await expect(dashboardPage.actionNeededTab).toBeVisible(); 62 | 63 | await testInfo.attach( at /home/runner/work/blurts-server/blurts-server/src/e2e/specs/auth.spec.ts:60:42

Check failure on line 60 in src/e2e/specs/auth.spec.ts

View workflow job for this annotation

GitHub Actions / e2e-tests-smoke

[chromium] › auth.spec.ts:42:3 › local - Authentication flow verification @smoke › Verify sign in with existing user

1) [chromium] › auth.spec.ts:42:3 › local - Authentication flow verification @smoke › Verify sign in with existing user Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── Error: Timed out 2000ms waiting for expect(locator).toBeVisible() Locator: getByRole('tab', { name: 'Fixed' }) Expected: visible Received: <element(s) not found> Call log: - expect.toBeVisible with timeout 2000ms - waiting for getByRole('tab', { name: 'Fixed' }) 58 | 59 | // assert successful login > 60 | await expect(dashboardPage.fixedTab).toBeVisible(); | ^ 61 | await expect(dashboardPage.actionNeededTab).toBeVisible(); 62 | 63 | await testInfo.attach( at /home/runner/work/blurts-server/blurts-server/src/e2e/specs/auth.spec.ts:60:42
await expect(dashboardPage.actionNeededTab).toBeVisible();

await testInfo.attach(
Expand All @@ -68,4 +68,62 @@
},
);
});

test("Verify successful silent authentication with existing user", async ({
page,
authPage,
}, testInfo) => {
// speed up test by ignoring non-necessary requests
await page.route(/(analytics)/, async (route) => {
await route.abort();
});

// login to FxA
await authPage.signInToFxA(
process.env.E2E_TEST_ACCOUNT_EMAIL as string,
process.env.E2E_TEST_ACCOUNT_PASSWORD as string,
);

// start authentication flow
await authPage.initSilentAuth();

// assert successful login
await page.waitForURL("**/user/dashboard/**");

Check failure on line 91 in src/e2e/specs/auth.spec.ts

View workflow job for this annotation

GitHub Actions / e2e-tests-smoke

[chromium] › auth.spec.ts:72:3 › local - Authentication flow verification @smoke › Verify successful silent authentication with existing user

2) [chromium] › auth.spec.ts:72:3 › local - Authentication flow verification @smoke › Verify successful silent authentication with existing user Error: page.waitForURL: Test timeout of 60000ms exceeded. =========================== logs =========================== waiting for navigation to "**/user/dashboard/**" until "load" navigated to "https://accounts.stage.mozaws.net/authorization?client_id=edd29a80019d61a1&scope=profile+https%3A%2F%2Fidentity.mozilla.com%2Faccount%2Fsubscriptions&response_type=code&redirect_uri=***%2Fapi%2Fauth%2Fcallback%2Ffxa&access_type=offline&action=email&prompt=none&max_age=0&state=GBiJuHa2xkeHZMx6twf96MZZK-1EBdDPwwSd_HCl2ik" navigated to "***/user/welcome" navigated to "***/user/welcome" ============================================================ 89 | 90 | // assert successful login > 91 | await page.waitForURL("**/user/dashboard/**"); | ^ 92 | 93 | await testInfo.attach( 94 | `${process.env.E2E_TEST_ENV}-silent-authentication-monitor-dashboard.png`, at /home/runner/work/blurts-server/blurts-server/src/e2e/specs/auth.spec.ts:91:16

await testInfo.attach(
`${process.env.E2E_TEST_ENV}-silent-authentication-monitor-dashboard.png`,
{
body: await page.screenshot(),
contentType: "image/png",
},
);
});

test("Verify failed silent authentication with existing user", async ({
page,
authPage,
landingPage,
}, testInfo) => {
// speed up test by ignoring non-necessary requests
await page.route(/(analytics)/, async (route) => {
await route.abort();
});

// start authentication flow
await authPage.initSilentAuth();

// assert failed login
await expect(landingPage.monitorLandingHeader).toBeVisible({
// The header can take a while to show in Playwright.
timeout: 5000,
});

await testInfo.attach(
`${process.env.E2E_TEST_ENV}-silent-authentication-monitor-dashboard.png`,
{
body: await page.screenshot(),
contentType: "image/png",
},
);
});
});
1 change: 1 addition & 0 deletions src/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export function middleware(request: NextRequest) {

const requestHeaders = new Headers(request.headers);
requestHeaders.set("x-nonce", nonce);

// Add the CSP to the request headers - that will make Next.js detect it and
// add it to the inline `<script>` tags that it injects itself, as per
// https://github.com/vercel/next.js/discussions/51039#discussioncomment-6596642
Expand Down
Loading