import { Locator, Page, expect } from '@playwright/test'; /** * The two halves of password recovery: asking for a link, and using one. * * They are one object because they are one flow and a test usually crosses * between them. Requesting is a modal reached from the login form; setting the * new password is a route the customer arrives at from their email, with no * page behind it to return to. */ export class PasswordResetPages { readonly requestDialog: Locator; readonly email: Locator; readonly sendResetLinkButton: Locator; readonly signInButton: Locator; readonly newPassword: Locator; readonly confirmNewPassword: Locator; readonly setNewPasswordButton: Locator; constructor(private readonly page: Page) { this.requestDialog = page.getByRole('dialog', { name: 'Reset your password' }); this.email = page.getByRole('textbox', { name: 'Email' }); this.sendResetLinkButton = page.getByRole('button', { name: 'Send reset link' }); this.signInButton = this.requestDialog.getByRole('button', { name: 'Sign in' }); this.newPassword = page.getByLabel('New password', { exact: true }); this.confirmNewPassword = page.getByLabel('Confirm new password'); this.setNewPasswordButton = page.getByRole('button', { name: 'Set new password' }); } async gotoRequest(): Promise { await this.page.goto('/forgot-password'); } /** * Opens the reset form, with or without a token. * * Omitting it is a real case rather than a degenerate one: a link that lost * its token has to explain itself instead of failing on submit. */ async gotoReset(token?: string): Promise { await this.page.goto(token ? `/reset-password?token=${token}` : '/reset-password'); } async setNewPassword(password: string, confirmation = password): Promise { await this.newPassword.fill(password); await this.confirmNewPassword.fill(confirmation); await this.setNewPasswordButton.click(); } async requestLinkFor(email: string): Promise { await this.email.fill(email); await this.sendResetLinkButton.click(); await expect(this.page.getByText('Check your email')).toBeVisible(); } }