import { test, expect } from '@playwright/test' import { imhotep } from 'imhotep-playwright' import { loadFixtureInPage, waitForFixtureReady } from './harness.js' async function fixtureUrl(category: string): Promise { const path = await loadFixtureInPage({ goto: async () => {} }, category) const { resolveFixturePage } = await import('./harness.js') return 'file://' + resolveFixturePage(category) } test.describe('E2E: Relations', () => { test('leftOf assertion verifies horizontal spatial ordering', async ({ page }) => { const ui = await imhotep(page) await page.goto(await fixtureUrl('relations')) await waitForFixtureReady(page) const leftData = await ui.extract('[data-testid="box-left"]') const rightData = await ui.extract('[data-testid="box-right"]') expect(Array.isArray(leftData)).toBe(true) expect(Array.isArray(rightData)).toBe(true) expect((leftData as any[]).length).toBe(1) expect((rightData as any[]).length).toBe(1) const leftRect = (leftData as any[])[0].rect const rightRect = (rightData as any[])[0].rect expect(leftRect.x + leftRect.width).toBeLessThanOrEqual(rightRect.x) expect(rightRect.x - (leftRect.x + leftRect.width)).toBeGreaterThanOrEqual(10) }) test('above assertion verifies vertical spatial ordering', async ({ page }) => { const ui = await imhotep(page) await page.goto(await fixtureUrl('relations')) await waitForFixtureReady(page) const topData = await ui.extract('[data-testid="box-top"]') const bottomData = await ui.extract('[data-testid="box-bottom"]') const topRect = (topData as any[])[0].rect const bottomRect = (bottomData as any[])[0].rect expect(topRect.y + topRect.height).toBeLessThanOrEqual(bottomRect.y) expect(bottomRect.y - (topRect.y + topRect.height)).toBeGreaterThanOrEqual(20) }) test('centeredWithin assertion verifies center alignment', async ({ page }) => { const ui = await imhotep(page) await page.goto(await fixtureUrl('relations')) await waitForFixtureReady(page) const containerData = await ui.extract('[data-testid="container"]') const centeredData = await ui.extract('[data-testid="centered"]') const containerRect = (containerData as any[])[0].rect const centeredRect = (centeredData as any[])[0].rect const containerCenterX = containerRect.x + containerRect.width / 2 const containerCenterY = containerRect.y + containerRect.height / 2 const centeredCenterX = centeredRect.x + centeredRect.width / 2 const centeredCenterY = centeredRect.y + centeredRect.height / 2 expect(centeredCenterX).toBeCloseTo(containerCenterX, 0) expect(centeredCenterY).toBeCloseTo(containerCenterY, 0) }) test('alignedWith centerY verifies vertical center alignment', async ({ page }) => { const ui = await imhotep(page) await page.goto(await fixtureUrl('relations')) await waitForFixtureReady(page) const refData = await ui.extract('[data-testid="align-center-ref"]') const subjectData = await ui.extract('[data-testid="align-center-subject"]') const refRect = (refData as any[])[0].rect const subjectRect = (subjectData as any[])[0].rect const refCenterY = refRect.y + refRect.height / 2 const subjectCenterY = subjectRect.y + subjectRect.height / 2 expect(subjectCenterY).toBeCloseTo(refCenterY, 0) }) test('atLeast wide verifies minimum width constraint', async ({ page }) => { const ui = await imhotep(page) await page.goto(await fixtureUrl('relations')) await waitForFixtureReady(page) const boxData = await ui.extract('[data-testid="box-left"]') const boxRect = (boxData as any[])[0].rect expect(boxRect.width).toBeGreaterThanOrEqual(44) }) test('failing leftOf assertion provides diagnostic geometry', async ({ page }) => { const ui = await imhotep(page) await page.goto(await fixtureUrl('relations')) await waitForFixtureReady(page) const rightData = await ui.extract('[data-testid="box-right"]') const leftData = await ui.extract('[data-testid="box-left"]') const rightRect = (rightData as any[])[0].rect const leftRect = (leftData as any[])[0].rect // Intentionally inverted: right item is NOT leftOf left item const isRightOfLeft = rightRect.x + rightRect.width <= leftRect.x expect(isRightOfLeft).toBe(false) // Diagnostic: capture the actual gap const actualGap = leftRect.x - (rightRect.x + rightRect.width) expect(actualGap).toBeLessThan(0) }) })