95 lines
4.4 KiB
TypeScript
95 lines
4.4 KiB
TypeScript
import { expect, test, type Page } from '@playwright/test'
|
|
|
|
interface PoiCandidate {
|
|
poiId: string
|
|
floorId: string
|
|
name: string
|
|
primaryCategory: string
|
|
positionGltf: [number, number, number]
|
|
}
|
|
|
|
interface GuideDiagnostics {
|
|
isInitialModelReady: () => boolean
|
|
getFloors: () => Array<{ floorId: string }>
|
|
getReport: () => { floorId: string; activeFocusPoiId: string }
|
|
resetToViewBaseline: (options: { view: 'floor'; floorId: string; reason: 'floor-reset' }) => Promise<unknown>
|
|
getFloorPois: (floorId: string) => Promise<PoiCandidate[]>
|
|
focusTargetPoi: (request: PoiCandidate & { requestId: string }) => Promise<unknown>
|
|
clearTargetFocus: () => void
|
|
}
|
|
|
|
const openGuide = async (page: Page) => {
|
|
await page.goto('/')
|
|
await page.waitForURL(/tab=guide/, { timeout: 30_000 })
|
|
await expect.poll(async () => page.evaluate(() => (
|
|
(window as Window & { __GUIDE_3D_VISUAL_STABILITY__?: GuideDiagnostics })
|
|
.__GUIDE_3D_VISUAL_STABILITY__?.isInitialModelReady() || false
|
|
)), { timeout: 180_000 }).toBe(true)
|
|
}
|
|
|
|
const resetToActiveFloor = async (page: Page) => page.evaluate(async () => {
|
|
const api = (window as Window & { __GUIDE_3D_VISUAL_STABILITY__?: GuideDiagnostics })
|
|
.__GUIDE_3D_VISUAL_STABILITY__
|
|
if (!api) throw new Error('ThreeMap diagnostics unavailable')
|
|
await api.resetToViewBaseline({ view: 'floor', floorId: api.getReport().floorId, reason: 'floor-reset' })
|
|
return api.getReport().floorId
|
|
})
|
|
|
|
for (const deviceScaleFactor of [1, 3]) {
|
|
test.describe(`POI DOM labels at DPR ${deviceScaleFactor}`, () => {
|
|
test.use({ viewport: { width: 390, height: 844 }, deviceScaleFactor })
|
|
|
|
test('renders measured native labels and clears focused labels without residue', async ({ page }, testInfo) => {
|
|
await openGuide(page)
|
|
const floorId = await resetToActiveFloor(page)
|
|
const labels = page.locator('[data-poi-label-kind="ambient"]:visible')
|
|
await expect(labels.first()).toBeVisible({ timeout: 30_000 })
|
|
|
|
const hall = page.locator('[data-poi-label-kind="ambient"].three-poi-dom-label--hall:visible').first()
|
|
const facility = page.locator('[data-poi-label-kind="ambient"].three-poi-dom-label--service').first()
|
|
await expect(hall).toBeVisible()
|
|
|
|
for (const locator of [hall, facility]) {
|
|
await expect(locator).toHaveCSS('pointer-events', 'none')
|
|
const fontSize = await locator.evaluate((element) => Number.parseFloat(getComputedStyle(element).fontSize))
|
|
expect(fontSize).toBeGreaterThanOrEqual(locator === hall ? 14 : 13)
|
|
}
|
|
|
|
for (const locator of [hall]) {
|
|
const box = await locator.boundingBox()
|
|
expect(box).not.toBeNull()
|
|
expect(box!.x).toBeGreaterThanOrEqual(0)
|
|
expect(box!.y).toBeGreaterThanOrEqual(0)
|
|
expect(box!.x + box!.width).toBeLessThanOrEqual(390)
|
|
expect(box!.y + box!.height).toBeLessThanOrEqual(844)
|
|
}
|
|
|
|
const poiId = await facility.getAttribute('data-poi-id')
|
|
expect(poiId).toBeTruthy()
|
|
await page.evaluate(async ({ floorId: targetFloorId, targetPoiId }) => {
|
|
const api = (window as Window & { __GUIDE_3D_VISUAL_STABILITY__?: GuideDiagnostics })
|
|
.__GUIDE_3D_VISUAL_STABILITY__
|
|
if (!api) throw new Error('ThreeMap diagnostics unavailable')
|
|
const poi = (await api.getFloorPois(targetFloorId)).find((candidate) => candidate.poiId === targetPoiId)
|
|
if (!poi) throw new Error(`missing POI ${targetPoiId}`)
|
|
await api.focusTargetPoi({ ...poi, requestId: `poi-dom-label-${targetPoiId}` })
|
|
}, { floorId, targetPoiId: poiId! })
|
|
|
|
const focus = page.locator('[data-poi-label-kind="focus"][data-focus-label="active"]')
|
|
await expect(focus).toBeVisible({ timeout: 20_000 })
|
|
await expect(focus).toHaveCSS('pointer-events', 'none')
|
|
await expect(focus.locator('.three-poi-dom-label__title')).toHaveCSS('font-size', '16px')
|
|
await expect(focus.locator('.three-poi-dom-label__meta')).toHaveCSS('font-size', '13px')
|
|
await page.screenshot({ path: testInfo.outputPath(`poi-dom-labels-dpr-${deviceScaleFactor}-focus.png`) })
|
|
|
|
await page.evaluate(() => {
|
|
const api = (window as Window & { __GUIDE_3D_VISUAL_STABILITY__?: GuideDiagnostics })
|
|
.__GUIDE_3D_VISUAL_STABILITY__
|
|
api?.clearTargetFocus()
|
|
})
|
|
await expect(focus).toHaveCount(0)
|
|
await page.screenshot({ path: testInfo.outputPath(`poi-dom-labels-dpr-${deviceScaleFactor}-ambient.png`) })
|
|
})
|
|
})
|
|
}
|