UNPKG

@codeforbreakfast/eventsourcing-testing-contracts

Version:

Comprehensive testing utilities for event sourcing implementations - Test contracts for transport and protocol implementations with mock utilities and test data generators

131 lines 6.96 kB
/** * Server Contract Tests * * Tests server-only transport behaviors that apply to any transport implementation * that supports multiple client connections, broadcasting, and server-side resource management. * * These tests verify server-specific behaviors like connection tracking, broadcasting to multiple clients, * and proper cleanup when clients disconnect or server shuts down. */ import { Effect, Stream, Scope } from 'effect'; import type { TransportMessage, ConnectionState } from '@codeforbreakfast/eventsourcing-transport'; /** * Factory for creating server transports and mock clients for testing */ export interface ServerTestFactory { readonly makeServer: () => Effect.Effect<ServerTransportTest, Error, Scope.Scope>; readonly makeMockClient: () => Effect.Effect<MockClientTransport, Error, Scope.Scope>; } /** * Context for testing server transport implementations. * Provides factory methods for creating servers and mock clients for testing. */ export interface ServerTestContext { readonly makeServerFactory: () => ServerTestFactory; readonly waitForConnectionCount: (server: ServerTransportTest, expectedCount: number, timeoutMs?: number) => Effect.Effect<void, Error, never>; readonly collectConnections: (stream: Stream.Stream<ServerConnectionTest, never, never>, count: number, timeoutMs?: number) => Effect.Effect<ServerConnectionTest[], Error, never>; readonly makeTestMessage: (type: string, payload: unknown) => TransportMessage; } /** * Server transport interface for testing */ export interface ServerTransportTest { readonly connections: Stream.Stream<ServerConnectionTest, never, never>; readonly broadcast: (message: TransportMessage) => Effect.Effect<void, Error, never>; readonly connectionCount: () => Effect.Effect<number, never, never>; } /** * Individual server connection representing a connected client */ export interface ServerConnectionTest { readonly id: string; readonly connectionState: Stream.Stream<ConnectionState, never, never>; readonly publish: (message: TransportMessage) => Effect.Effect<void, Error, never>; readonly subscribe: (filter?: (msg: TransportMessage) => boolean) => Effect.Effect<Stream.Stream<TransportMessage, never, never>, Error, never>; } /** * Mock client transport for testing server behaviors */ export interface MockClientTransport { readonly connectionState: Stream.Stream<ConnectionState, never, never>; readonly publish: (message: TransportMessage) => Effect.Effect<void, Error, never>; readonly subscribe: (filter?: (msg: TransportMessage) => boolean) => Effect.Effect<Stream.Stream<TransportMessage, never, never>, Error, never>; readonly disconnect: () => Effect.Effect<void, Error, never>; } export type ServerTestRunner = (name: string, setup: () => Effect.Effect<ServerTestContext>) => void; /** * Core server transport contract tests. * * This is the primary export for testing server-side transport implementations that support * multiple client connections, broadcasting, and server-side resource management. * Every server transport must pass these tests to ensure proper multi-client behavior. * * ## What This Tests * * - **Connection Management**: Tracking multiple client connections, unique connection IDs, * connection counting, and automatic cleanup when clients disconnect * - **Message Broadcasting**: Sending messages to all connected clients simultaneously, * ensuring disconnected clients don't receive messages, and handling broadcast errors gracefully * - **Individual Connection Communication**: Direct communication with specific client connections, * receiving messages from individual clients, and per-connection message filtering * - **Resource Management**: Proper cleanup when server shuts down, handling concurrent * operations during shutdown, and connection lifecycle tracking * * ## Real Usage Examples * * **WebSocket Server Implementation:** * See `/packages/eventsourcing-transport-websocket/src/tests/integration/client-server.test.ts` (lines 45-74) * - Uses `WebSocketAcceptor.make({ port, host })` with random port allocation * - Shows proper server startup with scope-based cleanup * - Demonstrates connection stream mapping to client transport interface * * **InMemory Server Implementation:** * See `/packages/eventsourcing-transport-inmemory/src/tests/integration/client-server.test.ts` (lines 44-78) * - Uses `InMemoryAcceptor.make()` for direct in-memory connections * - Shows shared server instance pattern for coordinated client-server testing * - Demonstrates server lifecycle management without network concerns * * Note: These implementations focus on client-server integration tests. * Server-only contract tests would need dedicated server test implementations. * * ## Required Interface * * Your server setup function must return a `ServerTestContext` that provides: * - `makeServerFactory`: Factory that creates server and mock client instances * - `waitForConnectionCount`: Utility to wait for expected number of connections * - `collectConnections`: Utility to collect connections from the server's connection stream * - `makeTestMessage`: Factory for creating test messages * * ## Test Categories * * 1. **Connection Management**: Tests tracking multiple clients, connection counting, and cleanup * 2. **Message Broadcasting**: Tests server-to-all-clients communication and error handling * 3. **Individual Connection Communication**: Tests per-client communication and message filtering * 4. **Resource Management**: Tests proper cleanup during server shutdown and client disconnection * * ## Server Interface Requirements * * Your server implementation must provide: * - `connections`: Stream of connected clients (emits when clients connect) * - `broadcast`: Function to send messages to all connected clients * - `connectionCount`: Function to get current number of connected clients * * ## Mock Client Requirements * * Your mock client factory must create clients that: * - Connect to the server automatically when created within a scope * - Expose connection state as a stream * - Support publishing and subscribing to messages * - Disconnect cleanly when their scope closes * * @param name - Descriptive name for your server transport implementation (e.g., "WebSocket Server") * @param setup - Function that returns Effect yielding ServerTestContext for your server transport * * @example * For complete working examples, see: * - WebSocket: `/packages/eventsourcing-transport-websocket/src/tests/integration/client-server.test.ts` * - InMemory: `/packages/eventsourcing-transport-inmemory/src/tests/integration/client-server.test.ts` * Both demonstrate real server implementations and client-server coordination. */ export declare const runServerTransportContractTests: ServerTestRunner; //# sourceMappingURL=server-transport-contract-tests.d.ts.map