/** * Playwright determinism proof tests. * * Verifies that the public API honours seed and deterministic options, * and that execution context propagates correctly through the UI handle. */ import { describe, it } from 'node:test' import assert from 'node:assert' import { createDeterministicContext, createVolatileContext } from 'imhotep-core' import type { ExecutionContext } from 'imhotep-core' // We cannot import `imhotep` directly here because it requires a real // Playwright page. Instead we test the context factory logic in isolation. // Full integration tests belong in the fixtures e2e suite. describe('Playwright determinism', () => { it('createDeterministicContext with same seed produces identical rng', () => { const ctx1 = createDeterministicContext(99) const ctx2 = createDeterministicContext(99) assert.deepStrictEqual( [ctx1.rng(), ctx1.rng(), ctx1.rng()], [ctx2.rng(), ctx2.rng(), ctx2.rng()], ) }) it('createDeterministicContext produces stable ids', () => { const ctx = createDeterministicContext(7) assert.strictEqual(ctx.idGenerator(), 'id-1') assert.strictEqual(ctx.idGenerator(), 'id-2') assert.strictEqual(ctx.idGenerator(), 'id-3') }) it('createDeterministicContext clock is stable', () => { const ctx = createDeterministicContext(7) assert.strictEqual(ctx.clock(), 0) assert.strictEqual(ctx.clock(), 0) }) it('createVolatileContext clock advances', () => { const ctx = createVolatileContext() const t1 = ctx.clock() const t2 = ctx.clock() assert.ok(t2 >= t1) }) it('parallel contexts with same seed produce identical sequences', () => { const ctxA = createDeterministicContext(1) const ctxB = createDeterministicContext(1) assert.deepStrictEqual( [ctxA.rng(), ctxA.rng()], [ctxB.rng(), ctxB.rng()], 'same seed must yield same rng sequence', ) }) it('parallel contexts with different seeds do not interfere', () => { const ctxA = createDeterministicContext(1) const ctxB = createDeterministicContext(2) const idsA = [ctxA.idGenerator(), ctxA.idGenerator()] const idsB = [ctxB.idGenerator(), ctxB.idGenerator()] assert.deepStrictEqual(idsA, ['id-1', 'id-2']) assert.deepStrictEqual(idsB, ['id-1', 'id-2']) assert.notDeepStrictEqual( [ctxA.rng(), ctxA.rng()], [ctxB.rng(), ctxB.rng()], 'different seeds must yield different rng sequences', ) }) it('property runner seeds are stored in replay metadata', () => { // This is a contract test: replay metadata must carry the seed. const meta = { version: 1 as const, seed: 42, numRuns: 100, sceneTarget: { kind: 'fixture' as const, fixtureId: 'test.html' }, inputDomain: { mode: 'generated' as const, arbitrary: 'record' }, timestamp: new Date().toISOString(), } assert.strictEqual(meta.seed, 42) assert.strictEqual(meta.numRuns, 100) }) })