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

140 lines 6.97 kB
/** * Client-Server Contract Tests * * Tests client-server transport behaviors that apply to any transport implementation * that supports bidirectional communication, multiple clients, and broadcasting. * * These tests verify the interaction between client and server transport instances, * including connection management, message broadcasting, and resource cleanup. */ import { Effect, Stream, Scope } from 'effect'; import type { TransportMessage, ConnectionState } from '@codeforbreakfast/eventsourcing-transport'; /** * Factory for creating paired client-server transports. * Each call creates a new pair that can communicate with each other. */ export interface TransportPair { readonly makeServer: () => Effect.Effect<ServerTransport, Error, Scope.Scope>; readonly makeClient: () => Effect.Effect<ClientTransport, Error, Scope.Scope>; } /** * Context for testing client-server transport implementations. * Provides factory methods for creating transport pairs and test utilities. */ export interface ClientServerTestContext { readonly makeTransportPair: () => TransportPair; readonly waitForConnectionState: (transport: ClientTransport, expectedState: ConnectionState, timeoutMs?: number) => Effect.Effect<void, Error, never>; readonly collectMessages: <T>(stream: Stream.Stream<T, never, never>, count: number, timeoutMs?: number) => Effect.Effect<T[], Error, never>; readonly makeTestMessage: (type: string, payload: unknown) => TransportMessage; } /** * Server transport interface for testing */ export interface ServerTransport { readonly connections: Stream.Stream<ServerConnection, never, never>; readonly broadcast: (message: TransportMessage) => Effect.Effect<void, Error, never>; } /** * Individual server connection representing a connected client */ export interface ServerConnection { readonly id: string; readonly transport: ClientTransport; } /** * Client transport interface for testing */ export interface ClientTransport { 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>; } export type ClientServerTestRunner = (name: string, setup: () => Effect.Effect<ClientServerTestContext>) => void; /** * Core client-server contract tests. * * This is the primary export for testing bidirectional communication between client and server * transport instances. These tests verify the interaction patterns, connection management, * and message flow between paired transport endpoints. * * ## What This Tests * * - **Connection Management**: Establishing client-server connections, handling multiple clients * connecting to the same server, and proper connection lifecycle management * - **Message Communication**: Client-to-server message publishing, server-to-client broadcasting, * bidirectional request-response patterns, and message filtering on the client side * - **Connection Lifecycle**: Graceful client disconnection, server shutdown handling, * resource cleanup when scopes close, and connection state synchronization * - **Error Handling**: Managing malformed messages, connection errors, and ensuring * graceful degradation during communication failures * * ## Real Usage Examples * * **WebSocket Integration:** * See `/packages/eventsourcing-transport-websocket/src/tests/integration/client-server.test.ts` (lines 38-95) * - Shows `TransportPair` implementation with random port allocation * - Demonstrates real WebSocket server/client coordination * - Includes proper error mapping and connection state management * - Line 116: `runClientServerContractTests('WebSocket', createWebSocketTestContext)` * * **InMemory Integration:** * See `/packages/eventsourcing-transport-inmemory/src/tests/integration/client-server.test.ts` (lines 37-104) * - Shows shared server instance pattern for synchronized testing * - Demonstrates direct connection without network protocols * - Line 126: `runClientServerContractTests('InMemory', createInMemoryTestContext)` * * Both implementations include transport-specific tests alongside the standard contracts. * * ## Required Interface * * Your setup function must return a `ClientServerTestContext` that provides: * - `makeTransportPair`: Factory that creates paired client/server transports that can communicate * - `waitForConnectionState`: Utility to wait for specific connection states * - `collectMessages`: Utility to collect messages from streams with timeout * - `makeTestMessage`: Factory for creating standardized test messages * * ## Test Categories * * 1. **Connection Management**: Tests client-server connection establishment and multi-client scenarios * 2. **Message Communication**: Tests all forms of client-server communication patterns * 3. **Connection Lifecycle**: Tests graceful shutdown and cleanup scenarios * 4. **Error Handling**: Tests resilience to malformed messages and connection errors * * ## Transport Pair Requirements * * Your `makeTransportPair` function must return an object with: * - `makeServer`: Creates a server transport within a scope * - `makeClient`: Creates a client transport that connects to the server within a scope * * Both server and client must be automatically cleaned up when their respective scopes close. * * ## Server Interface Requirements * * Your server implementation must provide: * - `connections`: Stream that emits server-side connection objects when clients connect * - `broadcast`: Function to send messages to all connected clients * * ## Client Interface Requirements * * Your client implementation must provide: * - `connectionState`: Stream that emits connection state changes * - `publish`: Function to send messages to the server * - `subscribe`: Function to subscribe to messages from the server (with optional filtering) * * ## Connection Object Requirements * * Server connection objects must provide: * - `id`: Unique identifier for the connection * - `transport`: Client transport interface for server-side communication * * @param name - Descriptive name for your transport integration (e.g., "WebSocket Integration") * @param setup - Function that returns Effect yielding ClientServerTestContext for your paired transports * * @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 client-server transport implementations passing all contract tests. */ export declare const runClientServerContractTests: ClientServerTestRunner; //# sourceMappingURL=client-server-contract-tests.d.ts.map