test(e2e): add profile page journey (view, update, password change)
Includes self-healing password change test that restores admin123 at the end so the shared session remains valid for subsequent specs. Refs #48 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
108
frontend/e2e/profile.spec.ts
Normal file
108
frontend/e2e/profile.spec.ts
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Profile page E2E tests.
|
||||||
|
*
|
||||||
|
* Reads top-to-bottom as a single user journey:
|
||||||
|
* the logged-in admin opens their profile, updates their display name,
|
||||||
|
* tries a wrong password (sees an error), then successfully changes their
|
||||||
|
* password and logs back in with the new one.
|
||||||
|
*
|
||||||
|
* The password change test restores the original password at the end so the
|
||||||
|
* shared session remains valid for all subsequent test files.
|
||||||
|
*/
|
||||||
|
|
||||||
|
test.describe('Profile page', () => {
|
||||||
|
test('user opens their profile and sees the personal data and password sections', async ({
|
||||||
|
page
|
||||||
|
}) => {
|
||||||
|
await page.goto('/profile');
|
||||||
|
await expect(page.getByRole('heading', { name: /Mein Profil/i })).toBeVisible();
|
||||||
|
await expect(page.getByText('Persönliche Daten')).toBeVisible();
|
||||||
|
await expect(page.getByText('Passwort ändern')).toBeVisible();
|
||||||
|
await page.screenshot({ path: 'test-results/e2e/profile-view.png' });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('user saves updated first and last name and sees confirmation', async ({ page }) => {
|
||||||
|
await page.goto('/profile');
|
||||||
|
await page.waitForSelector('[data-hydrated]');
|
||||||
|
|
||||||
|
await page.locator('input[name="firstName"]').fill('E2E');
|
||||||
|
await page.locator('input[name="lastName"]').fill('Admin');
|
||||||
|
|
||||||
|
// Two "Speichern" buttons exist — the first belongs to the profile form
|
||||||
|
await page
|
||||||
|
.locator('form[action*="updateProfile"]')
|
||||||
|
.getByRole('button', { name: /Speichern/i })
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await expect(page.getByText('Gespeichert.')).toBeVisible();
|
||||||
|
// Nav avatar shows the new initials derived from firstName + lastName
|
||||||
|
await expect(page.locator('button[aria-haspopup="true"]')).toContainText('EA');
|
||||||
|
await page.screenshot({ path: 'test-results/e2e/profile-save.png' });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('shows an error when the current password is wrong', async ({ page }) => {
|
||||||
|
await page.goto('/profile');
|
||||||
|
await page.waitForSelector('[data-hydrated]');
|
||||||
|
|
||||||
|
await page.locator('input[name="currentPassword"]').fill('definitely-wrong');
|
||||||
|
await page.locator('input[name="newPassword"]').fill('NewPass123!');
|
||||||
|
await page.locator('input[name="confirmPassword"]').fill('NewPass123!');
|
||||||
|
|
||||||
|
await page
|
||||||
|
.locator('form[action*="changePassword"]')
|
||||||
|
.getByRole('button', { name: /Speichern/i })
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await expect(page.getByText('Das aktuelle Passwort ist falsch.')).toBeVisible();
|
||||||
|
await page.screenshot({ path: 'test-results/e2e/profile-wrong-password.png' });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('user changes their password and can log in with the new one', async ({ page }) => {
|
||||||
|
await page.goto('/profile');
|
||||||
|
await page.waitForSelector('[data-hydrated]');
|
||||||
|
|
||||||
|
// ── Step 1: change to a temporary password ─────────────────────────────
|
||||||
|
await page.locator('input[name="currentPassword"]').fill('admin123');
|
||||||
|
await page.locator('input[name="newPassword"]').fill('TempAdmin456!');
|
||||||
|
await page.locator('input[name="confirmPassword"]').fill('TempAdmin456!');
|
||||||
|
await page
|
||||||
|
.locator('form[action*="changePassword"]')
|
||||||
|
.getByRole('button', { name: /Speichern/i })
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await expect(page.getByText('Passwort erfolgreich geändert.')).toBeVisible();
|
||||||
|
|
||||||
|
// ── Step 2: navigate away — server session is invalidated ───────────────
|
||||||
|
await page.goto('/');
|
||||||
|
await expect(page).toHaveURL(/\/login/);
|
||||||
|
|
||||||
|
// ── Step 3: log in with the new password ───────────────────────────────
|
||||||
|
await page.getByLabel('Benutzername').fill('admin');
|
||||||
|
await page.getByLabel('Passwort').fill('TempAdmin456!');
|
||||||
|
await page.getByRole('button', { name: 'Anmelden' }).click();
|
||||||
|
await expect(page).toHaveURL('/');
|
||||||
|
await page.screenshot({ path: 'test-results/e2e/profile-password-changed.png' });
|
||||||
|
|
||||||
|
// ── Step 4: restore the original password so subsequent tests still work ─
|
||||||
|
await page.goto('/profile');
|
||||||
|
await page.waitForSelector('[data-hydrated]');
|
||||||
|
await page.locator('input[name="currentPassword"]').fill('TempAdmin456!');
|
||||||
|
await page.locator('input[name="newPassword"]').fill('admin123');
|
||||||
|
await page.locator('input[name="confirmPassword"]').fill('admin123');
|
||||||
|
await page
|
||||||
|
.locator('form[action*="changePassword"]')
|
||||||
|
.getByRole('button', { name: /Speichern/i })
|
||||||
|
.click();
|
||||||
|
await expect(page.getByText('Passwort erfolgreich geändert.')).toBeVisible();
|
||||||
|
|
||||||
|
// ── Step 5: log back in with the restored password ─────────────────────
|
||||||
|
await page.goto('/');
|
||||||
|
await expect(page).toHaveURL(/\/login/);
|
||||||
|
await page.getByLabel('Benutzername').fill('admin');
|
||||||
|
await page.getByLabel('Passwort').fill('admin123');
|
||||||
|
await page.getByRole('button', { name: 'Anmelden' }).click();
|
||||||
|
await expect(page).toHaveURL('/');
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user