152 lines
4.7 KiB
TypeScript
152 lines
4.7 KiB
TypeScript
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
|
import * as tspm from '../ts/index.js';
|
|
import * as path from 'path';
|
|
import * as fs from 'fs/promises';
|
|
import { TspmIpcClient } from '../ts/client/tspm.ipcclient.js';
|
|
import * as os from 'os';
|
|
|
|
// Test IPC client functionality
|
|
tap.test('TspmIpcClient creation', async () => {
|
|
const client = new TspmIpcClient();
|
|
expect(client).toBeInstanceOf(TspmIpcClient);
|
|
});
|
|
|
|
tap.test('IPC client socket path', async () => {
|
|
const client = new TspmIpcClient();
|
|
const socketPath = (client as any).socketPath;
|
|
|
|
expect(socketPath).toInclude('.tspm');
|
|
expect(socketPath).toInclude('tspm.sock');
|
|
});
|
|
|
|
tap.test('IPC client daemon PID file path', async () => {
|
|
const client = new TspmIpcClient();
|
|
const daemonPidFile = (client as any).daemonPidFile;
|
|
|
|
expect(daemonPidFile).toInclude('.tspm');
|
|
expect(daemonPidFile).toInclude('daemon.pid');
|
|
});
|
|
|
|
tap.test('IPC client connection state', async () => {
|
|
const client = new TspmIpcClient();
|
|
const isConnected = (client as any).isConnected;
|
|
|
|
expect(isConnected).toEqual(false); // Should be false initially
|
|
});
|
|
|
|
tap.test('IPC client daemon running check - no daemon', async () => {
|
|
const client = new TspmIpcClient();
|
|
const tspmDir = path.join(os.homedir(), '.tspm');
|
|
const pidFile = path.join(tspmDir, 'daemon.pid');
|
|
|
|
// Ensure no PID file exists for this test
|
|
await fs.unlink(pidFile).catch(() => {});
|
|
|
|
const isRunning = await (client as any).isDaemonRunning();
|
|
expect(isRunning).toEqual(false);
|
|
});
|
|
|
|
tap.test('IPC client daemon running check - stale PID', async () => {
|
|
const client = new TspmIpcClient();
|
|
const tspmDir = path.join(os.homedir(), '.tspm');
|
|
const pidFile = path.join(tspmDir, 'daemon.pid');
|
|
|
|
// Create directory if it doesn't exist
|
|
await fs.mkdir(tspmDir, { recursive: true });
|
|
|
|
// Write a fake PID that doesn't exist
|
|
await fs.writeFile(pidFile, '99999999');
|
|
|
|
const isRunning = await (client as any).isDaemonRunning();
|
|
expect(isRunning).toEqual(false);
|
|
|
|
// Clean up - the stale PID should be removed
|
|
const fileExists = await fs
|
|
.access(pidFile)
|
|
.then(() => true)
|
|
.catch(() => false);
|
|
expect(fileExists).toEqual(false);
|
|
});
|
|
|
|
tap.test('IPC client daemon running check - current process', async () => {
|
|
const client = new TspmIpcClient();
|
|
const tspmDir = path.join(os.homedir(), '.tspm');
|
|
const pidFile = path.join(tspmDir, 'daemon.pid');
|
|
const socketFile = path.join(tspmDir, 'tspm.sock');
|
|
|
|
// Create directory if it doesn't exist
|
|
await fs.mkdir(tspmDir, { recursive: true });
|
|
|
|
// Write current process PID (simulating daemon is this process)
|
|
await fs.writeFile(pidFile, process.pid.toString());
|
|
|
|
// Create a fake socket file
|
|
await fs.writeFile(socketFile, '');
|
|
|
|
const isRunning = await (client as any).isDaemonRunning();
|
|
expect(isRunning).toEqual(true);
|
|
|
|
// Clean up
|
|
await fs.unlink(pidFile).catch(() => {});
|
|
await fs.unlink(socketFile).catch(() => {});
|
|
});
|
|
|
|
tap.test('IPC client singleton instance', async () => {
|
|
// Import the singleton
|
|
const { tspmIpcClient } = await import('../ts/client/tspm.ipcclient.js');
|
|
|
|
expect(tspmIpcClient).toBeInstanceOf(TspmIpcClient);
|
|
|
|
// Test that it's the same instance
|
|
const { tspmIpcClient: secondImport } = await import(
|
|
'../ts/client/tspm.ipcclient.js'
|
|
);
|
|
expect(tspmIpcClient).toEqual(secondImport);
|
|
});
|
|
|
|
tap.test('IPC client request method type safety', async () => {
|
|
const client = new TspmIpcClient();
|
|
|
|
// Test that request method exists
|
|
expect(client.request).toBeInstanceOf(Function);
|
|
expect(client.connect).toBeInstanceOf(Function);
|
|
expect(client.disconnect).toBeInstanceOf(Function);
|
|
expect(client.stopDaemon).toBeInstanceOf(Function);
|
|
expect(client.getDaemonStatus).toBeInstanceOf(Function);
|
|
});
|
|
|
|
tap.test('IPC client error message formatting', async () => {
|
|
const errorMessage =
|
|
'Could not connect to TSPM daemon. Please try running "tspm daemon start" manually.';
|
|
expect(errorMessage).toInclude('tspm daemon start');
|
|
});
|
|
|
|
tap.test('IPC client reconnection logic', async () => {
|
|
const client = new TspmIpcClient();
|
|
|
|
// Test reconnection error conditions
|
|
const econnrefusedError = new Error('ECONNREFUSED');
|
|
expect(econnrefusedError.message).toInclude('ECONNREFUSED');
|
|
|
|
const enoentError = new Error('ENOENT');
|
|
expect(enoentError.message).toInclude('ENOENT');
|
|
});
|
|
|
|
tap.test('IPC client daemon start timeout', async () => {
|
|
const maxWaitTime = 10000; // 10 seconds
|
|
const checkInterval = 500; // 500ms
|
|
|
|
const maxChecks = maxWaitTime / checkInterval;
|
|
expect(maxChecks).toEqual(20);
|
|
});
|
|
|
|
tap.test('IPC client daemon stop timeout', async () => {
|
|
const maxWaitTime = 15000; // 15 seconds
|
|
const checkInterval = 500; // 500ms
|
|
|
|
const maxChecks = maxWaitTime / checkInterval;
|
|
expect(maxChecks).toEqual(30);
|
|
});
|
|
|
|
export default tap.start();
|