import { test, expect } from '@playwright/test'; import { TEST_CONFIG } from './utils/test-helpers'; /** * Cross-Browser Tests * * These tests verify that core functionality works across different browsers: * - Chromium (Chrome, Edge) * - Firefox * - WebKit (Safari) * * These tests run on all browsers configured in playwright.config.ts * * To run cross-browser tests: * - Run: npx playwright test cross-browser * - Run on specific browser: npx playwright test cross-browser --project=firefox */ test.describe('Cross-Browser Compatibility', () => { // Use authenticated state for most tests test.use({ storageState: 'e2e/.auth/user.json' }); test.describe('Authentication', () => { test('should login successfully on all browsers', async ({ page, browserName }) => { // Use unauthenticated state for login test await page.context().clearCookies(); await page.goto(`${TEST_CONFIG.FRONTEND_URL}/login`); await page.waitForLoadState('networkidle'); // Wait for form to be ready await page.waitForSelector('form', { timeout: 5000 }); await page.waitForTimeout(500); // Fill login form await page.fill('input[type="email"], input[name="email"]', TEST_CONFIG.TEST_USER_EMAIL); await page.fill('input[type="password"], input[name="password"]', TEST_CONFIG.TEST_USER_PASSWORD); // Submit form await page.click('button[type="submit"], button:has-text("Login"), button:has-text("Sign in")'); // Wait for navigation to dashboard await page.waitForURL('**/dashboard', { timeout: 10000 }); // Verify we're on dashboard expect(page.url()).toContain('/dashboard'); console.log(`✅ Login successful on ${browserName}`); }); test('should display login form correctly on all browsers', async ({ page, browserName }) => { await page.context().clearCookies(); await page.goto(`${TEST_CONFIG.FRONTEND_URL}/login`); await page.waitForLoadState('networkidle'); // Check that form elements are visible const emailInput = page.locator('input[type="email"], input[name="email"]').first(); const passwordInput = page.locator('input[type="password"], input[name="password"]').first(); const submitButton = page.locator('button[type="submit"]').first(); await expect(emailInput).toBeVisible(); await expect(passwordInput).toBeVisible(); await expect(submitButton).toBeVisible(); console.log(`✅ Login form displayed correctly on ${browserName}`); }); }); test.describe('Navigation', () => { test('should navigate between pages on all browsers', async ({ page, browserName }) => { await page.goto(`${TEST_CONFIG.FRONTEND_URL}/dashboard`); await page.waitForLoadState('networkidle'); // Navigate to profile await page.click('a[href="/profile"], a[href*="profile"]', { timeout: 5000 }); await page.waitForURL('**/profile', { timeout: 5000 }); expect(page.url()).toContain('/profile'); // Navigate back to dashboard await page.click('a[href="/dashboard"], a[href*="dashboard"]', { timeout: 5000 }); await page.waitForURL('**/dashboard', { timeout: 5000 }); expect(page.url()).toContain('/dashboard'); console.log(`✅ Navigation works on ${browserName}`); }); test('should handle browser back/forward buttons', async ({ page, browserName }) => { await page.goto(`${TEST_CONFIG.FRONTEND_URL}/dashboard`); await page.waitForLoadState('networkidle'); // Navigate to profile await page.click('a[href="/profile"], a[href*="profile"]', { timeout: 5000 }); await page.waitForURL('**/profile', { timeout: 5000 }); // Use browser back button await page.goBack(); await page.waitForURL('**/dashboard', { timeout: 5000 }); expect(page.url()).toContain('/dashboard'); // Use browser forward button await page.goForward(); await page.waitForURL('**/profile', { timeout: 5000 }); expect(page.url()).toContain('/profile'); console.log(`✅ Browser navigation works on ${browserName}`); }); }); test.describe('UI Components', () => { test('should render buttons correctly on all browsers', async ({ page, browserName }) => { await page.goto(`${TEST_CONFIG.FRONTEND_URL}/dashboard`); await page.waitForLoadState('networkidle'); // Find buttons on the page const buttons = page.locator('button').first(); await expect(buttons).toBeVisible(); // Check button styling (basic check) const buttonStyles = await buttons.evaluate((el) => { const styles = window.getComputedStyle(el); return { display: styles.display, visibility: styles.visibility, }; }); expect(buttonStyles.display).not.toBe('none'); expect(buttonStyles.visibility).not.toBe('hidden'); console.log(`✅ Buttons render correctly on ${browserName}`); }); test('should render forms correctly on all browsers', async ({ page, browserName }) => { await page.goto(`${TEST_CONFIG.FRONTEND_URL}/profile`); await page.waitForLoadState('networkidle'); // Wait for form elements await page.waitForTimeout(1000); // Check for input fields const inputs = page.locator('input, textarea, select'); const inputCount = await inputs.count(); // Should have at least some form elements expect(inputCount).toBeGreaterThan(0); console.log(`✅ Forms render correctly on ${browserName}`); }); }); test.describe('JavaScript Features', () => { test('should support ES6+ features on all browsers', async ({ page, browserName }) => { const result = await page.evaluate(() => { // Test various ES6+ features const features = { arrowFunctions: typeof (() => { }) === 'function', promises: typeof Promise !== 'undefined', asyncAwait: typeof (async () => { }) === 'function', templateLiterals: typeof `test` === 'string', destructuring: (() => { try { const { a } = { a: 1 }; return a === 1; } catch { return false; } })(), spreadOperator: (() => { try { const arr = [...[1, 2, 3]]; return arr.length === 3; } catch { return false; } })(), }; return features; }); // All modern browsers should support these features expect(result.arrowFunctions).toBe(true); expect(result.promises).toBe(true); expect(result.asyncAwait).toBe(true); expect(result.templateLiterals).toBe(true); expect(result.destructuring).toBe(true); expect(result.spreadOperator).toBe(true); console.log(`✅ ES6+ features supported on ${browserName}`); }); test('should support Web APIs on all browsers', async ({ page, browserName }) => { const result = await page.evaluate(() => { return { fetch: typeof fetch !== 'undefined', localStorage: typeof localStorage !== 'undefined', sessionStorage: typeof sessionStorage !== 'undefined', webSocket: typeof WebSocket !== 'undefined', history: typeof window.history !== 'undefined' && typeof window.history.pushState === 'function', }; }); // All modern browsers should support these APIs expect(result.fetch).toBe(true); expect(result.localStorage).toBe(true); expect(result.sessionStorage).toBe(true); expect(result.webSocket).toBe(true); expect(result.history).toBe(true); console.log(`✅ Web APIs supported on ${browserName}`); }); }); test.describe('CSS Features', () => { test('should support modern CSS features on all browsers', async ({ page, browserName }) => { const result = await page.evaluate(() => { const testElement = document.createElement('div'); testElement.style.cssText = 'display: flex; grid-template-columns: 1fr; transform: translateX(0);'; document.body.appendChild(testElement); const styles = window.getComputedStyle(testElement); const supported = { flexbox: styles.display === 'flex' || styles.display === '-webkit-flex', grid: styles.gridTemplateColumns !== undefined, transform: styles.transform !== 'none' || styles.webkitTransform !== 'none', }; document.body.removeChild(testElement); return supported; }); // All modern browsers should support these CSS features expect(result.flexbox).toBe(true); expect(result.grid).toBe(true); expect(result.transform).toBe(true); console.log(`✅ Modern CSS features supported on ${browserName}`); }); }); test.describe('Responsive Design', () => { test('should be responsive on all browsers', async ({ page, browserName }) => { // Test mobile viewport await page.setViewportSize({ width: 375, height: 667 }); await page.goto(`${TEST_CONFIG.FRONTEND_URL}/dashboard`); await page.waitForLoadState('networkidle'); // Check that page is visible and not broken const body = page.locator('body'); await expect(body).toBeVisible(); // Test tablet viewport await page.setViewportSize({ width: 768, height: 1024 }); await page.reload(); await page.waitForLoadState('networkidle'); await expect(body).toBeVisible(); // Test desktop viewport await page.setViewportSize({ width: 1920, height: 1080 }); await page.reload(); await page.waitForLoadState('networkidle'); await expect(body).toBeVisible(); console.log(`✅ Responsive design works on ${browserName}`); }); }); test.describe('Error Handling', () => { test('should handle errors gracefully on all browsers', async ({ page, browserName }) => { // Navigate to a non-existent page await page.goto(`${TEST_CONFIG.FRONTEND_URL}/non-existent-page-12345`); await page.waitForLoadState('networkidle'); // Should show 404 page or error message, not blank page const body = page.locator('body'); const bodyText = await body.textContent(); expect(bodyText).not.toBe(''); expect(bodyText).not.toBeNull(); console.log(`✅ Error handling works on ${browserName}`); }); }); test.describe('Performance', () => { test('should load pages within acceptable time on all browsers', async ({ page, browserName }) => { const startTime = Date.now(); await page.goto(`${TEST_CONFIG.FRONTEND_URL}/dashboard`); await page.waitForLoadState('networkidle'); const loadTime = Date.now() - startTime; // Should load within 10 seconds (generous threshold for cross-browser) expect(loadTime).toBeLessThan(10000); console.log(`✅ Page loaded in ${loadTime}ms on ${browserName}`); }); }); });