Accessibility and testing

Deterministic replay testing

Record normalized lifecycle events, replay them through a ManualClock, and assert announcement or diagnostic transcripts with optional Vitest matchers.

Install the test helpers

Install @generative-a11y/test beside core in the test workspace. The package needs no browser and its root entry does not import Vitest.

shell
npm install --save-dev @generative-a11y/test

How this code works

  1. 01
    Keep fixtures local

    Replay files contain normalized application events and should follow the repository rules for test data.

  2. 02
    Add Vitest only when used

    Import the optional matcher entry from @generative-a11y/test/vitest.

Record and replay normalized events

recordRuntime captures only events sent through the dispatch target it returns. Fixtures use a versioned JSON envelope, relative timestamps, and array order for events with the same time.

typescript
import { ManualClock, createGenerativeA11y } from "@generative-a11y/core";
import { recordRuntime, replayEvents } from "@generative-a11y/test";

const clock = new ManualClock(0);
const runtime = createGenerativeA11y({ clock });
const recording = recordRuntime({ runtime, clock });
recording.runtime.dispatch({
  type: "response.started",
  responseId: "report",
});
const fixture = recording.fixture();

const replayClock = new ManualClock(fixture.startAt);
const replayRuntime = createGenerativeA11y({ clock: replayClock });
replayEvents(replayRuntime, replayClock, fixture);
replayClock.runUntilIdle();

runtime.dispose();
replayRuntime.dispose();

How this code works

  1. 01
    Wrap the dispatch target

    Send the same normalized events used by the application through recording.runtime.

  2. 02
    Create a fixture

    fixture returns a frozen V1 envelope with non-negative relative times.

  3. 03
    Replay with controlled time

    replayEvents advances ManualClock to each event and dispatches it in recorded order.

  4. 04
    Settle only when intended

    Call runUntilIdle when the test needs final delayed output rather than intermediate state.

Use semantic Vitest matchers

installVitestMatchers adds transcript, announcement, and diagnostic assertions. Expected objects use semantic partial fields, which keeps tests focused on the behavior under review.

  • toHaveAnnouncementTranscript checks ordered output
  • toHaveAnnounced checks that one matching intent exists
  • toHaveDiagnostic checks a matching runtime decision

Keep the evidence boundary clear

Replay proves that normalized events produce repeatable runtime output under a controlled clock. It does not prove browser delivery or screen-reader speech. Keep browser fixtures and hands-on assistive-technology tests as separate release evidence.