123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557 |
- "use strict";
- /**
- * Integration test for WebSocket session updates
- * Tests the complete flow of real-time WebSocket communication for hedging sessions
- */
- var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
- };
- Object.defineProperty(exports, "__esModule", { value: true });
- const globals_1 = require("@jest/globals");
- const ws_1 = __importDefault(require("ws"));
- const HedgingManager_1 = require("../../src/core/HedgingManager");
- const WebSocketManager_1 = require("../../src/services/WebSocketManager");
- (0, globals_1.describe)('WebSocket Session Updates Integration', () => {
- let hedgingManager;
- let webSocketManager;
- let testSessionId;
- let wsServer;
- let wsPort = 8080;
- (0, globals_1.beforeAll)(async () => {
- // Initialize hedging manager
- hedgingManager = new HedgingManager_1.HedgingManager({
- accounts: './config/accounts.json',
- hedging: './config/hedging-config.json',
- marketData: './config/market-data-config.json'
- });
- // Initialize WebSocket manager
- webSocketManager = new WebSocketManager_1.WebSocketManager({
- port: wsPort,
- heartbeatInterval: 30000,
- reconnectInterval: 5000,
- maxReconnectAttempts: 5,
- connectionTimeout: 10000
- });
- await hedgingManager.initialize();
- await webSocketManager.initialize();
- });
- (0, globals_1.afterAll)(async () => {
- if (hedgingManager) {
- await hedgingManager.shutdown();
- }
- if (webSocketManager) {
- await webSocketManager.shutdown();
- }
- if (wsServer) {
- wsServer.close();
- }
- });
- (0, globals_1.beforeEach)(async () => {
- // Create a test session for each test
- const sessionRequest = {
- name: 'WebSocket Test Session',
- accountIds: ['account-1', 'account-2'],
- volumeTarget: 10000,
- strategy: {
- symbol: 'ETH/USD',
- volumeDistribution: 'equal',
- priceRange: { min: 0.001, max: 0.01 },
- timing: { minInterval: 30, maxInterval: 120, orderSize: { min: 100, max: 500 } },
- riskLimits: { maxPositionSize: 0.1, stopLossThreshold: 0.05, maxSlippage: 0.02 },
- orderTypes: { primary: 'limit', fallback: 'market' }
- }
- };
- try {
- const session = await hedgingManager.createSession(sessionRequest);
- testSessionId = session.id;
- }
- catch (error) {
- testSessionId = 'mock-session-id';
- }
- });
- (0, globals_1.describe)('WebSocket Connection', () => {
- (0, globals_1.it)('should establish WebSocket connection', (done) => {
- const ws = new ws_1.default(`ws://localhost:${wsPort}/ws/sessions/${testSessionId}`);
- ws.on('open', () => {
- (0, globals_1.expect)(ws.readyState).toBe(ws_1.default.OPEN);
- ws.close();
- done();
- });
- ws.on('error', (error) => {
- // This test should fail initially since WebSocket server doesn't exist yet
- (0, globals_1.expect)(error.message).toContain('ECONNREFUSED');
- done();
- });
- });
- (0, globals_1.it)('should authenticate WebSocket connection', (done) => {
- const ws = new ws_1.default(`ws://localhost:${wsPort}/ws/sessions/${testSessionId}`, {
- headers: {
- 'Authorization': 'Bearer test-api-key'
- }
- });
- ws.on('open', () => {
- // Send authentication message
- const authMessage = {
- type: 'authenticate',
- token: 'test-api-key'
- };
- ws.send(JSON.stringify(authMessage));
- });
- ws.on('message', (data) => {
- const message = JSON.parse(data.toString());
- if (message.type === 'authenticated') {
- (0, globals_1.expect)(message.success).toBe(true);
- ws.close();
- done();
- }
- });
- ws.on('error', (error) => {
- // This test should fail initially since WebSocket server doesn't exist yet
- (0, globals_1.expect)(error.message).toContain('ECONNREFUSED');
- done();
- });
- });
- (0, globals_1.it)('should reject unauthenticated connections', (done) => {
- const ws = new ws_1.default(`ws://localhost:${wsPort}/ws/sessions/${testSessionId}`);
- ws.on('open', () => {
- // Don't send authentication
- setTimeout(() => {
- (0, globals_1.expect)(ws.readyState).toBe(ws_1.default.CLOSED);
- done();
- }, 1000);
- });
- ws.on('error', (error) => {
- // This test should fail initially since WebSocket server doesn't exist yet
- (0, globals_1.expect)(error.message).toContain('ECONNREFUSED');
- done();
- });
- });
- });
- (0, globals_1.describe)('Session Subscription', () => {
- (0, globals_1.it)('should subscribe to session updates', (done) => {
- const ws = new ws_1.default(`ws://localhost:${wsPort}/ws/sessions/${testSessionId}`, {
- headers: {
- 'Authorization': 'Bearer test-api-key'
- }
- });
- ws.on('open', () => {
- // Authenticate first
- ws.send(JSON.stringify({ type: 'authenticate', token: 'test-api-key' }));
- });
- ws.on('message', (data) => {
- const message = JSON.parse(data.toString());
- if (message.type === 'authenticated') {
- // Subscribe to session updates
- const subscription = {
- type: 'subscribe',
- sessionId: testSessionId,
- channels: ['status', 'orders', 'risk', 'metrics']
- };
- ws.send(JSON.stringify(subscription));
- }
- else if (message.type === 'subscribed') {
- (0, globals_1.expect)(message.success).toBe(true);
- (0, globals_1.expect)(message.channels).toEqual(['status', 'orders', 'risk', 'metrics']);
- ws.close();
- done();
- }
- });
- ws.on('error', (error) => {
- // This test should fail initially since WebSocket server doesn't exist yet
- (0, globals_1.expect)(error.message).toContain('ECONNREFUSED');
- done();
- });
- });
- (0, globals_1.it)('should validate subscription channels', (done) => {
- const ws = new ws_1.default(`ws://localhost:${wsPort}/ws/sessions/${testSessionId}`, {
- headers: {
- 'Authorization': 'Bearer test-api-key'
- }
- });
- ws.on('open', () => {
- ws.send(JSON.stringify({ type: 'authenticate', token: 'test-api-key' }));
- });
- ws.on('message', (data) => {
- const message = JSON.parse(data.toString());
- if (message.type === 'authenticated') {
- // Subscribe with invalid channel
- const invalidSubscription = {
- type: 'subscribe',
- sessionId: testSessionId,
- channels: ['invalid_channel']
- };
- ws.send(JSON.stringify(invalidSubscription));
- }
- else if (message.type === 'error') {
- (0, globals_1.expect)(message.error.code).toBe('INVALID_CHANNEL');
- ws.close();
- done();
- }
- });
- ws.on('error', (error) => {
- // This test should fail initially since WebSocket server doesn't exist yet
- (0, globals_1.expect)(error.message).toContain('ECONNREFUSED');
- done();
- });
- });
- });
- (0, globals_1.describe)('Real-time Updates', () => {
- (0, globals_1.it)('should receive status updates', (done) => {
- const ws = new ws_1.default(`ws://localhost:${wsPort}/ws/sessions/${testSessionId}`, {
- headers: {
- 'Authorization': 'Bearer test-api-key'
- }
- });
- let updateReceived = false;
- ws.on('open', () => {
- ws.send(JSON.stringify({ type: 'authenticate', token: 'test-api-key' }));
- });
- ws.on('message', (data) => {
- const message = JSON.parse(data.toString());
- if (message.type === 'authenticated') {
- // Subscribe to status updates
- ws.send(JSON.stringify({
- type: 'subscribe',
- sessionId: testSessionId,
- channels: ['status']
- }));
- }
- else if (message.type === 'session_update' && message.channel === 'status') {
- const updateMessage = message;
- (0, globals_1.expect)(updateMessage.sessionId).toBe(testSessionId);
- (0, globals_1.expect)(updateMessage.channel).toBe('status');
- (0, globals_1.expect)(updateMessage.data.status).toBeDefined();
- (0, globals_1.expect)(updateMessage.timestamp).toBeDefined();
- updateReceived = true;
- ws.close();
- done();
- }
- });
- ws.on('error', (error) => {
- // This test should fail initially since WebSocket server doesn't exist yet
- (0, globals_1.expect)(error.message).toContain('ECONNREFUSED');
- done();
- });
- // Timeout if no update received
- setTimeout(() => {
- if (!updateReceived) {
- ws.close();
- done();
- }
- }, 5000);
- });
- (0, globals_1.it)('should receive order updates', (done) => {
- const ws = new ws_1.default(`ws://localhost:${wsPort}/ws/sessions/${testSessionId}`, {
- headers: {
- 'Authorization': 'Bearer test-api-key'
- }
- });
- let updateReceived = false;
- ws.on('open', () => {
- ws.send(JSON.stringify({ type: 'authenticate', token: 'test-api-key' }));
- });
- ws.on('message', (data) => {
- const message = JSON.parse(data.toString());
- if (message.type === 'authenticated') {
- // Subscribe to order updates
- ws.send(JSON.stringify({
- type: 'subscribe',
- sessionId: testSessionId,
- channels: ['orders']
- }));
- }
- else if (message.type === 'session_update' && message.channel === 'orders') {
- const updateMessage = message;
- (0, globals_1.expect)(updateMessage.sessionId).toBe(testSessionId);
- (0, globals_1.expect)(updateMessage.channel).toBe('orders');
- (0, globals_1.expect)(updateMessage.data.orders).toBeDefined();
- (0, globals_1.expect)(Array.isArray(updateMessage.data.orders)).toBe(true);
- updateReceived = true;
- ws.close();
- done();
- }
- });
- ws.on('error', (error) => {
- // This test should fail initially since WebSocket server doesn't exist yet
- (0, globals_1.expect)(error.message).toContain('ECONNREFUSED');
- done();
- });
- // Timeout if no update received
- setTimeout(() => {
- if (!updateReceived) {
- ws.close();
- done();
- }
- }, 5000);
- });
- (0, globals_1.it)('should receive risk updates', (done) => {
- const ws = new ws_1.default(`ws://localhost:${wsPort}/ws/sessions/${testSessionId}`, {
- headers: {
- 'Authorization': 'Bearer test-api-key'
- }
- });
- let updateReceived = false;
- ws.on('open', () => {
- ws.send(JSON.stringify({ type: 'authenticate', token: 'test-api-key' }));
- });
- ws.on('message', (data) => {
- const message = JSON.parse(data.toString());
- if (message.type === 'authenticated') {
- // Subscribe to risk updates
- ws.send(JSON.stringify({
- type: 'subscribe',
- sessionId: testSessionId,
- channels: ['risk']
- }));
- }
- else if (message.type === 'session_update' && message.channel === 'risk') {
- const updateMessage = message;
- (0, globals_1.expect)(updateMessage.sessionId).toBe(testSessionId);
- (0, globals_1.expect)(updateMessage.channel).toBe('risk');
- (0, globals_1.expect)(updateMessage.data.riskBreaches).toBeDefined();
- (0, globals_1.expect)(Array.isArray(updateMessage.data.riskBreaches)).toBe(true);
- updateReceived = true;
- ws.close();
- done();
- }
- });
- ws.on('error', (error) => {
- // This test should fail initially since WebSocket server doesn't exist yet
- (0, globals_1.expect)(error.message).toContain('ECONNREFUSED');
- done();
- });
- // Timeout if no update received
- setTimeout(() => {
- if (!updateReceived) {
- ws.close();
- done();
- }
- }, 5000);
- });
- (0, globals_1.it)('should receive metrics updates', (done) => {
- const ws = new ws_1.default(`ws://localhost:${wsPort}/ws/sessions/${testSessionId}`, {
- headers: {
- 'Authorization': 'Bearer test-api-key'
- }
- });
- let updateReceived = false;
- ws.on('open', () => {
- ws.send(JSON.stringify({ type: 'authenticate', token: 'test-api-key' }));
- });
- ws.on('message', (data) => {
- const message = JSON.parse(data.toString());
- if (message.type === 'authenticated') {
- // Subscribe to metrics updates
- ws.send(JSON.stringify({
- type: 'subscribe',
- sessionId: testSessionId,
- channels: ['metrics']
- }));
- }
- else if (message.type === 'session_update' && message.channel === 'metrics') {
- const updateMessage = message;
- (0, globals_1.expect)(updateMessage.sessionId).toBe(testSessionId);
- (0, globals_1.expect)(updateMessage.channel).toBe('metrics');
- (0, globals_1.expect)(updateMessage.data.metrics).toBeDefined();
- (0, globals_1.expect)(updateMessage.data.metrics.volume).toBeDefined();
- (0, globals_1.expect)(updateMessage.data.metrics.orders).toBeDefined();
- (0, globals_1.expect)(updateMessage.data.metrics.performance).toBeDefined();
- (0, globals_1.expect)(updateMessage.data.metrics.risk).toBeDefined();
- updateReceived = true;
- ws.close();
- done();
- }
- });
- ws.on('error', (error) => {
- // This test should fail initially since WebSocket server doesn't exist yet
- (0, globals_1.expect)(error.message).toContain('ECONNREFUSED');
- done();
- });
- // Timeout if no update received
- setTimeout(() => {
- if (!updateReceived) {
- ws.close();
- done();
- }
- }, 5000);
- });
- });
- (0, globals_1.describe)('Connection Management', () => {
- (0, globals_1.it)('should handle connection heartbeat', (done) => {
- const ws = new ws_1.default(`ws://localhost:${wsPort}/ws/sessions/${testSessionId}`, {
- headers: {
- 'Authorization': 'Bearer test-api-key'
- }
- });
- let heartbeatReceived = false;
- ws.on('open', () => {
- ws.send(JSON.stringify({ type: 'authenticate', token: 'test-api-key' }));
- });
- ws.on('message', (data) => {
- const message = JSON.parse(data.toString());
- if (message.type === 'authenticated') {
- // Subscribe to updates
- ws.send(JSON.stringify({
- type: 'subscribe',
- sessionId: testSessionId,
- channels: ['status']
- }));
- }
- else if (message.type === 'heartbeat') {
- (0, globals_1.expect)(message.timestamp).toBeDefined();
- heartbeatReceived = true;
- ws.close();
- done();
- }
- });
- ws.on('error', (error) => {
- // This test should fail initially since WebSocket server doesn't exist yet
- (0, globals_1.expect)(error.message).toContain('ECONNREFUSED');
- done();
- });
- // Timeout if no heartbeat received
- setTimeout(() => {
- if (!heartbeatReceived) {
- ws.close();
- done();
- }
- }, 10000);
- });
- (0, globals_1.it)('should handle connection reconnection', (done) => {
- const ws = new ws_1.default(`ws://localhost:${wsPort}/ws/sessions/${testSessionId}`, {
- headers: {
- 'Authorization': 'Bearer test-api-key'
- }
- });
- ws.on('open', () => {
- ws.send(JSON.stringify({ type: 'authenticate', token: 'test-api-key' }));
- });
- ws.on('message', (data) => {
- const message = JSON.parse(data.toString());
- if (message.type === 'authenticated') {
- // Subscribe to updates
- ws.send(JSON.stringify({
- type: 'subscribe',
- sessionId: testSessionId,
- channels: ['status']
- }));
- // Simulate connection drop and reconnect
- setTimeout(() => {
- ws.close();
- // Reconnect
- const ws2 = new ws_1.default(`ws://localhost:${wsPort}/ws/sessions/${testSessionId}`, {
- headers: {
- 'Authorization': 'Bearer test-api-key'
- }
- });
- ws2.on('open', () => {
- ws2.send(JSON.stringify({ type: 'authenticate', token: 'test-api-key' }));
- });
- ws2.on('message', (data) => {
- const message = JSON.parse(data.toString());
- if (message.type === 'authenticated') {
- ws2.close();
- done();
- }
- });
- ws2.on('error', (error) => {
- // This test should fail initially since WebSocket server doesn't exist yet
- (0, globals_1.expect)(error.message).toContain('ECONNREFUSED');
- done();
- });
- }, 1000);
- }
- });
- ws.on('error', (error) => {
- // This test should fail initially since WebSocket server doesn't exist yet
- (0, globals_1.expect)(error.message).toContain('ECONNREFUSED');
- done();
- });
- });
- (0, globals_1.it)('should handle multiple concurrent connections', (done) => {
- const connections = [];
- let connectedCount = 0;
- // Create multiple connections
- for (let i = 0; i < 5; i++) {
- const ws = new ws_1.default(`ws://localhost:${wsPort}/ws/sessions/${testSessionId}`, {
- headers: {
- 'Authorization': 'Bearer test-api-key'
- }
- });
- ws.on('open', () => {
- ws.send(JSON.stringify({ type: 'authenticate', token: 'test-api-key' }));
- });
- ws.on('message', (data) => {
- const message = JSON.parse(data.toString());
- if (message.type === 'authenticated') {
- connectedCount++;
- if (connectedCount === 5) {
- // Close all connections
- connections.forEach(conn => conn.close());
- done();
- }
- }
- });
- ws.on('error', (error) => {
- // This test should fail initially since WebSocket server doesn't exist yet
- (0, globals_1.expect)(error.message).toContain('ECONNREFUSED');
- done();
- });
- connections.push(ws);
- }
- });
- });
- (0, globals_1.describe)('Error Handling', () => {
- (0, globals_1.it)('should handle invalid session ID', (done) => {
- const ws = new ws_1.default(`ws://localhost:${wsPort}/ws/sessions/invalid-session-id`, {
- headers: {
- 'Authorization': 'Bearer test-api-key'
- }
- });
- ws.on('open', () => {
- ws.send(JSON.stringify({ type: 'authenticate', token: 'test-api-key' }));
- });
- ws.on('message', (data) => {
- const message = JSON.parse(data.toString());
- if (message.type === 'error') {
- (0, globals_1.expect)(message.error.code).toBe('SESSION_NOT_FOUND');
- ws.close();
- done();
- }
- });
- ws.on('error', (error) => {
- // This test should fail initially since WebSocket server doesn't exist yet
- (0, globals_1.expect)(error.message).toContain('ECONNREFUSED');
- done();
- });
- });
- (0, globals_1.it)('should handle malformed messages', (done) => {
- const ws = new ws_1.default(`ws://localhost:${wsPort}/ws/sessions/${testSessionId}`, {
- headers: {
- 'Authorization': 'Bearer test-api-key'
- }
- });
- ws.on('open', () => {
- ws.send(JSON.stringify({ type: 'authenticate', token: 'test-api-key' }));
- });
- ws.on('message', (data) => {
- const message = JSON.parse(data.toString());
- if (message.type === 'authenticated') {
- // Send malformed message
- ws.send('invalid json');
- }
- else if (message.type === 'error') {
- (0, globals_1.expect)(message.error.code).toBe('INVALID_MESSAGE_FORMAT');
- ws.close();
- done();
- }
- });
- ws.on('error', (error) => {
- // This test should fail initially since WebSocket server doesn't exist yet
- (0, globals_1.expect)(error.message).toContain('ECONNREFUSED');
- done();
- });
- });
- });
- });
- //# sourceMappingURL=test_websocket_updates.js.map
|