Files
Imhotep/packages/imhotep-fixtures/src/e2e-property-enumerated.test.ts
T

110 lines
3.8 KiB
TypeScript

import { test, expect } from '@playwright/test'
import { imhotepFixture } from 'imhotep-playwright'
import { enumeratedDomain } from 'imhotep-core/property-contracts'
import { resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
const __dirname = fileURLToPath(new URL('.', import.meta.url))
function fixtureUrl(name: string): string {
return 'file://' + resolve(__dirname, 'pages', `${name}.html`)
}
test.describe('E2E: Fixture enumerated property run', () => {
test('exhaustively evaluates all size combinations and stops on failure', async ({ page }) => {
const handle = imhotepFixture(fixtureUrl('property-enumerated'))
const domain = enumeratedDomain([
{ size: 'sm', label: 'Small' },
{ size: 'md', label: 'Medium' },
{ size: 'lg', label: 'Large' },
])
let evaluatedCases = 0
const result = await handle.exhaustivelyForAllInputs(
page,
domain,
async (scene, ctx) => {
evaluatedCases++
const data = await scene.extract('[data-testid="enumerated-button"]')
expect(Array.isArray(data)).toBe(true)
expect((data as any[]).length).toBe(1)
const box = (data as any[])[0].rect as { width: number; height: number }
const input = ctx.input as { size: string; label: string }
// Assert button width changes with size
if (input.size === 'sm') {
expect(box.width).toBeGreaterThanOrEqual(60)
expect(box.width).toBeLessThan(80)
} else if (input.size === 'md') {
expect(box.width).toBeGreaterThanOrEqual(80)
expect(box.width).toBeLessThan(100)
} else if (input.size === 'lg') {
expect(box.width).toBeGreaterThanOrEqual(100)
}
}
)
expect(result.passed).toBe(true)
expect(result.mode).toBe('enumerated-determinate')
expect(result.totalCases).toBe(3)
expect(evaluatedCases).toBe(3)
expect(result.diagnostics).toHaveLength(0)
})
test('failing case stops with diagnostics', async ({ page }) => {
const handle = imhotepFixture(fixtureUrl('property-enumerated'))
const domain = enumeratedDomain([
{ size: 'sm', label: 'A' },
{ size: 'md', label: 'B' },
{ size: 'lg', label: 'C' },
])
let evaluatedCases = 0
const result = await handle.exhaustivelyForAllInputs(
page,
domain,
async (scene, ctx) => {
evaluatedCases++
const input = ctx.input as { size: string }
// Force a failure on the md case
if (input.size === 'md') {
throw new Error('Intentional failure for testing diagnostics')
}
const data = await scene.extract('[data-testid="enumerated-button"]')
expect((data as any[]).length).toBe(1)
}
)
expect(result.passed).toBe(false)
expect(result.mode).toBe('enumerated-determinate')
// Should have stopped at the failing case (md is second)
expect(evaluatedCases).toBe(2)
expect(result.failingCase).toEqual({ size: 'md', label: 'B' })
expect(result.diagnostics.length).toBeGreaterThan(0)
expect((result.diagnostics[0] as any).code).toBe('IMH_ENUMERATED_RUN_ERROR')
})
test('deterministic order with no randomness', async ({ page }) => {
const handle = imhotepFixture(fixtureUrl('property-enumerated'))
const domain = enumeratedDomain([
{ size: 'sm' },
{ size: 'md' },
{ size: 'lg' },
])
const order1: string[] = []
await handle.exhaustivelyForAllInputs(page, domain, async (_scene, ctx) => {
order1.push((ctx.input as { size: string }).size)
})
const order2: string[] = []
await handle.exhaustivelyForAllInputs(page, domain, async (_scene, ctx) => {
order2.push((ctx.input as { size: string }).size)
})
expect(order1).toEqual(['sm', 'md', 'lg'])
expect(order2).toEqual(['sm', 'md', 'lg'])
})
})