import { test, expect } from '@playwright/test'; import { LoginPage } from '../../page-objects/LoginPage.js'; import { DashboardPage } from '../../page-objects/DashboardPage.js'; import { testCredentials } from '../../fixtures/auth.js'; test.describe('Responsive Design Tests', () => { let loginPage; let dashboardPage; // Common setup for all responsive tests const setupMockAuth = async (page) => { await page.route('**/api/auth/login', async route => { await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ access_token: 'mock_access_token', refresh_token: 'mock_refresh_token', user: { id: 1, username: 'testuser', full_name: 'Test User' } }), }); }); await page.route('**/api/companies', async route => { await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify([ { code: 'COMP1', name: 'Test Company' } ]), }); }); }; test.describe('Mobile Layout (320px)', () => { test.beforeEach(async ({ page }) => { await page.setViewportSize({ width: 320, height: 568 }); loginPage = new LoginPage(page); dashboardPage = new DashboardPage(page); await setupMockAuth(page); }); test('should display login form correctly on mobile', async ({ page }) => { await loginPage.navigate(); // Take screenshot for visual verification await page.screenshot({ path: 'mobile-login.png', fullPage: true }); // Login form should be visible and properly sized await expect(page.locator(loginPage.loginCard)).toBeVisible(); await expect(page.locator(loginPage.usernameInput)).toBeVisible(); await expect(page.locator(loginPage.passwordInput)).toBeVisible(); // Check that form takes appropriate width const cardWidth = await page.locator(loginPage.loginCard).boundingBox(); expect(cardWidth.width).toBeLessThan(320); // Should fit in viewport }); test('should adapt dashboard layout for mobile', async ({ page }) => { // Login and navigate to dashboard await loginPage.navigate(); await loginPage.login(testCredentials.valid.username, testCredentials.valid.password); await page.waitForURL('/dashboard'); // Take screenshot await page.screenshot({ path: 'mobile-dashboard.png', fullPage: true }); // Dashboard should be responsive await expect(page.locator(dashboardPage.pageTitle)).toBeVisible(); // Stats grid should stack vertically on mobile const statsGrid = page.locator(dashboardPage.statsGrid); if (await statsGrid.isVisible()) { const gridBox = await statsGrid.boundingBox(); expect(gridBox.width).toBeLessThan(320); } }); }); test.describe('Tablet Layout (768px)', () => { test.beforeEach(async ({ page }) => { await page.setViewportSize({ width: 768, height: 1024 }); loginPage = new LoginPage(page); dashboardPage = new DashboardPage(page); await setupMockAuth(page); }); test('should display login form appropriately on tablet', async ({ page }) => { await loginPage.navigate(); await page.screenshot({ path: 'tablet-login.png', fullPage: true }); // Login card should be centered and well-proportioned const loginCard = page.locator(loginPage.loginCard); await expect(loginCard).toBeVisible(); const cardBox = await loginCard.boundingBox(); expect(cardBox.width).toBeGreaterThan(300); expect(cardBox.width).toBeLessThan(500); }); test('should show proper tablet dashboard layout', async ({ page }) => { await loginPage.navigate(); await loginPage.login(testCredentials.valid.username, testCredentials.valid.password); await page.waitForURL('/dashboard'); await page.screenshot({ path: 'tablet-dashboard.png', fullPage: true }); // Dashboard elements should be properly spaced await expect(page.locator(dashboardPage.pageTitle)).toBeVisible(); // Stats should be arranged in appropriate grid const statsCards = page.locator('.stat-card'); const cardCount = await statsCards.count(); if (cardCount > 0) { // Cards should be visible and properly sized for (let i = 0; i < cardCount; i++) { await expect(statsCards.nth(i)).toBeVisible(); } } }); }); test.describe('Desktop Layout (1024px+)', () => { test.beforeEach(async ({ page }) => { await page.setViewportSize({ width: 1024, height: 768 }); loginPage = new LoginPage(page); dashboardPage = new DashboardPage(page); await setupMockAuth(page); }); test('should display full desktop login layout', async ({ page }) => { await loginPage.navigate(); await page.screenshot({ path: 'desktop-login.png', fullPage: true }); // Login should be centered with appropriate sizing const loginCard = page.locator(loginPage.loginCard); await expect(loginCard).toBeVisible(); // Card should not take full width on desktop const cardBox = await loginCard.boundingBox(); expect(cardBox.width).toBeLessThan(500); }); test('should show complete desktop dashboard layout', async ({ page }) => { await loginPage.navigate(); await loginPage.login(testCredentials.valid.username, testCredentials.valid.password); await page.waitForURL('/dashboard'); await page.screenshot({ path: 'desktop-dashboard.png', fullPage: true }); // All dashboard elements should be visible await expect(page.locator(dashboardPage.pageTitle)).toBeVisible(); await expect(page.locator(dashboardPage.pageSubtitle)).toBeVisible(); // Stats grid should use horizontal layout const statsGrid = page.locator(dashboardPage.statsGrid); if (await statsGrid.isVisible()) { const gridBox = await statsGrid.boundingBox(); expect(gridBox.width).toBeGreaterThan(600); } }); }); test.describe('Wide Screen Layout (1920px)', () => { test.beforeEach(async ({ page }) => { await page.setViewportSize({ width: 1920, height: 1080 }); loginPage = new LoginPage(page); dashboardPage = new DashboardPage(page); await setupMockAuth(page); }); test('should handle wide screen layouts appropriately', async ({ page }) => { await loginPage.navigate(); await loginPage.login(testCredentials.valid.username, testCredentials.valid.password); await page.waitForURL('/dashboard'); await page.screenshot({ path: 'widescreen-dashboard.png', fullPage: true }); // Content should not stretch too wide const mainContent = page.locator('.dashboard-content'); if (await mainContent.isVisible()) { const contentBox = await mainContent.boundingBox(); // Content should have reasonable max-width expect(contentBox.width).toBeLessThan(1600); } }); }); test.describe('Orientation Changes', () => { test('should handle portrait to landscape orientation', async ({ page }) => { // Start in mobile portrait await page.setViewportSize({ width: 375, height: 667 }); loginPage = new LoginPage(page); await setupMockAuth(page); await loginPage.navigate(); await page.screenshot({ path: 'mobile-portrait.png' }); // Rotate to landscape await page.setViewportSize({ width: 667, height: 375 }); await page.waitForTimeout(500); // Allow for reflow await page.screenshot({ path: 'mobile-landscape.png' }); // Login form should still be usable await expect(page.locator(loginPage.loginCard)).toBeVisible(); await expect(page.locator(loginPage.usernameInput)).toBeVisible(); }); }); test.describe('Touch Interactions', () => { test('should handle touch interactions on mobile', async ({ page }) => { await page.setViewportSize({ width: 375, height: 667 }); loginPage = new LoginPage(page); await setupMockAuth(page); await loginPage.navigate(); // Test touch interactions await page.tap(loginPage.usernameInput); await page.fill(loginPage.usernameInput, 'testuser'); await page.tap(loginPage.passwordInput); await page.fill(loginPage.passwordInput, 'testpass'); // Login button should be tappable const loginButton = page.locator(loginPage.loginButton); await expect(loginButton).toBeEnabled(); // Button should have appropriate touch target size (minimum 44px) const buttonBox = await loginButton.boundingBox(); expect(buttonBox.height).toBeGreaterThanOrEqual(44); }); }); });