const { test } = require('@playwright/test'); const FD_BASE = process.env.FD_BASE_URL || 'http://localhost:8080'; test.use({ viewport: { width: 390, height: 844 } }); test('diagnose mobile sidebar wheel scroll', async ({ page }) => { await page.goto(`${FD_BASE}/auth/login?provider=local`, { waitUntil: 'domcontentloaded' }); await page.fill('#email', process.env.FD_USER || 'e2e@flowdeck.test'); await page.fill('#password', process.env.FD_PASS || 'e2e-pass-123'); await page.click('.btn-primary'); await page.waitForURL('**/workspaces', { timeout: 10000 }).catch(() => {}); await page.goto(`${FD_BASE}/library`, { waitUntil: 'domcontentloaded' }); await page.waitForFunction(() => document.querySelector('.hamburger-btn')); await page.locator('.hamburger-btn').click(); await page.waitForSelector('#sidebar.mobile-open'); const info = await page.evaluate(() => { const sb = document.getElementById('sidebar'); const sc = document.querySelector('.sidebar-scroll'); const cs = getComputedStyle(sb); const ccs = sc ? getComputedStyle(sc) : null; return { sidebar: { display: cs.display, height: cs.height, overflow: cs.overflow, sh: sb.scrollHeight, ch: sb.clientHeight }, scroll: sc ? { top: sc.scrollTop, sh: sc.scrollHeight, ch: sc.clientHeight, oy: ccs.overflowY, flex: ccs.flex, rect: JSON.stringify(sc.getBoundingClientRect()) } : null, wheelTarget: (() => { const el = document.elementFromPoint(150, 400); return el ? el.className : 'none'; })(), }; }); console.log('DIAG:', JSON.stringify(info, null, 1)); await page.mouse.move(150, 400); await page.mouse.wheel(0, 300); await page.waitForTimeout(300); const after = await page.evaluate(() => { const sc = document.querySelector('.sidebar-scroll'); return { scTop: sc.scrollTop, scSH: sc.scrollHeight, scCH: sc.clientHeight, bodyTop: document.scrollingElement.scrollTop }; }); console.log('AFTER WHEEL:', JSON.stringify(after)); });