> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tappify.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# createTestClient

> Drives a vendor server the way Tappify does, so a route is tested without a running Tappify.

```ts theme={null}
function createTestClient(target, defaults?): TestClient;
```

Drives a vendor server the way Tappify does, so a route is tested without a
running Tappify.

## Parameters

### target

`TappifyHandlerOptions`

### defaults?

[`TestClientDefaults`](/extensions/reference/testing-api/Interface.TestClientDefaults) = `{}`

## Returns

[`TestClient`](/extensions/reference/testing-api/Interface.TestClient)

## Remarks

Pass the options object you hand `createTappifyHandler`, not the handler it
returns: the client rebuilds the handler around `testJwks` and signs each call
with a matching token. A built handler throws a `TapError` carrying
`TAP_TEST_TARGET_INVALID`, because it would verify against the live Tappify key
set and answer 401. Every call carries a fresh event id and the envelope Tappify
sends, and every call but `health` a signed token, so the handler reads the same
`install`, `context`, `credentials` and `documents` it will read in production. A route that
answers an error rejects with a `TapServerError` carrying the code, message and
status from the body, which is what a test asserts on; use `raw` when the status
itself is the assertion. Every method calls the unprefixed path — `/tappify/…` —
whatever `basePath` the options carry, so a `basePath` the handler strips off
something else is not exercised here, and one that is itself a prefix of
`/tappify`, such as `/tap`, makes every call 404 `TAP_ROUTE_UNKNOWN`. Reach a
prefixed path through `raw` when that is what you need to cover.

## Example

```ts theme={null}
import type { TappifyHandlerOptions } from '@tappify/extension-sdk/server';
import { createTestClient } from '@tappify/extension-sdk/testing';
import { expect, it } from 'vitest';

const handlerOptions: TappifyHandlerOptions = {
  extensionId: 'starter',
  health: () => ({ ok: true, version: '0.1.0' }),
};
const client = createTestClient(handlerOptions, { scopes: ['analytics:read'] });

it('answers the health check', async () => {
  await expect(client.health()).resolves.toEqual({ ok: true, version: '0.1.0' });
});
```
