Skip to main content
The SDK ships the bridge your component talks to and the host’s CSS variables, so a test renders what the host renders. Add the preset to your test setup and use renderWithTap.
Importing a preset sets the host theme variables on the document, registers the four matchers, and clears the mock’s portal after each test. Both need a DOM environment, because the theme goes on document.documentElement.

Rendering a component

It returns everything Testing Library returns, plus tap, mock and the queryClient it built. Every storage call needs storage:write, reads included. handler has to be built against the test key set — createTappifyHandler({ ...handlerOptions, jwks: await testJwks() }) — and extensionId has to name the same extension the handler does, because the mock signs the token it sends and the handler checks the audience on it.

The mock

createTapMock() builds the same bridge without a component, for a test that has no UI. Storage is an in-memory implementation of the collections you name, data queries answer from the sandbox fixtures the portal preview uses, and everything else the host would do is recorded: The mock drives the bridge from outside the component too:
setFilters takes a whole TapFilters; the filters option is the one that merges. setParams takes the shape the host builds, which is positional — pageId, path, and one key per segment.

Matchers

Each failure names what was expected and every call that was recorded. They take the mock itself, so expect(mock) rather than the component or tap.

Testing your server

createTestClient drives your handler the way Tappify does, with a signed token, so a procedure is tested without a running Tappify:
Hand it the options, not a built handler: a handler from createTappifyHandler verifies tokens against Tappify’s live key set, so every call would come back 401. The client rebuilds the handler around a test key set and signs against it. The client has one method per route — health, metrics, tool, mention, action, procedure, context, event, work — and raw(method, path, body) for the status codes. signTestToken() and testJwks() are there when you verify tokens yourself. Two validators read a response the way a reviewer would and return the list of what is wrong, so assert the list is empty: validateMetricsResponse(response, metrics) against your declared metric definitions, and validateToolResponse(value, returns) against the card shape a tool of that returns kind has to answer with.
tappify extension doctor runs your test script and counts a failing suite as a failed check.