119 lines
3.3 KiB
TypeScript
119 lines
3.3 KiB
TypeScript
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||
|
import * as smartipc from '../ts/index.js';
|
||
|
import * as smartdelay from '@push.rocks/smartdelay';
|
||
|
import * as smartpromise from '@push.rocks/smartpromise';
|
||
|
|
||
|
let server: smartipc.IpcServer;
|
||
|
let client: smartipc.IpcClient;
|
||
|
|
||
|
// Test TCP transport which is simpler
|
||
|
tap.test('should create and start a TCP IPC server', async () => {
|
||
|
server = smartipc.SmartIpc.createServer({
|
||
|
id: 'tcp-test-server',
|
||
|
host: 'localhost',
|
||
|
port: 18765,
|
||
|
heartbeat: false // Disable heartbeat for simpler testing
|
||
|
});
|
||
|
|
||
|
await server.start();
|
||
|
expect(server.getStats().isRunning).toBeTrue();
|
||
|
});
|
||
|
|
||
|
tap.test('should create and connect a TCP client', async () => {
|
||
|
client = smartipc.SmartIpc.createClient({
|
||
|
id: 'tcp-test-server',
|
||
|
host: 'localhost',
|
||
|
port: 18765,
|
||
|
clientId: 'test-client-1',
|
||
|
metadata: { name: 'Test Client' },
|
||
|
heartbeat: false
|
||
|
});
|
||
|
|
||
|
await client.connect();
|
||
|
expect(client.getIsConnected()).toBeTrue();
|
||
|
expect(client.getClientId()).toEqual('test-client-1');
|
||
|
});
|
||
|
|
||
|
tap.test('should send messages between server and client', async () => {
|
||
|
const messageReceived = smartpromise.defer();
|
||
|
|
||
|
// Server listens for messages
|
||
|
server.onMessage('test-message', (payload, clientId) => {
|
||
|
expect(payload).toEqual({ data: 'Hello Server' });
|
||
|
expect(clientId).toEqual('test-client-1');
|
||
|
messageReceived.resolve();
|
||
|
});
|
||
|
|
||
|
// Client sends message
|
||
|
await client.sendMessage('test-message', { data: 'Hello Server' });
|
||
|
|
||
|
await messageReceived.promise;
|
||
|
});
|
||
|
|
||
|
tap.test('should handle request/response pattern', async () => {
|
||
|
// Server handles requests
|
||
|
server.onMessage('add', async (payload: {a: number, b: number}, clientId) => {
|
||
|
return { result: payload.a + payload.b };
|
||
|
});
|
||
|
|
||
|
// Client makes request
|
||
|
const response = await client.request<{a: number, b: number}, {result: number}>(
|
||
|
'add',
|
||
|
{ a: 5, b: 3 },
|
||
|
{ timeout: 5000 }
|
||
|
);
|
||
|
|
||
|
expect(response.result).toEqual(8);
|
||
|
});
|
||
|
|
||
|
tap.test('should handle pub/sub pattern', async () => {
|
||
|
// Create a second client
|
||
|
const client2 = smartipc.SmartIpc.createClient({
|
||
|
id: 'tcp-test-server',
|
||
|
host: 'localhost',
|
||
|
port: 18765,
|
||
|
clientId: 'test-client-2',
|
||
|
metadata: { name: 'Test Client 2' },
|
||
|
heartbeat: false
|
||
|
});
|
||
|
|
||
|
await client2.connect();
|
||
|
|
||
|
const messageReceived = smartpromise.defer();
|
||
|
|
||
|
// Client 1 subscribes to a topic
|
||
|
await client.subscribe('news', (payload) => {
|
||
|
expect(payload).toEqual({ headline: 'Breaking news!' });
|
||
|
messageReceived.resolve();
|
||
|
});
|
||
|
|
||
|
// Give server time to process subscription
|
||
|
await smartdelay.delayFor(100);
|
||
|
|
||
|
// Client 2 publishes to the topic
|
||
|
await client2.publish('news', { headline: 'Breaking news!' });
|
||
|
|
||
|
await messageReceived.promise;
|
||
|
|
||
|
await client2.disconnect();
|
||
|
});
|
||
|
|
||
|
tap.test('should track metrics correctly', async () => {
|
||
|
const stats = client.getStats();
|
||
|
|
||
|
expect(stats.connected).toBeTrue();
|
||
|
expect(stats.metrics.messagesSent).toBeGreaterThan(0);
|
||
|
expect(stats.metrics.messagesReceived).toBeGreaterThan(0);
|
||
|
expect(stats.metrics.bytesSent).toBeGreaterThan(0);
|
||
|
expect(stats.metrics.bytesReceived).toBeGreaterThan(0);
|
||
|
});
|
||
|
|
||
|
tap.test('should cleanup and close connections', async () => {
|
||
|
await client.disconnect();
|
||
|
await server.stop();
|
||
|
|
||
|
expect(server.getStats().isRunning).toBeFalse();
|
||
|
expect(client.getIsConnected()).toBeFalse();
|
||
|
});
|
||
|
|
||
|
export default tap.start();
|