import type { Page } from "@playwright/test"; /** * Drives the app's OAuth sign-in, mirroring the product-management template's * LoginPage. The erp app authenticates through @tailor-platform/app-shell's * hosted login (email + password), which yields a proper DPoP-bound session — * the reason e2e signs in for real rather than injecting a token. */ export class LoginPage { private page: Page; constructor(page: Page) { this.page = page; } async goto() { await this.page.goto("/"); } private async openAuthPage() { // AuthGuard shows a spinner while useAuth() resolves; the Sign in button // only appears once isReady=true and the user is unauthenticated. const signIn = this.page.getByRole("button", { name: "Sign in" }); await signIn.waitFor({ state: "visible" }); await signIn.click(); await this.page.getByLabel(/email/i).waitFor(); } private async submitCredentials(email: string, password: string) { await this.page.getByLabel(/email/i).waitFor(); await this.page.getByLabel(/email/i).fill(email); await this.page.getByPlaceholder("Password").fill(password); await this.page.getByPlaceholder("Password").press("Enter"); } async login(email: string, password: string) { await this.goto(); await this.openAuthPage(); await this.submitCredentials(email, password); // Auth redirects through `/?code=...` before landing on the app root; wait // for the final URL plus a stable sidebar landmark instead of networkidle. await this.page.waitForURL((url) => url.pathname === "/" && !url.searchParams.has("code"), { waitUntil: "domcontentloaded", }); await this.page.getByText("Procurement", { exact: true }).first().waitFor(); } }