@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
TypeScript
/**
* 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