@appport/testing
v1.2.5
Published
Transport conformance suite and test fixtures for AppPort.
Downloads
1,783
Readme
@appport/testing
The reference fixture application and the transport conformance suite.
import { createTestApplication, describeTransport } from "@appport/testing";
import { createInProcessTransport } from "@appport/transport-inprocess";
describeTransport("in-process", async ({ sessionId }) => {
const fixture = createTestApplication();
return {
transport: createInProcessTransport({
server: fixture.server,
identity: await fixture.server.identify({ transport: "inprocess", sessionId })
}),
fixture,
teardown: () => fixture.server.close()
};
});Every transport runs the same 21 tests through the same client against the same capabilities: connect and reconnect, request and response, request-id echo, manifest discovery, capability versions, unknown capability, unsupported version, invalid input, application errors, authorization, sanitization, timeouts, concurrency, idempotent replay, events and unsubscribe, streams and cancellation, protocol mismatch, malformed envelopes and malformed carrier data.
Optional sendRaw and sendRawText hooks let a harness inject envelopes the
client would never produce, so protocol-level failures are tested too.
The fixture application is deliberately small and deliberately complete: a request capability, a versioned capability, an event, a stream, a capability that times out and one that fails.
Store conformance
AppPort ships memory stores only and depends on no database. An application that
keeps idempotency records or sessions in its own storage checks the store against
the contract the runtime relies on (IdempotencyStore and SessionStore in
@appport/core, documented on the interfaces):
import { runIdempotencyStoreConformance, runSessionStoreConformance } from "@appport/testing";
runIdempotencyStoreConformance(() => myDurableIdempotencyStore, { name: "durable", requireClaims: true, requireFindByRequestId: true });
runSessionStoreConformance(() => myDurableSessionStore, { name: "durable" });The idempotency suite checks record round-trips and expiry; with claim/release,
that claim is an atomic create-if-absent (one winner among concurrent claims),
that get never returns a claim, that set replaces a claim and release
removes only the holder's unresolved claim; and findByRequestId when present.
requireClaims turns a missing claim/release into a failure instead of
skipped tests. Every test uses fresh random keys, so a shared database works;
cleanup runs after each test.
