mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-30 14:58:08 +00:00
82 lines
3.6 KiB
TypeScript
82 lines
3.6 KiB
TypeScript
import { expect, test } from '@playwright/test'
|
|
import { serveExport } from './export'
|
|
import { signIn } from '../session'
|
|
|
|
let base: string
|
|
let stop: () => Promise<void>
|
|
|
|
test.beforeAll(async () => {
|
|
const served = await serveExport()
|
|
base = served.url
|
|
stop = served.close
|
|
})
|
|
|
|
test.afterAll(async () => stop())
|
|
|
|
test('sidebar has tight margin and zero icon shift when toggled open/closed', async ({ page }) => {
|
|
await signIn(page, { name: 'Antje', orgs: [{ org: 'webby-ai', role: 'admin' }] })
|
|
await page.addInitScript(() => localStorage.setItem('hanzo_iam_current_org', 'webby-ai'))
|
|
|
|
await page.route(
|
|
(u) => u.pathname.startsWith('/v1/'),
|
|
(route) => route.fulfill({ json: {} })
|
|
)
|
|
|
|
await page.setViewportSize({ width: 1440, height: 900 })
|
|
await page.goto(`${base}/chat`)
|
|
await page.waitForLoadState('networkidle')
|
|
|
|
const toggle = page.locator('[data-slot="sidebar-toggle"]')
|
|
await expect(toggle).toBeVisible()
|
|
|
|
// Ensure sidebar is open first
|
|
if ((await toggle.getAttribute('aria-expanded')) !== 'true') {
|
|
await toggle.click()
|
|
}
|
|
await expect(page.locator('[data-slot="app-column"]')).toBeVisible()
|
|
|
|
// Measure icon position when open
|
|
const iconOpen = (await page.locator('[data-slot="rail-chat"] svg').boundingBox())!
|
|
const railOpen = (await page.locator('[data-slot="rail"]').boundingBox())!
|
|
|
|
console.log(`[MEASUREMENT OPEN] Rail: x=${railOpen.x}, width=${railOpen.width}`)
|
|
console.log(`[MEASUREMENT OPEN] Icon: x=${iconOpen.x}, width=${iconOpen.width}`)
|
|
|
|
// Close the sidebar
|
|
await toggle.click()
|
|
await expect(page.locator('[data-slot="app-column"]')).toHaveCount(0)
|
|
|
|
// Measure mark, icon, rail, and stage when closed
|
|
const railClosed = (await page.locator('[data-slot="rail"]').boundingBox())!
|
|
const markClosed = (await page.locator('[data-slot="rail-chat"]').boundingBox())!
|
|
const iconClosed = (await page.locator('[data-slot="rail-chat"] svg').boundingBox())!
|
|
const stageClosed = (await page.locator('[data-slot="stage"]').boundingBox())!
|
|
|
|
const leftMarginMark = markClosed.x - 0
|
|
const rightMarginMark = stageClosed.x - (markClosed.x + markClosed.width)
|
|
|
|
const leftMarginIcon = iconClosed.x - 0
|
|
const rightMarginIcon = stageClosed.x - (iconClosed.x + iconClosed.width)
|
|
|
|
console.log(`[MEASUREMENT CLOSED] Rail: x=${railClosed.x}, width=${railClosed.width}`)
|
|
console.log(`[MEASUREMENT CLOSED] Mark: x=${markClosed.x}, width=${markClosed.width}`)
|
|
console.log(`[MEASUREMENT CLOSED] Icon: x=${iconClosed.x}, width=${iconClosed.width}`)
|
|
console.log(`[MEASUREMENT CLOSED] Stage: x=${stageClosed.x}`)
|
|
console.log(`[MEASUREMENT CLOSED] Mark margins: left=${leftMarginMark}px, right=${rightMarginMark}px`)
|
|
console.log(`[MEASUREMENT CLOSED] Icon margins: left=${leftMarginIcon}px, right=${rightMarginIcon}px`)
|
|
|
|
// Save screenshot of closed sidebar
|
|
await page.screenshot({ path: 'out/sidebar-closed-symmetry.png', fullPage: false })
|
|
|
|
// 1. Zero icon movement between open and closed!
|
|
expect(iconClosed.x, 'Icon horizontal position must not move when sidebar is toggled').toBe(iconOpen.x)
|
|
expect(railClosed.x, 'Rail must stay flush at window left edge (x=0)').toBe(0)
|
|
expect(railClosed.width, 'Rail width should be 44px for 4px compact margin around 36px mark').toBe(44)
|
|
|
|
// 2. Pixel-perfect symmetry on the tight 4px margin
|
|
expect(leftMarginMark, 'Mark should have identical tight left and right margin').toBe(rightMarginMark)
|
|
expect(leftMarginMark, 'Mark should have 4px compact margin').toBe(4)
|
|
expect(leftMarginIcon, 'Icon should have identical tight left and right margin').toBe(rightMarginIcon)
|
|
expect(leftMarginIcon, 'Icon should have 13px left and right margin').toBe(13)
|
|
})
|