mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-15 22:21:20 +00:00
175 lines
6.0 KiB
TypeScript
175 lines
6.0 KiB
TypeScript
/**
|
|
* Unit tests for remote-proxy-client module
|
|
*/
|
|
import { describe, it, expect } from 'bun:test';
|
|
import {
|
|
type RemoteProxyClientConfig,
|
|
type RemoteProxyStatus,
|
|
} from '../../../src/cliproxy/remote-proxy-client';
|
|
|
|
// We test the module's type exports and error handling logic
|
|
// Actual HTTP calls are not mocked in this unit test - use integration tests for that
|
|
|
|
describe('remote-proxy-client', () => {
|
|
describe('type exports', () => {
|
|
it('should export RemoteProxyClientConfig interface', () => {
|
|
// Type-level test - ensure the interface shape is correct
|
|
const config: RemoteProxyClientConfig = {
|
|
host: 'localhost',
|
|
port: 8317,
|
|
protocol: 'http',
|
|
authToken: 'test-token',
|
|
timeout: 2000,
|
|
allowSelfSigned: false,
|
|
};
|
|
expect(config.host).toBe('localhost');
|
|
expect(config.port).toBe(8317);
|
|
expect(config.protocol).toBe('http');
|
|
});
|
|
|
|
it('should export RemoteProxyStatus interface', () => {
|
|
// Success case
|
|
const successStatus: RemoteProxyStatus = {
|
|
reachable: true,
|
|
latencyMs: 50,
|
|
};
|
|
expect(successStatus.reachable).toBe(true);
|
|
expect(successStatus.latencyMs).toBe(50);
|
|
|
|
// Error case
|
|
const errorStatus: RemoteProxyStatus = {
|
|
reachable: false,
|
|
error: 'Connection refused',
|
|
errorCode: 'CONNECTION_REFUSED',
|
|
};
|
|
expect(errorStatus.reachable).toBe(false);
|
|
expect(errorStatus.error).toBe('Connection refused');
|
|
expect(errorStatus.errorCode).toBe('CONNECTION_REFUSED');
|
|
});
|
|
});
|
|
|
|
describe('RemoteProxyErrorCode', () => {
|
|
it('should define expected error codes', () => {
|
|
const validCodes = [
|
|
'CONNECTION_REFUSED',
|
|
'TIMEOUT',
|
|
'AUTH_FAILED',
|
|
'DNS_FAILED',
|
|
'NETWORK_UNREACHABLE',
|
|
'UNKNOWN',
|
|
];
|
|
|
|
// Type-level test - ensure error codes can be used
|
|
const status1: RemoteProxyStatus = { reachable: false, errorCode: 'CONNECTION_REFUSED' };
|
|
const status2: RemoteProxyStatus = { reachable: false, errorCode: 'TIMEOUT' };
|
|
const status3: RemoteProxyStatus = { reachable: false, errorCode: 'AUTH_FAILED' };
|
|
const status4: RemoteProxyStatus = { reachable: false, errorCode: 'UNKNOWN' };
|
|
const status5: RemoteProxyStatus = { reachable: false, errorCode: 'DNS_FAILED' };
|
|
const status6: RemoteProxyStatus = { reachable: false, errorCode: 'NETWORK_UNREACHABLE' };
|
|
|
|
expect(validCodes).toContain(status1.errorCode);
|
|
expect(validCodes).toContain(status2.errorCode);
|
|
expect(validCodes).toContain(status3.errorCode);
|
|
expect(validCodes).toContain(status4.errorCode);
|
|
expect(validCodes).toContain(status5.errorCode);
|
|
expect(validCodes).toContain(status6.errorCode);
|
|
});
|
|
});
|
|
|
|
describe('config validation', () => {
|
|
it('should require host and port', () => {
|
|
const minimalConfig: RemoteProxyClientConfig = {
|
|
host: '127.0.0.1',
|
|
port: 8317,
|
|
protocol: 'http',
|
|
};
|
|
expect(minimalConfig.host).toBeDefined();
|
|
expect(minimalConfig.port).toBeDefined();
|
|
expect(minimalConfig.protocol).toBeDefined();
|
|
});
|
|
|
|
it('should allow optional fields', () => {
|
|
const config: RemoteProxyClientConfig = {
|
|
host: '127.0.0.1',
|
|
port: 8317,
|
|
protocol: 'https',
|
|
authToken: 'secret',
|
|
timeout: 5000,
|
|
allowSelfSigned: true,
|
|
};
|
|
expect(config.authToken).toBe('secret');
|
|
expect(config.timeout).toBe(5000);
|
|
expect(config.allowSelfSigned).toBe(true);
|
|
});
|
|
|
|
it('should accept http and https protocols', () => {
|
|
const httpConfig: RemoteProxyClientConfig = {
|
|
host: 'localhost',
|
|
port: 8317,
|
|
protocol: 'http',
|
|
};
|
|
const httpsConfig: RemoteProxyClientConfig = {
|
|
host: 'localhost',
|
|
port: 8317,
|
|
protocol: 'https',
|
|
};
|
|
expect(httpConfig.protocol).toBe('http');
|
|
expect(httpsConfig.protocol).toBe('https');
|
|
});
|
|
});
|
|
|
|
describe('health check URL construction', () => {
|
|
// CLIProxyAPI uses root endpoint for liveness checks (no /health endpoint)
|
|
it('should construct correct health check URL pattern using /', () => {
|
|
const config: RemoteProxyClientConfig = {
|
|
host: '192.168.1.100',
|
|
port: 8317,
|
|
protocol: 'http',
|
|
};
|
|
const expectedUrl = `${config.protocol}://${config.host}:${config.port}/`;
|
|
expect(expectedUrl).toBe('http://192.168.1.100:8317/');
|
|
});
|
|
|
|
it('should construct HTTPS URL when protocol is https', () => {
|
|
const config: RemoteProxyClientConfig = {
|
|
host: 'secure.example.com',
|
|
port: 443,
|
|
protocol: 'https',
|
|
};
|
|
const expectedUrl = `${config.protocol}://${config.host}:${config.port}/`;
|
|
expect(expectedUrl).toBe('https://secure.example.com:443/');
|
|
});
|
|
});
|
|
|
|
describe('port defaults by protocol', () => {
|
|
// Document expected default ports based on protocol
|
|
// HTTP: 8317 (CLIProxyAPI default for local/dev scenarios)
|
|
// HTTPS: 443 (standard SSL port for production remote servers)
|
|
|
|
it('should document HTTP default port as 8317', () => {
|
|
// HTTP connections default to CLIProxyAPI port 8317
|
|
// This matches local development scenarios
|
|
const expectedHttpDefault = 8317;
|
|
expect(expectedHttpDefault).toBe(8317);
|
|
});
|
|
|
|
it('should document HTTPS default port as 443', () => {
|
|
// HTTPS connections default to standard SSL port 443
|
|
// This matches production remote server scenarios
|
|
const expectedHttpsDefault = 443;
|
|
expect(expectedHttpsDefault).toBe(443);
|
|
});
|
|
|
|
it('should allow port to be optional in config', () => {
|
|
// Port is optional - when undefined, defaults based on protocol
|
|
const configWithoutPort: RemoteProxyClientConfig = {
|
|
host: 'example.com',
|
|
protocol: 'https',
|
|
// port is intentionally undefined
|
|
};
|
|
expect(configWithoutPort.port).toBeUndefined();
|
|
expect(configWithoutPort.protocol).toBe('https');
|
|
});
|
|
});
|
|
});
|