test/
├── sockets/ # Transport layer tests
│ ├── socket.test.js # Pure Socket (base transport)
│ ├── dealer.test.js # Dealer socket (client transport)
│ ├── router.test.js # Router socket (server transport)
│ └── integration.test.js # Router-Dealer communication
└── README.md # This file
Tests the pure transport layer - message I/O and request/response tracking:
- ✅ ID generation and management
- ✅ Online/offline state transitions
- ✅ Config and options storage
- ✅ Message reception (TICK, REQUEST) → emits 'message' event
- ✅ Request/response tracking (Promise resolution)
- ✅ Request timeout handling
- ✅ Error response handling
- ✅ Message sending validation (online check)
Key Insight: Socket has NO business logic handlers - it's pure transport.
Tests the ZeroMQ Dealer wrapper (client-side transport):
- ✅ Constructor and state initialization
- ✅ Address management (set/get router address)
- ✅ State transitions (DISCONNECTED → CONNECTED)
- ✅ Message formatting for Dealer (no recipient routing)
- ✅ Request/tick envelope creation
- ✅ Disconnect and close operations
Key Insight: Dealer extends Socket, adds ZeroMQ Dealer specifics.
Tests the ZeroMQ Router wrapper (server-side transport):
- ✅ Constructor and state initialization
- ✅ Address management (set/get bind address)
- ✅ Bind/unbind operations
- ✅ Bind validation (no double-binding to different addresses)
- ✅ Message formatting for Router ([recipient, '', buffer])
- ✅ Request/tick envelope creation
- ✅ Close operations
Key Insight: Router extends Socket, adds ZeroMQ Router specifics + routing.
Tests actual Router-Dealer communication:
- ✅ Connection establishment (bind + connect)
- ✅ REQUEST/RESPONSE flow
- ✅ TICK (one-way) messaging
- ✅ Request timeout behavior
- ✅ ERROR response handling
- ✅ Multiple dealer connections
Key Insight: Verifies the complete message flow end-to-end.
# Run all tests
npm test
# Run specific test file
npm test -- test/sockets/socket.test.js
# Run with coverage
npm run test:coverage
# Watch mode
npm test -- --watch- Transport Layer Only - These tests focus on message I/O, not business logic
- State Management - Connection states, online/offline transitions
- Message Format - Proper envelope creation and routing
- Error Handling - Timeouts, connection failures, error responses
- ❌ Handler execution (that's protocol layer - Client/Server)
- ❌ Node orchestration (that's application layer)
- ❌ Pattern matching (that's business logic)
┌─────────────────────────────────────────┐
│ Transport Layer (Socket, Dealer, Router)│
│ - Pure message I/O │
│ - Request/response tracking │
│ - Connection management │
│ - NO business logic │
└─────────────────────────────────────────┘
// ✅ TRANSPORT (tested here)
- Listen for messages → emit('message', buffer)
- Send messages → sendBuffer(buffer)
- Track requests → requestBuffer() returns Promise
- Handle responses → resolve/reject Promise
// ❌ NOT Socket's job (protocol layer)
- Parse messages
- Execute handlers
- Route to handlers
- Business logic- Phase 1 ✅ - Transport tests (current)
- Phase 2 🔄 - Protocol tests (Client/Server with handlers)
- Phase 3 🔄 - Application tests (Node orchestration)
- Phase 4 🔄 - Integration tests (full stack)
We use a lightweight mock that:
- Implements async iterator for message reception
- Tracks sent messages
- Simulates incoming messages
- Provides event emitter for socket events
Why? Real ZeroMQ sockets require actual network connections, making tests slow and brittle.
const mockSocket = createMockZmqSocket()
// Simulate incoming message
mockSocket.simulateIncomingMessage(['', buffer])
// Check sent messages
expect(mockSocket.sentMessages).to.have.lengthOf(1)Integration tests use real ZeroMQ sockets to verify actual communication:
# Integration tests may take longer
npm test -- test/sockets/integration.test.jsWhen adding new transport features:
- Add unit tests to respective file
- Add integration test if it affects message flow
- Update this README with coverage information
- Ensure tests are isolated (no shared state)
- Clean up connections in
afterEach
describe('Feature', () => {
let socket
beforeEach(() => {
socket = new Socket({ ... })
})
afterEach(async () => {
if (socket.isOnline()) {
await socket.close()
}
})
it('should do something specific', () => {
// Arrange
// Act
// Assert
})
})it('should handle async operation', async () => {
const promise = socket.requestBuffer(buffer, 'recipient', 1000)
// Simulate response
setTimeout(() => {
mockSocket.simulateIncomingMessage(responseBuffer)
}, 10)
const result = await promise
expect(result).to.deep.equal(expected)
})# Run with verbose output
npm test -- --reporter spec
# Run single test
npm test -- --grep "should track pending requests"
# Debug mode
NODE_ENV=test node --inspect-brk node_modules/.bin/mocha test/**/*.test.js