Skip to main content
Glama
enhanced-hl7-client.test.ts10.5 kB
// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors // SPDX-License-Identifier: Apache-2.0 import type { ILogger } from '@medplum/core'; import { Hl7Message, TypedEventTarget } from '@medplum/core'; import { Hl7Server } from '@medplum/hl7'; import { EnhancedHl7Client } from './enhanced-hl7-client'; import { createMockLogger } from './test-utils'; import type { HeartbeatEmitter } from './types'; describe('EnhancedHl7Client', () => { const usedPorts = [] as number[]; // Helper function to get a random port number function getRandomPort(): number { let port = Math.floor(Math.random() * 10000) + 40000; while (usedPorts.includes(port)) { port = Math.floor(Math.random() * 10000) + 40000; } usedPorts.push(port); return port; } let mockHeartbeatEmitter: HeartbeatEmitter; let mockLogger: ILogger; beforeEach(() => { mockHeartbeatEmitter = new TypedEventTarget(); mockLogger = createMockLogger(); }); describe('send with tracking off', () => { test('Send does not record stats when tracking is off', async () => { const port = getRandomPort(); const server = new Hl7Server((connection) => { connection.addEventListener('message', ({ message }) => { connection.send(message.buildAck()); }); }); await server.start(port); const client = new EnhancedHl7Client({ host: 'localhost', port, log: mockLogger, }); const message = Hl7Message.parse( 'MSH|^~\\&|ADT1|MCM|LABADT|MCM|198808181126|SECURITY|ADT^A01|MSG00001|P|2.2\r' + 'PID|||PATID1234^5^M11||JONES^WILLIAM^A^III||19610615|M-' ); await client.send(message); expect(client.stats).toBeUndefined(); await client.close(); await server.stop(); }); }); describe('sendAndWait with tracking off', () => { test('SendAndWait does not record stats when tracking is off', async () => { const port = getRandomPort(); const server = new Hl7Server((connection) => { connection.addEventListener('message', ({ message }) => { connection.send(message.buildAck()); }); }); await server.start(port); const client = new EnhancedHl7Client({ host: 'localhost', port, log: mockLogger, }); const message = Hl7Message.parse( 'MSH|^~\\&|ADT1|MCM|LABADT|MCM|198808181126|SECURITY|ADT^A01|MSG00001|P|2.2\r' + 'PID|||PATID1234^5^M11||JONES^WILLIAM^A^III||19610615|M-' ); const response = await client.sendAndWait(message); expect(response).toBeDefined(); expect(client.stats).toBeUndefined(); await client.close(); await server.stop(); }); }); describe('send with tracking on', () => { test('Send records message sent when tracking is on', async () => { const port = getRandomPort(); const server = new Hl7Server((connection) => { connection.addEventListener('message', ({ message }) => { connection.send(message.buildAck()); }); }); await server.start(port); const client = new EnhancedHl7Client({ host: 'localhost', port, log: mockLogger, }); client.startTrackingStats({ heartbeatEmitter: mockHeartbeatEmitter, }); expect(client.stats).toBeDefined(); const message = Hl7Message.parse( 'MSH|^~\\&|ADT1|MCM|LABADT|MCM|198808181126|SECURITY|ADT^A01|MSG00001|P|2.2\r' + 'PID|||PATID1234^5^M11||JONES^WILLIAM^A^III||19610615|M-' ); await client.send(message); // Message should be recorded as pending expect(client.stats?.getPendingCount()).toBe(1); expect(client.stats?.getSampleCount()).toBe(0); await client.close(); await server.stop(); }); test('Send does not record stats when message has no control ID', async () => { const port = getRandomPort(); const server = new Hl7Server((connection) => { connection.addEventListener('message', ({ message }) => { connection.send(message.buildAck()); }); }); await server.start(port); const client = new EnhancedHl7Client({ host: 'localhost', port, log: mockLogger, }); client.startTrackingStats({ heartbeatEmitter: mockHeartbeatEmitter, }); const message = Hl7Message.parse( 'MSH|^~\\&|ADT1|MCM|LABADT|MCM|198808181126|SECURITY|ADT^A01||P|2.2\r' + 'PID|||PATID1234^5^M11||JONES^WILLIAM^A^III||19610615|M-' ); await client.send(message); // No stats should be recorded expect(client.stats?.getPendingCount()).toBe(0); expect(client.stats?.getSampleCount()).toBe(0); await client.close(); await server.stop(); }); }); describe('sendAndWait with tracking on', () => { test('SendAndWait records RTT when tracking is on', async () => { const port = getRandomPort(); const server = new Hl7Server((connection) => { connection.addEventListener('message', ({ message }) => { connection.send(message.buildAck()); }); }); await server.start(port); const client = new EnhancedHl7Client({ host: 'localhost', port, log: mockLogger, }); client.startTrackingStats({ heartbeatEmitter: mockHeartbeatEmitter, }); expect(client.stats).toBeDefined(); const message = Hl7Message.parse( 'MSH|^~\\&|ADT1|MCM|LABADT|MCM|198808181126|SECURITY|ADT^A01|MSG00001|P|2.2\r' + 'PID|||PATID1234^5^M11||JONES^WILLIAM^A^III||19610615|M-' ); const response = await client.sendAndWait(message); expect(response).toBeDefined(); // RTT should be recorded expect(client.stats?.getPendingCount()).toBe(0); expect(client.stats?.getSampleCount()).toBe(1); const stats = client.stats?.getRttStats(); expect(stats?.count).toBe(1); expect(stats?.min).toBeGreaterThanOrEqual(0); expect(stats?.max).toBeGreaterThanOrEqual(0); await client.close(); await server.stop(); }); test('sendAndWait records multiple RTT samples', async () => { const port = getRandomPort(); const server = new Hl7Server((connection) => { connection.addEventListener('message', ({ message }) => { connection.send(message.buildAck()); }); }); await server.start(port); const client = new EnhancedHl7Client({ host: 'localhost', port, log: mockLogger, }); client.startTrackingStats({ heartbeatEmitter: mockHeartbeatEmitter, }); // Send multiple messages for (let i = 1; i <= 3; i++) { const message = Hl7Message.parse( `MSH|^~\\&|ADT1|MCM|LABADT|MCM|198808181126|SECURITY|ADT^A01|MSG0000${i}|P|2.2\r` + 'PID|||PATID1234^5^M11||JONES^WILLIAM^A^III||19610615|M-' ); await client.sendAndWait(message); } // All RTTs should be recorded expect(client.stats?.getPendingCount()).toBe(0); expect(client.stats?.getSampleCount()).toBe(3); expect(client.stats?.getRttSamples().length).toBe(3); const stats = client.stats?.getRttStats(); expect(stats?.count).toBe(3); await client.close(); await server.stop(); }); test('sendAndWait does not record stats when message has no control ID', async () => { const port = getRandomPort(); const server = new Hl7Server((connection) => { connection.addEventListener('message', ({ message }) => { connection.send(message.buildAck()); }); }); await server.start(port); const client = new EnhancedHl7Client({ host: 'localhost', port, log: mockLogger, }); client.startTrackingStats({ heartbeatEmitter: mockHeartbeatEmitter, }); const message = Hl7Message.parse( 'MSH|^~\\&|ADT1|MCM|LABADT|MCM|198808181126|SECURITY|ADT^A01||P|2.2\r' + 'PID|||PATID1234^5^M11||JONES^WILLIAM^A^III||19610615|M-' ); // sendAndWait throws an error when there's no control ID in the base class await expect(client.sendAndWait(message)).rejects.toThrow('Required field missing: MSH.10'); // No stats should be recorded expect(client.stats?.getPendingCount()).toBe(0); expect(client.stats?.getSampleCount()).toBe(0); await client.close(); await server.stop(); }); }); describe('startTrackingStats', () => { test('Does not start tracking if already tracking', async () => { const client = new EnhancedHl7Client({ host: 'localhost', port: 9999, log: mockLogger, }); client.startTrackingStats({ heartbeatEmitter: mockHeartbeatEmitter, }); const firstStatsTracker = client.stats; expect(firstStatsTracker).toBeDefined(); expect(mockHeartbeatEmitter.listenerCount('heartbeat')).toBe(1); // Try to start tracking again client.startTrackingStats({ heartbeatEmitter: mockHeartbeatEmitter, }); // Should still be the same stats tracker expect(client.stats).toBe(firstStatsTracker); // Should not have added another listener expect(mockHeartbeatEmitter.listenerCount('heartbeat')).toBe(1); await client.close(); }); }); describe('stopTrackingStats', () => { test('Calls cleanup on stats tracker when stopping', async () => { const client = new EnhancedHl7Client({ host: 'localhost', port: 9999, log: mockLogger, }); client.startTrackingStats({ heartbeatEmitter: mockHeartbeatEmitter, }); expect(client.stats).toBeDefined(); expect(mockHeartbeatEmitter.listenerCount('heartbeat')).toBe(1); client.stopTrackingStats(); // Cleanup should have removed the heartbeat listener expect(mockHeartbeatEmitter.listenerCount('heartbeat')).toBe(0); await client.close(); }); test('Does not error when stopping tracking when not tracking', async () => { const client = new EnhancedHl7Client({ host: 'localhost', port: 9999, log: mockLogger, }); expect(client.stats).toBeUndefined(); // Should not throw expect(() => client.stopTrackingStats()).not.toThrow(); await client.close(); }); }); });

Latest Blog Posts

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/medplum/medplum'

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