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 getFloorPois: (floorId: string) => Promise focusTargetPoi: (request: PoiCandidate & { requestId: string }) => Promise 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`) }) }) }) }