v0 · Developer Preview Frond is under active development. APIs may change between releases.

Testing

Frond ships testing helpers in two subpaths: @frondruntime/core/testing for a headless harness, and @frondruntime/react/testing for a provider that wires one into a render.

import * as FrondTest from "@frondruntime/core/testing";
import * as FrondReactTest from "@frondruntime/react/testing";

The harness

createFrondTestHarness(options) builds a runtime, captures its events, and adds helpers for driving and reading nodes.

const harness = FrondTest.createFrondTestHarness();
await harness.start();

const profile = await harness.startNode(ProfileNode, { userId: "u_42" });
expect(profile.displayName).toBe("Ada");

await harness.teardown();
MemberPurpose
start() / stop() / teardown()Lifecycle. teardown is idempotent.
startNode(spec, args)Acquire and return the ready node instance.
startNodes(map)Acquire a keyed map of nodes.
node(spec, args)Get a handle without acquiring.
readReady(handle) / readError(handle)Read the current ready or error state.
waitForEvent(predicate)Resolve when a matching runtime event fires.
waitForNodeRead(handle, predicate)Resolve when a node’s read matches the predicate.
waitForIdle()Resolve when no work is in flight.
runtime, client, eventsThe underlying runtime, client, and captured event records.

For a runtime without the extra helpers, createTestRuntime(options) returns { runtime, client, sink, events }.

Stubbing dependencies

readySpec replaces a node with one that is instantly ready with a fixed result — no driver, no dependencies. mockSpec overrides a node’s dependencies or driver. Apply either with specOverrides, a list of { from, to }.

const ReadyDependency = FrondTest.readySpec(SessionNode, { userId: "u_42", token: "t" });

const ProfileWithStubSession = FrondTest.mockSpec(ProfileNode, {
  dependencies: Frond.dependencies(() => ({
    session: Frond.dep(ReadyDependency, Frond.Args.none),
  })),
});

const harness = FrondTest.createFrondTestHarness({
  specOverrides: [{ from: ProfileNode, to: ProfileWithStubSession }],
});

Requests for ProfileNode now resolve to the mocked spec, which depends on the ready stub instead of the real session. Tags and identity are preserved, so the rest of the graph is unaffected.

Controlling timing

createDeferredDriver gives a driver whose acquire and operations you resolve by hand — useful for asserting pending states before data arrives.

const driver = FrondTest.createDeferredDriver<string>({ release: true });
// resolve the pending acquire when the test is ready

React

TestFrondProvider wires a harness into a render tree. Pass a runtime, an existing harness, or options to have it create and tear down its own.

import { render } from "@testing-library/react";

render(
  <FrondReactTest.TestFrondProvider options={{ specOverrides }}>
    <ProfilePanel userId="u_42" />
  </FrondReactTest.TestFrondProvider>
);

When it owns the harness, it tears it down on unmount.


Back to the Model for the concepts, or Authoring to build a node.