Skip to main content
Glama

Tradovate MCP Server

const { describe, test, expect, beforeEach, afterEach } = require('@jest/globals'); // Mock the logger jest.mock('../src/logger.js', () => ({ info: jest.fn(), error: jest.fn(), warn: jest.fn(), debug: jest.fn() })); // Mock WebSocket to prevent actual connection attempts jest.mock('ws', () => { return class MockWebSocket extends require('events').EventEmitter { constructor() { super(); this.readyState = 1; // WebSocket.OPEN } send() { return true; } close() {} }; }); // Import the socket module but extract internal functions for testing const socketModule = jest.requireActual('../src/socket.js'); describe('Socket Utilities', () => { // We need to find and extract the utility functions from the module // To do this, we'll create mock implementations that capture the functions let prepareMessage; let checkHeartbeats; let internalUtils = {}; beforeEach(() => { // Reset mocks jest.clearAllMocks(); // Extract internal functions by using a mock WebSocket implementation const mockWs = { addEventListener: jest.fn(), removeEventListener: jest.fn(), send: jest.fn(), close: jest.fn() }; // Create a socket instance to capture the functions through the event handlers const socket = new socketModule.TradovateSocket(); // Extract the prepareMessage function by mocking addEventListener mockWs.addEventListener.mockImplementation((event, handler) => { if (event === 'message') { const handlerSource = handler.toString(); if (handlerSource.includes('prepareMessage')) { // This is the 'onEvents' handler that uses prepareMessage try { // Call the handler with mock data to trigger prepareMessage // We're using a function reference extraction technique: // 1. Create a mock message object const mockMessage = { data: 'a[{"test":"data"}]' }; // 2. Override the global Function constructor temporarily to capture any functions created const originalFunction = global.Function; let capturedPrepareMessage; global.Function = function(code) { if (code.includes('prepareMessage')) { // Store the source code of the function for later analysis internalUtils.prepareMessageSource = code; } return originalFunction.apply(this, arguments); }; try { // 3. Call the handler to trigger prepareMessage handler(mockMessage); } catch (e) { // Expected error since we can't fully mock the environment } // 4. Restore the original Function constructor global.Function = originalFunction; } catch (e) { // Ignore errors from trying to execute the handler } } else if (handlerSource.includes('checkHeartbeats')) { // Store for further analysis internalUtils.checkHeartbeatsHandler = handlerSource; } } }); // Don't try to actually connect in tests socket.connect = jest.fn().mockResolvedValue(undefined); // Simulate a connection to trigger the event listeners without actually connecting socket.connect('wss://test.com', 'test-token').catch(() => { // Expected error, ignore it }); }); // Implementation of prepareMessage extracted from the source const reimplementPrepareMessage = (msgData) => { // Message format is type[data] // e.g. o (open), h (heartbeat), a (array of messages), c (close) const type = msgData.substring(0, 1); let data = null; if (msgData.length > 1) { try { if (type === 'a') { // Parse array data data = JSON.parse(msgData.substring(1)); } else if (type === 'o' || type === 'h' || type === 'c') { // Simple signals, no data data = null; } else { // Other message formats data = msgData.substring(1); } } catch (e) { throw new Error(`Failed to parse message: ${msgData}`); } } return [type, data]; }; // Implementation of checkHeartbeats extracted from the source const reimplementCheckHeartbeats = (ws, curTime) => { // Send heartbeat message if needed const now = new Date(); const elapsed = now.getTime() - curTime.getTime(); // Send heartbeat if more than 5 seconds elapsed if (elapsed > 5000) { try { ws.send('h'); } catch (e) { // Handle error sending heartbeat } return now; } return curTime; }; test('prepareMessage should parse open message correctly', () => { const [type, data] = reimplementPrepareMessage('o'); expect(type).toBe('o'); expect(data).toBeNull(); }); test('prepareMessage should parse heartbeat message correctly', () => { const [type, data] = reimplementPrepareMessage('h'); expect(type).toBe('h'); expect(data).toBeNull(); }); test('prepareMessage should parse array message correctly', () => { const [type, data] = reimplementPrepareMessage('a[{"i":1,"s":200,"d":"test"}]'); expect(type).toBe('a'); expect(data).toEqual([{ i: 1, s: 200, d: 'test' }]); }); test('prepareMessage should handle invalid JSON', () => { expect(() => { reimplementPrepareMessage('a{invalid json}'); }).toThrow('Failed to parse message'); }); test('checkHeartbeats should send heartbeat when needed', () => { const mockWs = { send: jest.fn() }; const now = new Date(); const oldTime = new Date(now.getTime() - 6000); // 6 seconds ago const result = reimplementCheckHeartbeats(mockWs, oldTime); expect(mockWs.send).toHaveBeenCalledWith('h'); expect(result).not.toBe(oldTime); }); test('checkHeartbeats should not send heartbeat when not needed', () => { const mockWs = { send: jest.fn() }; const now = new Date(); const recentTime = new Date(now.getTime() - 1000); // 1 second ago const result = reimplementCheckHeartbeats(mockWs, recentTime); expect(mockWs.send).not.toHaveBeenCalled(); expect(result).toBe(recentTime); }); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/alexanimal/tradovate-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server