/** * Mobile Responsiveness Test for HVAC Plugin UX Enhancements * * Simplified mobile testing focusing on key responsiveness features */ import { test, expect } from '@playwright/test'; const STAGING_URL = 'https://upskill-staging.measurequick.com'; // Test responsive breakpoints test.describe('Mobile Responsiveness', () => { test('Mobile login page layout (iPhone viewport)', async ({ page }) => { test.setTimeout(20000); // Set mobile viewport await page.setViewportSize({ width: 375, height: 667 }); 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(40); // 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-375x667.png` }); }); test('Mobile dashboard layout and navigation', async ({ page }) => { test.setTimeout(30000); // Set mobile viewport await page.setViewportSize({ width: 375, height: 667 }); // 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-375x667.png` }); }); test('Toast notifications positioning on mobile', async ({ page }) => { test.setTimeout(25000); // Set mobile viewport await page.setViewportSize({ width: 375, height: 667 }); // 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'); // Inject test toast to verify mobile positioning await page.evaluate(() => { // Create toast container if it doesn't exist if (!document.querySelector('.hvac-toast-container')) { const container = document.createElement('div'); container.className = 'hvac-toast-container'; container.style.cssText = ` position: fixed; top: 10px; right: 10px; left: 10px; z-index: 10000; display: flex; flex-direction: column; gap: 10px; max-width: none; pointer-events: none; `; document.body.appendChild(container); } // Create a test toast const toast = document.createElement('div'); toast.className = 'hvac-toast success show'; toast.style.cssText = ` background: white; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); padding: 16px 20px; pointer-events: all; transform: translateX(0); border-left: 4px solid #10b981; display: flex; align-items: flex-start; gap: 12px; max-width: 100%; word-wrap: break-word; `; toast.innerHTML = `
Success
Mobile toast notification test - this is a longer message to test wrapping
`; const container = document.querySelector('.hvac-toast-container'); if (container) { container.appendChild(toast); } }); await page.waitForTimeout(1000); // Check if toast is visible and properly positioned const toast = page.locator('.hvac-toast'); await expect(toast).toBeVisible(); // Verify toast doesn't overflow viewport const toastBox = await toast.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-375x667.png` }); }); test('Form interaction on mobile devices', async ({ page }) => { test.setTimeout(25000); // Set mobile viewport await page.setViewportSize({ width: 375, height: 667 }); // 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(40); // 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(); if (buttonCount > 0) { const button = buttons.first(); if (await button.isVisible()) { const buttonBox = await button.boundingBox(); expect(buttonBox?.height).toBeGreaterThanOrEqual(40); } } // Take screenshot await page.screenshot({ path: `test-results/mobile-form-375x667.png` }); }); test('Responsive breakpoints verification', async ({ page }) => { test.setTimeout(35000); const breakpoints = [ { name: 'Mobile-Small', width: 320, height: 568 }, { name: 'Mobile-Medium', width: 375, height: 667 }, { name: 'Tablet-Portrait', width: 768, height: 1024 }, ]; for (const breakpoint of breakpoints) { // 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: navigation should adapt const nav = page.locator('.hvac-dashboard-nav'); await expect(nav).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}-${breakpoint.width}x${breakpoint.height}.png`, fullPage: false }); console.log(`✓ Verified ${breakpoint.name} (${breakpoint.width}x${breakpoint.height})`); } }); test('UX enhancements load correctly', async ({ page }) => { test.setTimeout(20000); // Set mobile viewport await page.setViewportSize({ width: 375, height: 667 }); // 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 that UX enhancement assets are loaded const uxEnhancementsLoaded = await page.evaluate(() => { // Check if HVACToast is available const hasToast = typeof window.HVACToast !== 'undefined'; // Check if UX CSS is loaded by looking for specific classes const uxStyles = Array.from(document.styleSheets).some(sheet => { try { return Array.from(sheet.cssRules).some(rule => rule.selectorText && rule.selectorText.includes('hvac-toast') ); } catch (e) { return false; } }); return { hasToast, uxStyles, mobileNav: !!document.querySelector('.hvac-mobile-nav-container, .hvac-mobile-nav-toggle') }; }); console.log('UX Enhancements status:', uxEnhancementsLoaded); // At minimum, some UX elements should be present expect(uxEnhancementsLoaded.hasToast || uxEnhancementsLoaded.uxStyles).toBe(true); await page.screenshot({ path: `test-results/ux-enhancements-loaded.png` }); }); });