test(ui): stabilize auth and provider e2e flows (#9945)

This commit is contained in:
Alan Buscaglia
2026-02-05 09:56:49 +01:00
committed by GitHub
parent ab18ddb81a
commit 770269772a
8 changed files with 56 additions and 12 deletions

View File

@@ -188,5 +188,5 @@ export const getUserByMe = async (accessToken: string) => {
};
export async function logOut() {
await signOut();
await signOut({ redirectTo: "/sign-in" });
}

View File

@@ -74,11 +74,17 @@ test.describe("Session Error Messages", () => {
await scansPage.goto();
await expect(page.locator("main")).toBeVisible();
// Navigate to a safe public page before clearing cookies
// This prevents background requests from the protected page (scans)
// triggering a client-side redirect race condition when cookies are cleared
await signInPage.goto();
// Clear cookies to simulate session expiry
await context.clearCookies();
// Try to navigate to a different protected route
await providersPage.goto();
// Use fresh navigation to force middleware evaluation
await providersPage.gotoFresh();
// Should be redirected to login with callbackUrl
await signInPage.verifyRedirectWithCallback("/providers");

View File

@@ -1,6 +1,11 @@
import { expect, test } from "@playwright/test";
import { getSession, TEST_CREDENTIALS, verifySessionValid } from "../helpers";
import {
getSession,
getSessionWithoutCookies,
TEST_CREDENTIALS,
verifySessionValid,
} from "../helpers";
import { HomePage } from "../home/home-page";
import { SignInPage } from "../sign-in-base/sign-in-base-page";
@@ -71,7 +76,7 @@ test.describe("Token Refresh Flow", () => {
await context.clearCookies();
const expiredSession = await getSession(page);
const expiredSession = await getSessionWithoutCookies(page);
expect(expiredSession).toBeNull();
},
);

View File

@@ -143,9 +143,10 @@
### Flow Steps:
1. Log in with valid credentials.
2. Navigate to a protected route (/scans).
3. Clear cookies to simulate session expiry.
4. Navigate to another protected route (/providers).
5. Verify redirect to sign-in includes callbackUrl parameter.
3. Navigate to a safe public page (/sign-in).
4. Clear cookies to simulate session expiry.
5. Navigate to another protected route (/providers) using fresh navigation.
6. Verify redirect to sign-in includes callbackUrl parameter.
### Expected Result:
- URL contains callbackUrl=/providers parameter.

View File

@@ -1,4 +1,4 @@
import { Locator, Page, expect } from "@playwright/test";
import { Locator, Page, expect, request } from "@playwright/test";
import { AWSProviderCredential, AWSProviderData, AWS_CREDENTIAL_OPTIONS, ProvidersPage } from "./providers/providers-page";
import { ScansPage } from "./scans/scans-page";
@@ -47,6 +47,20 @@ export async function getSession(page: Page) {
return response.json();
}
export async function getSessionWithoutCookies(page: Page) {
const currentUrl = page.url();
const baseUrl = currentUrl.startsWith("http")
? new URL(currentUrl).origin
: process.env.NEXTAUTH_URL || "http://localhost:3000";
const apiContext = await request.newContext({ baseURL: baseUrl });
const response = await apiContext.get("/api/auth/session");
const session = await response.json();
await apiContext.dispose();
return session;
}
export async function verifySessionValid(page: Page) {
const session = await getSession(page);
expect(session).toBeTruthy();

View File

@@ -428,6 +428,12 @@ export class ProvidersPage extends BasePage {
await super.goto("/providers");
}
async gotoFresh(): Promise<void> {
// Go to the providers page with fresh navigation
await super.gotoFresh("/providers");
}
private async verifyPageHasProwlerTitle(): Promise<void> {
await expect(this.page).toHaveTitle(/Prowler/);
}

View File

@@ -110,8 +110,18 @@ export class ScansPage extends BasePage {
.filter({ hasText: accountId })
.first();
// Verify the row with the account ID is visible (provider exists)
await expect(rowWithAccountId).toBeVisible();
try {
// Verify the row with the account ID is visible (provider exists)
// Use a short timeout first to allow for a quick check
await expect(rowWithAccountId).toBeVisible({ timeout: 5000 });
} catch {
// If not visible immediately (likely due to async backend processing),
// reload the page to fetch the latest data
await this.page.reload();
await this.verifyPageLoaded();
// Wait longer after reload
await expect(rowWithAccountId).toBeVisible({ timeout: 15000 });
}
// Verify the row contains "scheduled scan" in the Scan name column
// The scan name "Daily scheduled scan" is displayed as "scheduled scan" in the table

View File

@@ -150,9 +150,11 @@ test.describe("Session Persistence", () => {
await signInPage.loginAndVerify(TEST_CREDENTIALS.VALID);
await homePage.signOut();
await signInPage.verifyLogoutSuccess();
await homePage.goto();
// Wait for signOut to redirect to /sign-in (NextAuth signOut flow)
await page.waitForURL(/\/sign-in/, { timeout: 15000 });
// Verify we're on the sign-in page with the form visible
await signInPage.verifyOnSignInPage();
},
);