import { test, expect } from '@playwright/test'; /** * E2E Tests for Backward Compatibility - Single-Server Login (US-011) * * These tests verify that the classic username/password login flow works * when ORACLE_SERVERS is NOT configured (single-server mode). * * Prerequisites: * 1. Backend running WITHOUT ORACLE_SERVERS env variable * 2. Start test environment: ./start.sh test * 3. Frontend running on port 3000 * * Run: * npm run test:e2e -- single-server-login.spec.js * npm run test:e2e:headed -- single-server-login.spec.js */ // Test configuration for single-server mode const TEST_USER = { username: 'MARIUS M', password: '123', company: 'MARIUSM AUTO' }; test.describe('Single-Server Login Backward Compatibility (US-011)', () => { test('should show username/password form in single-server mode', async ({ page }) => { // Navigate to login page await page.goto('/'); // Wait for auth mode detection to complete // The login form should show username field (not email) in single-server mode await page.waitForSelector('input#identity', { timeout: 10000 }); // Verify username field is visible (single-server mode) const usernameField = page.locator('input#identity'); const emailField = page.locator('input#identity'); // In single-server mode, username field should be visible // In multi-server mode, email field would be visible instead const isUsernameVisible = await usernameField.isVisible().catch(() => false); const isEmailVisible = await emailField.isVisible().catch(() => false); // At least one should be visible expect(isUsernameVisible || isEmailVisible).toBe(true); if (isUsernameVisible) { // Single-server mode - verify password field is also present const passwordField = page.locator('#password input'); await expect(passwordField).toBeVisible(); // Verify "Autentificare" button exists (not "Continuă") await expect(page.locator('button:has-text("Autentificare")')).toBeVisible(); } }); test('should successfully login with username/password', async ({ page }) => { await page.goto('/'); // Wait for form to load await page.waitForSelector('input#identity', { timeout: 10000 }); // Check which mode we're in const usernameField = page.locator('input#identity'); const isUsernameVisible = await usernameField.isVisible().catch(() => false); if (isUsernameVisible) { // Single-server mode: fill username and password await page.fill('input#identity', TEST_USER.username); await page.fill('#password input', TEST_USER.password); // Click login button await page.click('button:has-text("Autentificare")'); // Wait for redirect after successful login await page.waitForURL(/\/(reports|data-entry|dashboard)/, { timeout: 15000 }); // Verify we're logged in (check for logout button or user menu) const logoutButton = page.locator('button:has-text("Deconectare"), [class*="logout"]'); const userMenu = page.locator('[class*="user"], [class*="profile"]'); // Should be redirected away from login page expect(page.url()).not.toContain('/login'); } else { // Multi-server mode: use email flow (existing tests cover this) console.log('Multi-server mode detected - skipping single-server login test'); } }); test('should show error for invalid credentials', async ({ page }) => { await page.goto('/'); // Wait for form to load await page.waitForSelector('input#identity', { timeout: 10000 }); const usernameField = page.locator('input#identity'); const isUsernameVisible = await usernameField.isVisible().catch(() => false); if (isUsernameVisible) { // Single-server mode: test invalid credentials await page.fill('input#identity', 'INVALID_USER'); await page.fill('#password input', 'wrong_password'); // Click login button await page.click('button:has-text("Autentificare")'); // Wait for error message await page.waitForTimeout(2000); // Wait for API response // Check for error toast or message const errorToast = page.locator('.p-toast-message-error, .p-toast-error, [class*="error"]'); const errorMessage = page.locator('[class*="error-message"], .p-message-error'); // Should show some form of error const hasError = await errorToast.isVisible().catch(() => false) || await errorMessage.isVisible().catch(() => false); // Should still be on login page (not redirected) expect(page.url()).toMatch(/\/$|\/login/); } }); test('should preserve JWT in localStorage after login', async ({ page }) => { await page.goto('/'); await page.waitForSelector('input#identity', { timeout: 10000 }); const usernameField = page.locator('input#identity'); const isUsernameVisible = await usernameField.isVisible().catch(() => false); if (isUsernameVisible) { await page.fill('input#identity', TEST_USER.username); await page.fill('#password input', TEST_USER.password); await page.click('button:has-text("Autentificare")'); await page.waitForURL(/\/(reports|data-entry|dashboard)/, { timeout: 15000 }); // Check localStorage for JWT const accessToken = await page.evaluate(() => localStorage.getItem('access_token')); const user = await page.evaluate(() => localStorage.getItem('user')); // JWT should be stored expect(accessToken).toBeTruthy(); expect(accessToken.split('.').length).toBe(3); // Valid JWT format // User should be stored expect(user).toBeTruthy(); const userData = JSON.parse(user); expect(userData).toHaveProperty('username'); } }); test('should access reports after login', async ({ page }) => { await page.goto('/'); await page.waitForSelector('input#identity', { timeout: 10000 }); const usernameField = page.locator('input#identity'); const isUsernameVisible = await usernameField.isVisible().catch(() => false); if (isUsernameVisible) { // Login first await page.fill('input#identity', TEST_USER.username); await page.fill('#password input', TEST_USER.password); await page.click('button:has-text("Autentificare")'); await page.waitForURL(/\/(reports|data-entry|dashboard)/, { timeout: 15000 }); // Navigate to reports if not already there await page.goto('/reports'); // Wait for page to load await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => {}); // Should not be redirected back to login await page.waitForTimeout(2000); expect(page.url()).not.toMatch(/\/$|\/login/); } }); }); test.describe('Auth Mode Detection', () => { test('should return valid auth-mode response', async ({ request }) => { // Test the auth-mode endpoint directly const response = await request.get('/api/system/auth-mode'); expect(response.ok()).toBe(true); const data = await response.json(); // Should have required fields expect(data).toHaveProperty('mode'); expect(data).toHaveProperty('supports_email_login'); // Mode should be either single-server or multi-server expect(['single-server', 'multi-server']).toContain(data.mode); // supports_email_login should match mode if (data.mode === 'single-server') { expect(data.supports_email_login).toBe(false); } else { expect(data.supports_email_login).toBe(true); } }); });