// Mobile regression: hamburger opens the sidebar drawer, settings page fits viewport. const { test, expect } = require('@playwright/test'); const FD_BASE = process.env.FD_BASE_URL || 'http://localhost:8080'; const USER = process.env.FD_USER || 'e2e@flowdeck.test'; const PASS = process.env.FD_PASS || 'e2e-pass-123'; async function login(page) { await page.goto(`${FD_BASE}/auth/login?provider=local`, { waitUntil: 'domcontentloaded' }); await page.fill('#email', USER); await page.fill('#password', PASS); await page.click('.btn-primary'); const ok = await page.waitForURL('**/workspaces', { timeout: 10000 }).then(() => true).catch(() => false); if (!ok) { const resp = await page.request.post(`${FD_BASE}/auth/register`, { data: { email: USER, password: PASS, name: 'E2E Mobile' } }); if (!resp.ok() && resp.status() !== 409) throw new Error(`register ${resp.status()}`); await page.goto(`${FD_BASE}/auth/login?provider=local`, { waitUntil: 'domcontentloaded' }); await page.fill('#email', USER); await page.fill('#password', PASS); await page.click('.btn-primary'); await page.waitForURL('**/workspaces', { timeout: 10000 }); } } test.describe('mobile', () => { test.use({ viewport: { width: 390, height: 844 } }); test('hamburger opens mobile sidebar drawer', async ({ page }) => { const errs = []; page.on('pageerror', (e) => errs.push(e.message)); await login(page); await page.goto(`${FD_BASE}/library`, { waitUntil: 'domcontentloaded' }); const burger = page.locator('.hamburger-btn'); await expect(burger).toBeVisible(); // Sidebar starts off-canvas const sidebar = page.locator('#sidebar'); const boxBefore = await sidebar.boundingBox(); expect(boxBefore.x).toBeLessThan(0); await burger.click(); await expect(sidebar).toHaveClass(/mobile-open/, { timeout: 5000 }); const boxAfter = await sidebar.boundingBox(); expect(boxAfter.x).toBeGreaterThanOrEqual(0); expect(errs).toEqual([]); // Overlay tap closes it await page.locator('.sidebar-overlay').click({ position: { x: 350, y: 400 } }); await expect(sidebar).not.toHaveClass(/mobile-open/, { timeout: 5000 }); }); test('settings page fits mobile viewport', async ({ page }) => { await login(page); await page.goto(`${FD_BASE}/settings`, { waitUntil: 'domcontentloaded' }); const panel = page.locator('.settings-panel'); await expect(panel).toBeVisible(); const box = await panel.boundingBox(); expect(box.width).toBeLessThanOrEqual(390); expect(box.height).toBeLessThanOrEqual(844); // Nav becomes horizontal tabs: nav wider than tall const navBox = await page.locator('.settings-nav').boundingBox(); expect(navBox.width).toBeGreaterThan(navBox.height); // Tapping a nav item still switches sections await page.locator('.settings-nav-item', { hasText: 'Tags' }).click(); await expect(page.locator('h2', { hasText: 'Tags' }).first()).toBeVisible(); // No horizontal page overflow const overflow = await page.evaluate(() => document.documentElement.scrollWidth - document.documentElement.clientWidth); expect(overflow).toBeLessThanOrEqual(0); }); });