upskill-event-manager/wordpress-dev/tests/e2e/mobile-responsiveness.test.ts
bengizmo dea1200efb feat: Add comprehensive UX enhancements for mobile and desktop
- Create modern toast notification system replacing browser alerts
- Add mobile-responsive layouts with touch-friendly elements
- Implement loading states and progress indicators for all AJAX operations
- Add mobile navigation with collapsible menus
- Create enhanced form validation with inline error messages
- Add accessibility features (keyboard navigation, ARIA labels)
- Build comprehensive mobile testing suite
- Optimize for 320px to 1024px+ screen sizes
- Include progressive enhancement and fallback support

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-05-23 16:41:01 -03:00

285 lines
No EOL
11 KiB
TypeScript

/**
* 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` });
});
});