/** * Mobile Responsiveness Test for HVAC Plugin UX Enhancements * * Tests the mobile experience including: * - Touch-friendly interface elements * - Responsive layouts * - Mobile navigation * - Toast notifications on mobile * - Form usability on mobile devices */ import { test, expect, devices } from '@playwright/test'; const STAGING_URL = 'https://upskill-staging.measurequick.com'; // Test with different mobile viewports const mobileDevices = [ devices['iPhone 12'], devices['iPhone 12 Pro'], devices['Samsung Galaxy S21'], devices['iPad Mini'] ]; for (const device of mobileDevices) { test.describe(`Mobile Responsiveness - ${device.name}`, () => { test.use({ ...device }); test(`Login page mobile layout - ${device.name}`, async ({ page }) => { test.setTimeout(20000); await page.goto(`${STAGING_URL}/community-login`); await page.waitForLoadState('networkidle'); // Check login form is properly sized for mobile const loginForm = page.locator('#hvac_community_loginform'); await expect(loginForm).toBeVisible(); // Verify mobile-optimized form elements const usernameField = page.locator('#user_login'); const passwordField = page.locator('#user_pass'); const submitButton = page.locator('#wp-submit'); await expect(usernameField).toBeVisible(); await expect(passwordField).toBeVisible(); await expect(submitButton).toBeVisible(); // Check touch target sizes (minimum 44px for iOS) const submitBox = await submitButton.boundingBox(); expect(submitBox?.height).toBeGreaterThanOrEqual(44); // Test form field focus states work on mobile await usernameField.focus(); await passwordField.focus(); // Take screenshot for visual verification await page.screenshot({ path: `test-results/mobile-login-${device.name?.replace(/\s+/g, '-')}.png` }); }); test(`Dashboard mobile layout - ${device.name}`, async ({ page }) => { test.setTimeout(30000); // Login first await page.goto(`${STAGING_URL}/community-login`); await page.fill('#user_login', 'test_trainer'); await page.fill('#user_pass', 'Test123!'); await page.click('#wp-submit'); await page.waitForLoadState('networkidle'); // Verify we're on dashboard await expect(page).toHaveURL(/hvac-dashboard/); // Check dashboard layout adapts to mobile const dashboard = page.locator('.hvac-dashboard-wrapper'); await expect(dashboard).toBeVisible(); // Test mobile navigation if present const mobileNavToggle = page.locator('.hvac-mobile-nav-toggle'); if (await mobileNavToggle.isVisible()) { await mobileNavToggle.click(); const mobileNav = page.locator('.hvac-mobile-nav'); await expect(mobileNav).toHaveClass(/open/); // Test navigation links work const navLinks = page.locator('.hvac-mobile-nav a'); const navCount = await navLinks.count(); expect(navCount).toBeGreaterThan(0); } // Check stats cards stack properly on mobile const statCards = page.locator('.hvac-stat-card'); const statCount = await statCards.count(); if (statCount > 0) { // Verify cards are visible and properly sized for (let i = 0; i < Math.min(statCount, 3); i++) { await expect(statCards.nth(i)).toBeVisible(); } } // Test touch scrolling works await page.evaluate(() => window.scrollTo(0, 200)); await page.waitForTimeout(500); // Take screenshot await page.screenshot({ path: `test-results/mobile-dashboard-${device.name?.replace(/\s+/g, '-')}.png` }); }); test(`Toast notifications on mobile - ${device.name}`, async ({ page }) => { test.setTimeout(25000); // Login await page.goto(`${STAGING_URL}/community-login`); await page.fill('#user_login', 'test_trainer'); await page.fill('#user_pass', 'Test123!'); await page.click('#wp-submit'); await page.waitForLoadState('networkidle'); // Go to certificate reports to trigger potential notifications await page.goto(`${STAGING_URL}/certificate-reports`); await page.waitForLoadState('networkidle'); // Check if toast container exists and is positioned correctly for mobile const toastContainer = page.locator('.hvac-toast-container'); // Inject test toast to verify mobile positioning await page.evaluate(() => { if (window.HVACToast) { window.HVACToast.success('This is a test toast notification for mobile testing'); } }); await page.waitForTimeout(1000); // Check if toast is visible and properly positioned const toast = page.locator('.hvac-toast'); if (await toast.count() > 0) { await expect(toast.first()).toBeVisible(); // Verify toast doesn't overflow viewport const toastBox = await toast.first().boundingBox(); const viewport = page.viewportSize(); if (toastBox && viewport) { expect(toastBox.x + toastBox.width).toBeLessThanOrEqual(viewport.width); expect(toastBox.y).toBeGreaterThanOrEqual(0); } } // Take screenshot await page.screenshot({ path: `test-results/mobile-toast-${device.name?.replace(/\s+/g, '-')}.png` }); }); test(`Form interaction on mobile - ${device.name}`, async ({ page }) => { test.setTimeout(25000); // Login await page.goto(`${STAGING_URL}/community-login`); await page.fill('#user_login', 'test_trainer'); await page.fill('#user_pass', 'Test123!'); await page.click('#wp-submit'); await page.waitForLoadState('networkidle'); // Go to create event page to test forms await page.goto(`${STAGING_URL}/manage-event`); await page.waitForLoadState('networkidle'); // Test form field interactions const titleField = page.locator('#event_title'); if (await titleField.isVisible()) { // Check field is properly sized for mobile const fieldBox = await titleField.boundingBox(); expect(fieldBox?.height).toBeGreaterThanOrEqual(44); // Test touch interaction await titleField.tap(); await titleField.fill('Mobile Test Event'); const value = await titleField.inputValue(); expect(value).toBe('Mobile Test Event'); } // Check form buttons are touch-friendly const buttons = page.locator('button, input[type="submit"]'); const buttonCount = await buttons.count(); for (let i = 0; i < Math.min(buttonCount, 3); i++) { const button = buttons.nth(i); if (await button.isVisible()) { const buttonBox = await button.boundingBox(); expect(buttonBox?.height).toBeGreaterThanOrEqual(44); } } // Take screenshot await page.screenshot({ path: `test-results/mobile-form-${device.name?.replace(/\s+/g, '-')}.png` }); }); }); } // Test responsive breakpoints test.describe('Responsive Breakpoints', () => { const breakpoints = [ { name: 'Mobile Small', width: 320, height: 568 }, { name: 'Mobile Medium', width: 375, height: 667 }, { name: 'Mobile Large', width: 414, height: 896 }, { name: 'Tablet Portrait', width: 768, height: 1024 }, { name: 'Tablet Landscape', width: 1024, height: 768 } ]; for (const breakpoint of breakpoints) { test(`Dashboard layout at ${breakpoint.name} (${breakpoint.width}x${breakpoint.height})`, async ({ page }) => { test.setTimeout(25000); // Set viewport await page.setViewportSize({ width: breakpoint.width, height: breakpoint.height }); // Login await page.goto(`${STAGING_URL}/community-login`); await page.fill('#user_login', 'test_trainer'); await page.fill('#user_pass', 'Test123!'); await page.click('#wp-submit'); await page.waitForLoadState('networkidle'); // Check dashboard layout await expect(page).toHaveURL(/hvac-dashboard/); // Verify content is visible and accessible const mainContent = page.locator('.hvac-dashboard-wrapper, .entry-content'); await expect(mainContent).toBeVisible(); // Check navigation is appropriate for screen size if (breakpoint.width <= 767) { // Mobile: should see mobile nav or stacked nav const mobileNav = page.locator('.hvac-mobile-nav-toggle, .hvac-dashboard-nav'); await expect(mobileNav).toBeVisible(); } else { // Tablet/Desktop: should see regular nav const desktopNav = page.locator('.hvac-dashboard-nav'); await expect(desktopNav).toBeVisible(); } // Take screenshot await page.screenshot({ path: `test-results/responsive-${breakpoint.name.replace(/\s+/g, '-')}-${breakpoint.width}x${breakpoint.height}.png`, fullPage: true }); }); } }); // Test accessibility on mobile test.describe('Mobile Accessibility', () => { test.use(devices['iPhone 12']); test('Touch accessibility and keyboard navigation', async ({ page }) => { test.setTimeout(25000); // Login await page.goto(`${STAGING_URL}/community-login`); await page.fill('#user_login', 'test_trainer'); await page.fill('#user_pass', 'Test123!'); await page.click('#wp-submit'); await page.waitForLoadState('networkidle'); // Test keyboard navigation with tab await page.keyboard.press('Tab'); await page.keyboard.press('Tab'); await page.keyboard.press('Tab'); // Check focus states are visible const focusedElement = page.locator(':focus'); await expect(focusedElement).toBeVisible(); // Test escape key closes mobile elements await page.keyboard.press('Escape'); // Verify aria labels exist on interactive elements const buttons = page.locator('button[aria-label], input[aria-label]'); const buttonCount = await buttons.count(); console.log(`Found ${buttonCount} buttons with aria-labels`); // Take screenshot await page.screenshot({ path: `test-results/mobile-accessibility.png` }); }); });