import { expect, test } from '@playwright/test'; import { subjects } from '../../support/auth-config'; import { expireConfirmationLink, expireRecoveryLink } from '../../support/db'; import { GoTrueClient, randomEmail, randomPassword } from '../../support/gotrue'; import { expectMailCount, extractTokenHash, waitForMail } from '../../support/mailpit'; import { fillField, open, pressFirstButton, t, textOf } from '../../support/web'; const gotrue = new GoTrueClient(); async function requestReset(page: import('@playwright/test').Page, email: string) { await open(page, '/forgot-password'); await fillField(page.getByRole('textbox', { name: 'Email address' }), email); await page.getByRole('button', { name: 'Send link' }).click(); await expect(page).toHaveURL(/\/forgot-password\/check-email$/); } test.describe('KTO-01 Kriterium 8 (web): Passwort zuruecksetzen', () => { test('KTO-01 Kriterium 8: Reset anfordern, Link oeffnen, neues Passwort setzen, mit neuem Passwort anmelden', async ({ page }) => { const email = randomEmail(); const oldPassword = randomPassword(); const newPassword = randomPassword(); await gotrue.createConfirmedUser(email, oldPassword); await requestReset(page, email); const mail = await waitForMail(email); expect(mail.Subject).toBe(subjects.recovery.en); const { link, type } = extractTokenHash(mail); expect(type).toBe('recovery'); // Der Link fuehrt auf die Link-Seite; erst der Klick loest die Pruefung aus. await open(page, link.pathname + link.search); await pressFirstButton(page); await expect(page).toHaveURL(/\/reset-password$/); await fillField(page.getByRole('textbox', { name: 'New password' }), newPassword); await page.getByRole('button', { name: 'Save password' }).click(); await expect(textOf(page, t.passwordChanged)).toBeVisible(); expect((await gotrue.signIn(email, newPassword)).status).toBe(200); expect((await gotrue.signIn(email, oldPassword)).body.error_code).toBe('invalid_credentials'); }); test('KTO-01 Kriterium 8: bereits benutzter Reset-Link zeigt „abgelaufen oder schon benutzt“', async ({ page }) => { const email = randomEmail(); await gotrue.createConfirmedUser(email, randomPassword()); await gotrue.recover(email); const { link, tokenHash } = extractTokenHash(await waitForMail(email)); expect((await gotrue.verify(tokenHash, 'recovery')).status).toBe(200); // Link verbraucht await open(page, link.pathname + link.search); await pressFirstButton(page); await expect(textOf(page, t.linkInvalid)).toBeVisible(); }); test('KTO-01 Kriterium 8: AUTH-CFG-07 abgelaufener Reset-Link (recovery_sent_at 1 h + 1 s zurueck) zeigt den Fehlerzustand', async ({ page }) => { const email = randomEmail(); await gotrue.createConfirmedUser(email, randomPassword()); await gotrue.recover(email); const { link } = extractTokenHash(await waitForMail(email)); await expireRecoveryLink(email); await open(page, link.pathname + link.search); await pressFirstButton(page); await expect(textOf(page, t.linkInvalid)).toBeVisible(); await expect(page.getByRole('button', { name: 'Request a new link' })).toBeVisible(); }); test('KTO-01 Kriterium 8: AUTH-CFG-07 abgelaufener Bestaetigungslink zeigt den Fehlerzustand', async ({ page }) => { const email = randomEmail(); await gotrue.signUp(email, randomPassword()); const { link } = extractTokenHash(await waitForMail(email)); await expireConfirmationLink(email); await open(page, link.pathname + link.search); await pressFirstButton(page); await expect(textOf(page, t.linkInvalid)).toBeVisible(); }); test('KTO-01 Kriterium 8: Link ohne Parameter zeigt sofort den Fehlerzustand', async ({ page }) => { await open(page, '/auth/confirm'); await expect(textOf(page, t.linkInvalid)).toBeVisible(); }); test('KTO-01 Kriterium 4/8: Reset fuer unbekannte Adresse zeigt denselben Bildschirm, es geht keine Mail raus', async ({ page, browser }) => { const known = randomEmail(); await gotrue.createConfirmedUser(known, randomPassword()); await requestReset(page, known); await expect(textOf(page, /reset link if an account exists/)).toBeVisible(); const body = (await page.locator('body').ariaSnapshot()).trim(); const unknown = randomEmail('unknown'); const ctx = await browser.newContext({ locale: 'en-US', serviceWorkers: 'block', baseURL: 'http://localhost:3000' }); try { const other = await ctx.newPage(); await requestReset(other, unknown); expect((await other.locator('body').ariaSnapshot()).trim()).toBe(body); } finally { await ctx.close(); } await expectMailCount(unknown, 0); }); });