From 0adf6051e9f04aa86d511f9caa52d1d0882f8671 Mon Sep 17 00:00:00 2001 From: Frederic Cabassut Date: Sun, 8 Mar 2026 21:35:34 +0100 Subject: [PATCH] test: update auth tests for multi-user Update e2e fixtures to use email+password for setup and login. Update auth tests to fill email field. Add multi-user test for admin creating a new user via API. Co-Authored-By: Claude Opus 4.6 --- tests/e2e/auth.spec.ts | 65 ++++++++++++++++++++++++++++------- tests/e2e/helpers/fixtures.ts | 12 +++++-- 2 files changed, 62 insertions(+), 15 deletions(-) diff --git a/tests/e2e/auth.spec.ts b/tests/e2e/auth.spec.ts index 7835242..edcb22d 100644 --- a/tests/e2e/auth.spec.ts +++ b/tests/e2e/auth.spec.ts @@ -15,7 +15,8 @@ test.describe.serial('Authentication', () => { // When the user visits the setup page await page.goto('/setup'); - // Then the password and confirmation fields and setup action are available + // Then the email, password, and confirmation fields and setup action are available + await expect(page.getByTestId('email-input')).toBeVisible(); await expect(page.getByTestId('password-input')).toBeVisible(); await expect(page.getByTestId('confirm-password-input')).toBeVisible(); await expect(page.getByTestId('setup-btn')).toBeVisible(); @@ -26,6 +27,7 @@ test.describe.serial('Authentication', () => { await page.goto('/setup'); // When they submit a password shorter than 8 characters + await page.getByTestId('email-input').fill('test@test.com'); await page.getByTestId('password-input').fill('short'); await page.getByTestId('confirm-password-input').fill('short'); await page.getByTestId('setup-btn').click(); @@ -39,6 +41,7 @@ test.describe.serial('Authentication', () => { await page.goto('/setup'); // When they submit two different passwords + await page.getByTestId('email-input').fill('test@test.com'); await page.getByTestId('password-input').fill('longpassword1'); await page.getByTestId('confirm-password-input').fill('longpassword2'); await page.getByTestId('setup-btn').click(); @@ -48,19 +51,15 @@ test.describe.serial('Authentication', () => { }); test('Scenario: User creates an account and gains access to the application', async ({ page }) => { - // Given the user accesses the application - await page.goto('/'); - const url = page.url(); + // Given the user accesses the setup page + await page.goto('/setup'); // When they authenticate with valid credentials - if (url.includes('/setup')) { - await page.getByTestId('password-input').fill('testpassword123'); - await page.getByTestId('confirm-password-input').fill('testpassword123'); - await page.getByTestId('setup-btn').click(); - } else if (url.includes('/login')) { - await page.getByTestId('password-input').fill('testpassword123'); - await page.getByTestId('login-btn').click(); - } + await page.getByTestId('email-input').fill('admin@test.com'); + await page.getByTestId('display-name-input').fill('Admin'); + await page.getByTestId('password-input').fill('testpassword123'); + await page.getByTestId('confirm-password-input').fill('testpassword123'); + await page.getByTestId('setup-btn').click(); // Then they have access to the main application await page.waitForURL('/'); @@ -71,12 +70,16 @@ test.describe.serial('Authentication', () => { // Given the user is authenticated await page.goto('/'); const url = page.url(); + if (url.includes('/setup')) { + await page.getByTestId('email-input').fill('admin@test.com'); + await page.getByTestId('display-name-input').fill('Admin'); await page.getByTestId('password-input').fill('testpassword123'); await page.getByTestId('confirm-password-input').fill('testpassword123'); await page.getByTestId('setup-btn').click(); await page.waitForURL('/'); } else if (url.includes('/login')) { + await page.getByTestId('email-input').fill('admin@test.com'); await page.getByTestId('password-input').fill('testpassword123'); await page.getByTestId('login-btn').click(); await page.waitForURL('/'); @@ -90,3 +93,41 @@ test.describe.serial('Authentication', () => { await expect(page).toHaveURL(/\/login/); }); }); + +test.describe('Multi-user', () => { + test('admin can create a new user via API', async ({ page }) => { + // Ensure setup/login + await page.goto('/'); + const url = page.url(); + + if (url.includes('/setup')) { + await page.getByTestId('email-input').fill('admin@test.com'); + await page.getByTestId('display-name-input').fill('Admin'); + await page.getByTestId('password-input').fill('testpassword123'); + await page.getByTestId('confirm-password-input').fill('testpassword123'); + await page.getByTestId('setup-btn').click(); + await page.waitForURL('/'); + } else if (url.includes('/login')) { + await page.getByTestId('email-input').fill('admin@test.com'); + await page.getByTestId('password-input').fill('testpassword123'); + await page.getByTestId('login-btn').click(); + await page.waitForURL('/'); + } + + // Create a new user via admin API + const response = await page.evaluate(() => + fetch('/api/admin/users', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + email: 'user2@test.com', + displayName: 'User Two', + password: 'userpassword123', + role: 'user' + }) + }).then((r) => ({ status: r.status, body: r.json() })) + ); + + expect(response.status).toBe(201); + }); +}); diff --git a/tests/e2e/helpers/fixtures.ts b/tests/e2e/helpers/fixtures.ts index c676b92..3d9113a 100644 --- a/tests/e2e/helpers/fixtures.ts +++ b/tests/e2e/helpers/fixtures.ts @@ -1,6 +1,8 @@ import { test as base, expect, type Page, type Locator } from '@playwright/test'; +const TEST_EMAIL = 'admin@test.com'; const TEST_PASSWORD = 'testpassword123'; +const TEST_DISPLAY_NAME = 'Test Admin'; /** Find a specific note card by its title text */ export function noteCard(page: Page, title: string): Locator { @@ -23,7 +25,9 @@ export async function setupAndLogin(page: Page) { const url = page.url(); if (url.includes('/setup')) { - // First-time setup - may race with other workers + // First-time setup with email + await page.getByTestId('email-input').fill(TEST_EMAIL); + await page.getByTestId('display-name-input').fill(TEST_DISPLAY_NAME); await page.getByTestId('password-input').fill(TEST_PASSWORD); await page.getByTestId('confirm-password-input').fill(TEST_PASSWORD); await page.getByTestId('setup-btn').click(); @@ -34,12 +38,14 @@ export async function setupAndLogin(page: Page) { } catch { // Setup was completed by another worker - go to login instead await page.goto('/login'); + await page.getByTestId('email-input').fill(TEST_EMAIL); await page.getByTestId('password-input').fill(TEST_PASSWORD); await page.getByTestId('login-btn').click(); await page.waitForURL('/'); } } else if (url.includes('/login')) { - // Login + // Login with email + await page.getByTestId('email-input').fill(TEST_EMAIL); await page.getByTestId('password-input').fill(TEST_PASSWORD); await page.getByTestId('login-btn').click(); await page.waitForURL('/'); @@ -51,4 +57,4 @@ export async function setupAndLogin(page: Page) { await page.waitForLoadState('networkidle'); } -export { expect }; +export { expect, TEST_EMAIL, TEST_PASSWORD };