import { test, expect } from '@playwright/test'; import * as auth from '../fixtures/auth'; import * as assertions from '../utils/assertions'; import { LDAP_USERS, LOCAL_USERS } from '../fixtures/test-data'; test.describe('Login Workflow', () => { const BASE_URL = process.env.BASE_URL || 'http://localhost:3000'; test.beforeEach(async ({ page }) => { // Navigate to login page await page.goto(BASE_URL); // Wait for identity check overlay await page.waitForSelector('[data-testid="identity-check-overlay"]', { timeout: 10000 }); }); test('should display identity check overlay on app load', async ({ page }) => { const overlay = page.locator('[data-testid="identity-check-overlay"]'); await expect(overlay).toBeVisible(); // Verify tabs are available const ldapTab = page.locator('[data-testid="ldap-login-tab"]'); const localTab = page.locator('[data-testid="local-login-tab"]'); await expect(ldapTab).toBeVisible(); await expect(localTab).toBeVisible(); }); test('should display login form with username and password fields', async ({ page }) => { await assertions.assertLoginFormVisible(page); }); test('should reject empty login credentials', async ({ page }) => { const submitButton = page.locator('[data-testid="login-submit"]'); await submitButton.click(); // Should show validation error const errorMessage = page.locator('[data-testid="toast-error"]'); await expect(errorMessage).toBeVisible({ timeout: 3000 }); }); test('should reject invalid LDAP credentials', async ({ page }) => { await auth.loginWithLdap(page, LDAP_USERS.invalid, BASE_URL); // Should show error message const errorToast = page.locator('[data-testid="toast-error"]'); await expect(errorToast).toBeVisible({ timeout: 5000 }); // Should still be on login page await expect(page).toHaveURL(BASE_URL); }); test('should successfully login with valid LDAP credentials', async ({ page }) => { // Skip if LDAP is not configured in test environment test.skip(process.env.SKIP_LDAP === 'true', 'LDAP not available in test environment'); await auth.loginWithLdap(page, LDAP_USERS.valid, BASE_URL); // Verify we're authenticated await assertions.assertUserAuthenticated(page, BASE_URL); // Verify token is stored const token = await auth.getAuthToken(page); expect(token).toBeTruthy(); }); test('should reject invalid local user credentials', async ({ page }) => { // Switch to local user tab const localTab = page.locator('[data-testid="local-login-tab"]'); await localTab.click(); // Try to login with invalid credentials await page.fill('[data-testid="local-username-input"]', 'invalid_user'); await page.fill('[data-testid="local-password-input"]', 'wrong_password'); await page.click('[data-testid="local-login-submit"]'); // Should show error const errorToast = page.locator('[data-testid="toast-error"]'); await expect(errorToast).toBeVisible({ timeout: 5000 }); }); test('should successfully login with valid local user credentials', async ({ page }) => { // Switch to local user tab const localTab = page.locator('[data-testid="local-login-tab"]'); await localTab.click(); // Login with valid credentials await auth.loginWithLocalUser(page, LOCAL_USERS.admin, BASE_URL); // Verify authenticated await assertions.assertUserAuthenticated(page, BASE_URL); }); test('should show user identity after successful login', async ({ page }) => { await auth.loginWithLocalUser(page, LOCAL_USERS.admin, BASE_URL); // Check that user info is displayed const userDisplay = page.locator('[data-testid="user-display"]'); await expect(userDisplay).toBeVisible(); // Verify username is shown const username = await userDisplay.textContent(); expect(username).toContain(LOCAL_USERS.admin.username); }); test('should maintain session across page reloads', async ({ page }) => { await auth.loginWithLocalUser(page, LOCAL_USERS.admin, BASE_URL); await assertions.assertUserAuthenticated(page, BASE_URL); // Reload page await page.reload(); // Should still be authenticated const token = await auth.getAuthToken(page); expect(token).toBeTruthy(); // Should not be on login page await expect(page).not.toHaveURL(BASE_URL); }); test('should support logout functionality', async ({ page }) => { // Login first await auth.loginWithLocalUser(page, LOCAL_USERS.admin, BASE_URL); await assertions.assertUserAuthenticated(page, BASE_URL); // Logout await auth.logout(page, BASE_URL); // Should be back on login page const identityOverlay = page.locator('[data-testid="identity-check-overlay"]'); await expect(identityOverlay).toBeVisible({ timeout: 5000 }); // Token should be cleared const token = await auth.getAuthToken(page); expect(token).toBeFalsy(); }); test('should show admin button for admin users', async ({ page }) => { await auth.loginWithLocalUser(page, LOCAL_USERS.admin, BASE_URL); await assertions.assertUserAuthenticated(page, BASE_URL); // Admin button should be visible const adminButton = page.locator('[data-testid="admin-button"]'); await expect(adminButton).toBeVisible(); }); test('should allow switching between LDAP and local login tabs', async ({ page }) => { const ldapTab = page.locator('[data-testid="ldap-login-tab"]'); const localTab = page.locator('[data-testid="local-login-tab"]'); // Start on LDAP tab let ldapForm = page.locator('[data-testid="ldap-login-form"]'); await expect(ldapForm).toBeVisible(); // Switch to local await localTab.click(); ldapForm = page.locator('[data-testid="ldap-login-form"]'); await expect(ldapForm).not.toBeVisible(); // Switch back to LDAP await ldapTab.click(); ldapForm = page.locator('[data-testid="ldap-login-form"]'); await expect(ldapForm).toBeVisible(); }); test('should remember login preference on revisit', async ({ page, context }) => { // Login with local user await auth.loginWithLocalUser(page, LOCAL_USERS.admin, BASE_URL); // Close and reopen browser await page.close(); const newPage = await context.newPage(); await newPage.goto(BASE_URL); // Should still be authenticated const authenticated = await auth.isAuthenticated(newPage); expect(authenticated).toBe(true); await newPage.close(); }); test('should handle network errors gracefully', async ({ page }) => { // Enable offline mode await page.context().setOffline(true); // Try to login const usernameInput = page.locator('[data-testid="username-input"]'); const passwordInput = page.locator('[data-testid="password-input"]'); const submitButton = page.locator('[data-testid="login-submit"]'); await usernameInput.fill(LOCAL_USERS.admin.username); await passwordInput.fill(LOCAL_USERS.admin.password); await submitButton.click(); // Should show network error const errorToast = page.locator('[data-testid="toast-error"]'); await expect(errorToast).toBeVisible({ timeout: 5000 }); // Re-enable network await page.context().setOffline(false); }); test('should display user list in local login tab', async ({ page }) => { const localTab = page.locator('[data-testid="local-login-tab"]'); await localTab.click(); // User list should be visible const userList = page.locator('[data-testid="user-list"]'); await expect(userList).toBeVisible(); // Should have at least one user const userItems = page.locator('[data-testid="user-list-item"]'); expect(await userItems.count()).toBeGreaterThan(0); }); test('should auto-login when clicking user from list', async ({ page }) => { const localTab = page.locator('[data-testid="local-login-tab"]'); await localTab.click(); // Click first user in list const firstUser = page.locator('[data-testid="user-list-item"]').first(); await firstUser.click(); // Password input should be focused const passwordInput = page.locator('[data-testid="local-password-input"]'); await expect(passwordInput).toBeFocused(); }); });