Binance MCP Server
by qeinfinity
- src
- __tests__
import { BinanceWebSocketManager } from '../connectors/binance-ws';
import WebSocket from 'ws';
import { StreamEventData, TradeData } from '../types/ws-stream';
jest.mock('ws');
type MockWebSocket = jest.Mocked<WebSocket> & {
readyState: number;
};
describe('BinanceWebSocketManager', () => {
let wsManager: BinanceWebSocketManager;
let mockWs: MockWebSocket;
beforeEach(() => {
wsManager = new BinanceWebSocketManager();
mockWs = {
readyState: WebSocket.CONNECTING,
on: jest.fn(),
once: jest.fn(),
emit: jest.fn(),
close: jest.fn(),
ping: jest.fn(),
send: jest.fn(),
terminate: jest.fn(),
removeListener: jest.fn(),
removeAllListeners: jest.fn(),
setMaxListeners: jest.fn(),
getMaxListeners: jest.fn(),
listeners: jest.fn(),
rawListeners: jest.fn(),
listenerCount: jest.fn(),
eventNames: jest.fn(),
addListener: jest.fn(),
off: jest.fn(),
prependListener: jest.fn(),
prependOnceListener: jest.fn(),
} as unknown as MockWebSocket;
(WebSocket as unknown as jest.Mock).mockImplementation(() => mockWs);
});
afterEach(() => {
wsManager.close();
jest.clearAllMocks();
});
it('should successfully subscribe to stream', () => {
const symbol = 'BTCUSDT';
const streams = ['trade', 'ticker'] as const;
wsManager.subscribe(symbol, 'spot', streams);
expect(WebSocket).toHaveBeenCalledWith(
expect.stringContaining(`btcusdt@trade/btcusdt@ticker`)
);
});
it('should handle incoming messages correctly', (done) => {
const symbol = 'BTCUSDT';
const mockData = {
stream: 'btcusdt@trade',
data: {
e: 'trade',
E: 123456789,
s: 'BTCUSDT',
p: '50000.00',
q: '1.0'
} as TradeData
};
wsManager.subscribe(symbol, 'spot', ['trade']);
wsManager.onStreamData(symbol, 'trade', (data: StreamEventData) => {
expect(data).toEqual(mockData.data);
done();
});
// Simulate receiving a message
mockWs.emit('message', JSON.stringify(mockData));
});
it('should handle reconnection on connection close', () => {
const symbol = 'BTCUSDT';
wsManager.subscribe(symbol, 'spot', ['trade']);
// Simulate connection close
mockWs.emit('close');
// Verify that a new connection attempt is made
expect(WebSocket).toHaveBeenCalledTimes(2);
});
it('should clean up resources on unsubscribe', () => {
const symbol = 'BTCUSDT';
wsManager.subscribe(symbol, 'spot', ['trade']);
wsManager.unsubscribe(symbol);
expect(mockWs.close).toHaveBeenCalled();
});
it('should handle multiple stream subscriptions', () => {
const symbol = 'BTCUSDT';
const streams = ['trade', 'ticker', 'bookTicker'] as const;
wsManager.subscribe(symbol, 'spot', streams);
expect(WebSocket).toHaveBeenCalledWith(
expect.stringContaining('btcusdt@trade/btcusdt@ticker/btcusdt@bookTicker')
);
});
it('should properly maintain connection state', () => {
const symbol = 'BTCUSDT';
wsManager.subscribe(symbol, 'spot', ['trade']);
// Update mockWs.readyState which is now properly typed
mockWs.readyState = WebSocket.OPEN;
mockWs.emit('open');
expect(wsManager.getConnectionState(symbol)).toBe(WebSocket.OPEN);
});
});