86 lines
2.9 KiB
TypeScript
86 lines
2.9 KiB
TypeScript
/**
|
|
* 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)
|
|
})
|
|
})
|