import { expect, Locator, Page } from '@playwright/test'; import { Account } from '../fixtures/accounts'; /** The sign-in screen: agency picker, credentials, demo shortcuts. */ export class LoginPage { readonly tenantSelect: Locator; readonly email: Locator; readonly password: Locator; readonly submit: Locator; readonly error: Locator; readonly demoChips: Locator; constructor(private readonly page: Page) { this.tenantSelect = page.locator('#tenant'); this.email = page.locator('#email'); this.password = page.locator('#password'); // Matched by role rather than label: the button relabels itself to // "Signing in…" while a request is in flight, and tests assert on that. this.submit = page.locator('form button[type="submit"]'); this.error = page.locator('.alert-error'); this.demoChips = page.locator('.demo-chip'); } async goto(): Promise { await this.page.goto('/login'); await expect(this.submit).toBeVisible(); } /** Fills the form from the demo shortcut for the given account. */ async useDemoChip(account: Account): Promise { await this.demoChips.filter({ hasText: account.email }).first().click(); } async fill(account: Account, password = account.password): Promise { await this.tenantSelect.selectOption(account.tenant); await this.email.fill(account.email); await this.password.fill(password); } /** Signs in and waits for the console to appear. */ async signIn(account: Account): Promise { await this.goto(); await this.useDemoChip(account); await this.submit.click(); await this.page.waitForURL('**/dashboard'); } /** Attempts a sign-in that is expected to fail, and returns the message. */ async signInExpectingFailure(account: Account, password: string): Promise { await this.fill(account, password); await this.submit.click(); await expect(this.error).toBeVisible(); return (await this.error.innerText()).trim(); } }