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();
| Member | Purpose |
|---|---|
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, events | The 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.