Ramonda

Testing hooks

const { current, rerender, unmount } = renderHook(CounterHook, {
  initialProps: { start: 2 },
});

expect(current.count).toBe(2);

act(() => current.increment());
expect(current.count).toBe(3);

It really mounts a component

A hook can't stand alone — use() gives it its owner's runtime. So renderHook builds a throwaway host component and uses the hook on it, exercising the same machinery that ships.

current stays the same object

Unlike function-hook libraries, where each render returns a fresh value:

const first = result.current;
act(() => result.current.increment());
expect(result.current).toBe(first); // ✓ same object

A Ramonda hook is constructed once and lives as long as its owner — the instance is the identity, the fields are what change. Read a field for the current value.

rerender(props) drives the real path

rerender({ start: 99 });

A hook's props reach it through signals owned by the caller, updated when the caller re-renders — so passing new props here makes anything that reacts to one react exactly as it would under a real parent.

wrapper

For a hook that needs a provider above it:

renderHook(ThemedHook, { wrapper: ThemeShell });

Or test it through a component

Sometimes clearer, especially when the hook's job is to affect what its owner renders:

class Owner extends Component {
  counter = this.use(CounterHook, () => ({ start: 5 }));
  render() {
    return <p>{this.counter.count}</p>;
  }
}

const { instance, getByText } = render<Owner>(<Owner />);
act(() => instance.counter.increment());
expect(getByText("6")).toBeTruthy();

renderHook tests the hook's own behaviour; a component tests what the hook does to a render.

Next