---
title: domainkit/testing
description: The fakes, the recording transport, and the conformance runners that let host tests drive the real services instead of stubbing global fetch.
sidebar:
  label: domainkit/testing
seo:
  title: DomainKit testing reference
---

```ts
import { Testing } from "domainkit/testing";
```

{/* reference-inventory:start */}

| Namespace | Carries                                                                                   |
| --------- | ----------------------------------------------------------------------------------------- |
| `Testing` | `provider`, `resolver`, `storage`, `principal`, `transport`, `fakeRecords`, `conformance` |
| `VERSION` | The installed package version, so a test can assert what it is running against            |

{/* reference-inventory:end */}

## Fakes

| Value                 | Gives                                                                           |
| --------------------- | ------------------------------------------------------------------------------- |
| `Testing.provider`    | A provider definition with a token method, optional OAuth, over in-memory zones |
| `Testing.resolver`    | A `Resolver` answering from those zones, or from a table you pass               |
| `Testing.storage`     | `Storage.layerMemory`, re-exported here for discoverability                     |
| `Testing.principal`   | A fixed `{ ownerId, actorId }` for tests that do not care which tenant          |
| `Testing.transport`   | The whole lifecycle behind a `Transport.Interface`, recording every call        |
| `Testing.fakeRecords` | What the fake providers currently hold for a name                               |

<Snippet file="examples/testing/fakes.ts" region="provider" title="A fake provider" />

### Options

| Option               | Effect                                                                                                           |
| -------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `id`                 | The provider id. Default `fake`                                                                                  |
| `name`               | The name a customer reads. Default `Fake <id>`                                                                   |
| `zones`              | Zones the fake credential reaches. Default `example.com`                                                         |
| `labels`             | The label each zone carries, keyed by zone. Default: the zone name                                               |
| `accountLabel`       | What the fake calls the account it issues credentials for. Default: none, so the label is null                   |
| `records`            | Pre-existing records, to produce `Noop` and `Conflict` operations                                                |
| `oauth`              | Offer OAuth beside the token method; the fake redirects to `callbackUrl` immediately                             |
| `failWrite`          | A predicate over the zero-based write index; a write fails when it returns `true`, to exercise a partial receipt |
| `nameservers`        | Nameservers per zone, which `Testing.resolver` answers NS queries from                                           |
| `nameserverSuffixes` | Suffixes the fake declares as `Definition.nameservers`, so `Connect.discover` names it as a host                 |

:::caution
`Testing.provider` registers its zones in one table shared by the whole process, and
`Testing.resolver()` answers from that table. Give each test its own zone, or a record another test
applied will answer a public DNS query here.
:::

## The recording transport

<Snippet file="examples/testing/fakes.ts" region="transport" title="A transport for UI tests" />

`Testing.transport` mounts `domainkit/server` over memory storage and a fake provider, then wraps
`Transport.fromFetch` around that handler. `calls` holds `{ method, input }` for every call, oldest
first, where `method` reads `connection.inspect`, `provisioning.approve`, and so on. There is
nothing to dispose.

## Conformance

| Runner                         | Checks                                                                                                                        |
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- |
| `Testing.conformance.storage`  | Tenant isolation and the one deliberate exception to it, apply leases, exactly-once continuations, revocation recovery, locks |
| `Testing.conformance.provider` | Create and read back, exact no-op, conflict, stale plan, partial apply, cleanup, rejected token                               |

<Snippet file="examples/testing/conformance.ts" region="storage" title="Storage conformance" />

<Snippet file="examples/testing/conformance.ts" region="provider" title="Provider conformance" />

The provider runner writes to a real account. Every record it creates carries the `prefix` and is
removed again, so point it at a zone you own and can inspect.

The `rejected-token` case authenticates with every required token field set to an empty secret and
expects `Unauthenticated`. A token method with a required non-secret field, such as a region
selector, needs `rejectedToken`: the values the provider rejects, keyed by field name.
