79 lines
3.8 KiB
TypeScript
79 lines
3.8 KiB
TypeScript
import { expect, test } from "./utils/test";
|
|
import { expectNoCriticalA11yViolations } from "./utils/axe";
|
|
import { getTenantCredentials, loginAsTenantUser, tenantSettingsAccountPath } from "./utils/auth";
|
|
import { expectNoHorizontalOverflow } from "./utils/mobile";
|
|
import { skipOrFailWhenE2eInputsMissing } from "./utils/readiness";
|
|
|
|
const credentials = getTenantCredentials();
|
|
const dashboardPath = process.env.E2E_TENANT_DASHBOARD_PATH ?? "/app/dashboard";
|
|
|
|
test.describe("auth golden path", () => {
|
|
test("registration surface remains reachable or redirects cleanly to login", async ({ page }) => {
|
|
await page.goto("/register", { waitUntil: "domcontentloaded" });
|
|
|
|
if (/\/login(?:[?#].*)?$/u.test(page.url())) {
|
|
await expect(page.locator('input[type="email"], input[name="email"], input#email').first()).toBeVisible();
|
|
await expectNoHorizontalOverflow(page);
|
|
await expectNoCriticalA11yViolations(page);
|
|
return;
|
|
}
|
|
|
|
await expect(page.locator("body")).toBeVisible();
|
|
await expectNoHorizontalOverflow(page);
|
|
|
|
const passwordInput = page.locator('input[type="password"], input[name="password"], input#password').first();
|
|
if ((await passwordInput.count()) > 0 && (await passwordInput.isVisible())) {
|
|
const requirements = page.locator('[aria-live="polite"]').first();
|
|
await expect(requirements).toBeVisible();
|
|
}
|
|
|
|
await expectNoCriticalA11yViolations(page);
|
|
});
|
|
|
|
test("authenticated tenant can move from account settings back to dashboard", async ({ page }) => {
|
|
if (!credentials) {
|
|
skipOrFailWhenE2eInputsMissing(["E2E_TENANT_EMAIL", "E2E_TENANT_PASSWORD"], "Skipping authenticated auth golden path");
|
|
}
|
|
|
|
await loginAsTenantUser(page, credentials!);
|
|
|
|
const accountPath = tenantSettingsAccountPath(dashboardPath);
|
|
await page.goto(accountPath, { waitUntil: "domcontentloaded" });
|
|
await expect(page).toHaveURL(new RegExp(`${escapeRegExp(accountPath)}(?:[?#].*)?$`, "u"));
|
|
await expect(page.locator('[data-ui-id="ui.surface.app.sidebar"]')).toBeVisible();
|
|
await expectNoHorizontalOverflow(page);
|
|
|
|
await page.goto(dashboardPath, { waitUntil: "domcontentloaded" });
|
|
await expect(page).toHaveURL(new RegExp(`${escapeRegExp(dashboardPath)}(?:[?#].*)?$`, "u"));
|
|
await expect(page.locator('[data-ui-id="ui.nav.app.dashboard"]').first()).toBeVisible();
|
|
await expectNoHorizontalOverflow(page);
|
|
});
|
|
|
|
test("login continues to the protected redirect target", async ({ page }) => {
|
|
if (!credentials) {
|
|
skipOrFailWhenE2eInputsMissing(["E2E_TENANT_EMAIL", "E2E_TENANT_PASSWORD"], "Skipping login redirect flow");
|
|
}
|
|
|
|
const protectedPath = process.env.E2E_TENANT_PROTECTED_DEEP_LINK ?? tenantSettingsAccountPath(dashboardPath);
|
|
const response = await page.goto(protectedPath, { waitUntil: "domcontentloaded" });
|
|
expect(response?.status() ?? 200).toBeLessThan(500);
|
|
|
|
const loginUrl = new URL(page.url());
|
|
expect(loginUrl.pathname).toBe("/login");
|
|
expect(loginUrl.searchParams.get("redirectTo")).toBe(protectedPath);
|
|
|
|
await page.locator('[data-ui-id="ui.auth.login.email"], input[type="email"], input[name="email"], input#email').first().fill(credentials!.email);
|
|
await page.locator('[data-ui-id="ui.auth.login.password"], input[type="password"], input[name="password"], input#password').first().fill(credentials!.password);
|
|
await Promise.all([page.waitForLoadState("domcontentloaded"), page.locator('button[type="submit"]').first().click()]);
|
|
|
|
await expect(page).toHaveURL(new RegExp(`${escapeRegExp(protectedPath)}(?:[?#].*)?$`, "u"));
|
|
await expect(page).not.toHaveURL(/\/login(?:[?#].*)?$/u);
|
|
await expect(page.locator('[data-ui-id="ui.surface.shell.main"]').first()).toBeVisible();
|
|
await expectNoHorizontalOverflow(page);
|
|
});
|
|
});
|
|
|
|
function escapeRegExp(value: string): string {
|
|
return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
}
|