Test against the seam
Drive the real services with in-memory fakes, render UI against a recording transport, and check your own implementations with the conformance runners.
domainkit/testing exists so host tests never stub global fetch. Every fake is a real
implementation of a seam the lifecycle already goes through, so the code under test is the code that
ships.
A fake provider
/**
* A provider definition over in-memory zones, with a token method and optionally OAuth. Give each
* test its own zone: `Testing.provider` registers zones in one process-wide table that
* `Testing.resolver` reads.
*/
export const fake = Testing.provider({
zones: ["plans.example.com"],
records: [
{
zone: "plans.example.com",
record: DnsRecord.txt({ name: "_acme.plans.example.com", value: "acme-verify=7f3a" }),
},
],
oauth: true,
});Seed records to produce Noop and Conflict operations, set failWrite to exercise a partial
receipt, and set oauth to add the interactive method beside the token one.
/** Exercise a partial receipt by failing one write, and a mismatch by seeding the wrong record. */
export const failsTheSecondWrite = Testing.provider({
zones: ["partial.example.com"],
failWrite: (index) => index === 1,
});One layer for the lifecycle
/** One layer for the whole lifecycle: memory Storage, a throwaway custody key, and the fake pool. */
export const TestLive = DomainKit.layerMemory({
providers: [fake],
resolver: Testing.resolver(),
});/** A host test drives the real services; nothing stubs global `fetch`. */
export const plansTheSecondRecord = Effect.gen(function* () {
yield* Connect.start({
provider: fake.id,
method: Connect.Method.token("test-token"),
domain: "app.plans.example.com",
});
const plan = yield* Provision.plan({
domain: "app.plans.example.com",
requirements: [
DnsRecord.cname({ name: "app.plans.example.com", target: "edge.acme.dev" }),
DnsRecord.txt({ name: "_acme.plans.example.com", value: "acme-verify=7f3a" }),
],
});
return plan.operations.map((operation) => operation._tag); // ["Create", "Noop"]
}).pipe(Effect.provideService(Principal.Service, Testing.principal), Effect.provide(TestLive));DomainKit.layerMemory adds Storage.layerMemory and a throwaway custody key, so a test needs no
database and no key material.
Public DNS answers
/** Answer public DNS from a table instead of the fake provider's own zones. */
export const StaleResolver = Testing.resolver([
{
name: "app.example.com",
records: [DnsRecord.cname({ name: "app.example.com", target: "old.acme.dev" })],
},
]);
export const seesTheOldTarget = Verify.observe({ domain: "app.example.com" });Passing a table replaces the fake providers’ zones entirely, which is how you test a requirement that is satisfied at the provider and still missing in public DNS.
UI tests
/**
* The whole lifecycle behind a `Transport.Interface`, over an in-memory server, recording every
* call. Declare fewer capabilities to render a UI against a host that mounted only part of the
* group.
*/
export const transport = Testing.transport({ capabilities: ["connection", "provisioning"] });
export const callsSoFar = () => transport.calls.map((call) => call.method);Testing.transport mounts domainkit/server over memory storage and a fake provider, then points
Transport.fromFetch at that handler. Rendering <DomainKit.Root transport={transport}> gives a
component tree that connects, plans, approves, applies, observes, and cleans up for real.
transport.calls records { method, input } for every call, so a test can assert that approving
sent the operation ids the customer selected. Declaring fewer capabilities renders the UI against a
host that mounted only part of the route group.
Conformance
/**
* Register every `Storage` invariant with your test runner: tenant isolation, apply leases,
* exactly-once continuations, revocation recovery, and lock semantics. Both shipped
* implementations pass this suite, so a host can swap them without a behaviour change.
*/
export const registerStorageCases = (
layer: Layer.Layer<Storage.Service, unknown>,
it: (name: string, run: () => Promise<void>) => void,
) => Testing.conformance.storage(layer, { it });/**
* A provider author runs this against a real account before shipping: create and read back, exact
* no-op, conflict, stale plan, and partial apply, all through the same services hosts use. Every
* record it creates carries the prefix and is removed again.
*/
export const check = (definition: Provider.Definition, token: string, zone: string) =>
Testing.conformance.provider(
definition,
{ secret: Redacted.make(token), context: { apiKey: token } },
zone,
{ prefix: "acme-conformance" },
);
export const run = (definition: Provider.Definition, token: string) =>
Effect.runPromise(check(definition, token, "example.com"));The storage runner takes a layer and registers one case per invariant with your test runner. The provider runner writes to a real account and cleans up after itself, so it belongs in an opt-in suite rather than in CI.
The domainkit/testing reference lists every fake and its options.