mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-30 14:58:08 +00:00
70 lines
2.7 KiB
TypeScript
70 lines
2.7 KiB
TypeScript
import { test, expect } from '@playwright/test'
|
|
import { serveExport } from './export'
|
|
import { signIn } from '../session'
|
|
|
|
/**
|
|
* EVERY ROOM ON AN ACTUAL THUMB.
|
|
*
|
|
* `readable.spec` measures the same four widths with a FINE pointer, which is a
|
|
* different page: `@hanzo/design`'s base.css grows every control to a 44px floor under
|
|
* `pointer: coarse`, so a 390px desktop window reads rooms whose controls are
|
|
* still their small size. The widths that ship to a phone were never measured.
|
|
*
|
|
* The difference is not theoretical. It has mattered twice — the organization
|
|
* switcher sat at 28px until a coarse run showed it, and the composer's row only
|
|
* reaches the floor here — and a taller control is exactly what pushes a row
|
|
* past the edge.
|
|
*
|
|
* The pointer is a property of the CONTEXT, which Playwright fixes per file, so
|
|
* this is a file rather than a fifth size in the other one.
|
|
*/
|
|
test.use({ viewport: { width: 390, height: 844 }, hasTouch: true, isMobile: true })
|
|
|
|
const ROOMS = ['/chat', '/home', '/board', '/drive', '/inbox', '/work']
|
|
|
|
for (const room of ROOMS) {
|
|
test(`${room} is readable on a thumb`, async ({ page }) => {
|
|
test.setTimeout(60_000)
|
|
await signIn(page)
|
|
const site = await serveExport()
|
|
try {
|
|
await page.goto(`${site.url}${room}`)
|
|
await expect(page.locator('main')).toBeVisible({ timeout: 20_000 })
|
|
|
|
const found = await page.evaluate((width) => {
|
|
const scrolls = (el: Element | null): boolean => {
|
|
for (let n = el; n; n = n.parentElement) {
|
|
const o = getComputedStyle(n).overflowX
|
|
if (o === 'auto' || o === 'scroll') return true
|
|
}
|
|
return false
|
|
}
|
|
// Content, not any box — a glow drawn to bleed off a card corner is not
|
|
// something a reader cannot reach. See readable.spec.
|
|
const speaks = (el: Element): boolean =>
|
|
(el.textContent || '').trim().length > 0 ||
|
|
el.matches('button,[role=button],a[href],select,input,textarea') ||
|
|
el.querySelector('button,[role=button],a[href],select,input,textarea') !== null
|
|
|
|
const past: string[] = []
|
|
for (const el of Array.from(document.querySelectorAll('body *'))) {
|
|
const b = el.getBoundingClientRect()
|
|
if (
|
|
b.width > 0 &&
|
|
b.height > 0 &&
|
|
b.right > width + 1 &&
|
|
!scrolls(el.parentElement) &&
|
|
speaks(el)
|
|
)
|
|
past.push(`${el.tagName}.${(el.className || '').toString().split(' ')[0]}`)
|
|
}
|
|
return past.slice(0, 3)
|
|
}, 390)
|
|
|
|
expect(found, `${room} puts something out of reach on a thumb`).toEqual([])
|
|
} finally {
|
|
await site.close()
|
|
}
|
|
})
|
|
}
|