const { test, expect } = require('@playwright/test'); test('mobile compare uses tabs to show one mounted pane at a time', async ({ page }) => { await page.setViewportSize({ width: 390, height: 844 }); await page.goto('/login'); await page.addStyleTag({ url: '/static/style.css?v=20260903comparemodeicons1-emailsettingscards1' }); await page.evaluate(async () => { const { default: state } = await import('/static/js/compare/state.js'); const { mountMobilePaneTabs } = await import('/static/js/compare/panes.js?v=20260903comparemodeicons1'); document.body.innerHTML = '
'; const host = document.getElementById('compare-test-host'); host.style.cssText = 'position:fixed;inset:0;display:flex;flex-direction:column;padding-top:12px;'; const grid = host.querySelector('.compare-grid'); state._blindMode = false; state._parallel = true; state._selectedModels = [ { name: 'Alpha model' }, { name: 'Beta model' }, { name: 'Gamma model' }, ]; state._activeMobilePane = 0; state._selectedModels.forEach((model, index) => { const pane = document.createElement('section'); pane.className = 'compare-pane'; pane.dataset.pane = String(index); pane.innerHTML = `
Response ${index + 1}
`; grid.appendChild(pane); }); mountMobilePaneTabs(host, grid); }); const tabs = page.locator('.compare-mobile-tab'); const panes = page.locator('.compare-pane'); await expect(tabs).toHaveCount(3); await expect(tabs.nth(0)).toHaveAttribute('aria-selected', 'true'); await expect(panes.nth(0)).toBeVisible(); await expect(panes.nth(1)).toBeHidden(); await expect(panes.nth(2)).toBeHidden(); await tabs.nth(1).click(); await expect(tabs.nth(1)).toHaveAttribute('aria-selected', 'true'); await expect(panes.nth(0)).toBeHidden(); await expect(panes.nth(1)).toBeVisible(); await expect(panes.nth(2)).toBeHidden(); const geometry = await page.evaluate(() => ({ grid: document.querySelector('.compare-grid').getBoundingClientRect().toJSON(), pane: document.querySelector('.compare-pane-mobile-active').getBoundingClientRect().toJSON(), visiblePaneCount: Array.from(document.querySelectorAll('.compare-pane')).filter((pane) => getComputedStyle(pane).display !== 'none').length, })); expect(geometry.visiblePaneCount).toBe(1); expect(Math.abs((geometry.grid.width - 16) - geometry.pane.width)).toBeLessThan(2); }); test('mobile compare probe keeps feedback below models and actions split', async ({ page }) => { await page.setViewportSize({ width: 390, height: 844 }); await page.goto('/login'); await page.addStyleTag({ url: '/static/style.css?v=20260903comparemodeicons1-emailsettingscards1' }); await page.evaluate(() => { document.body.innerHTML = `
Checking models...
▁▂▃Alpha
×Beta
Insufficient balance
`; }); const layout = await page.evaluate(() => { const list = document.querySelector('.compare-probe-list').getBoundingClientRect(); const feedback = document.querySelector('.compare-probe-feedback').getBoundingClientRect(); const back = document.querySelector('.compare-probe-footer-btn').getBoundingClientRect(); const start = document.querySelector('.compare-probe-start-anyway').getBoundingClientRect(); const spinnerStyle = getComputedStyle(document.querySelector('.compare-probe-spinner')); const cardStyle = getComputedStyle(document.querySelector('.compare-probe-card')); const startStyle = getComputedStyle(document.querySelector('.compare-probe-start-anyway')); return { feedbackBelowList: feedback.top >= list.bottom, splitActions: back.left < start.left && start.right > 350, spinnerTransform: spinnerStyle.transform, cardRadius: cardStyle.borderRadius, startBackground: startStyle.backgroundColor, }; }); expect(layout.feedbackBelowList).toBe(true); expect(layout.splitActions).toBe(true); expect(layout.spinnerTransform).toContain('-2'); expect(layout.cardRadius).toBe('8px'); expect(layout.startBackground).not.toBe('rgba(0, 0, 0, 0)'); });