fix: resolve strict typecheck fallout in setup, routing, and tests

This commit is contained in:
William Valentin
2026-02-15 23:22:05 -08:00
parent 948d4ac6d8
commit ae70818ec1
18 changed files with 182 additions and 134 deletions
+2 -2
View File
@@ -52,7 +52,7 @@ describe('discoverServices', () => {
it('marks configured channels as disconnected when adapter is not registered', () => {
const cfg = makeBaseConfig();
withMutableConfig(cfg).telegram = { bot_token: 'x', allowed_chat_ids: [123] };
withMutableConfig(cfg).telegram = { bot_token: 'x', allowed_chat_ids: [123], require_mention: false };
const reg = new ChannelRegistry();
const services = discoverServices(cfg, reg);
@@ -62,7 +62,7 @@ describe('discoverServices', () => {
it('uses adapter status when channel adapter is registered', () => {
const cfg = makeBaseConfig();
withMutableConfig(cfg).telegram = { bot_token: 'x', allowed_chat_ids: [123] };
withMutableConfig(cfg).telegram = { bot_token: 'x', allowed_chat_ids: [123], require_mention: false };
const reg = new ChannelRegistry();
reg.register({
+21 -42
View File
@@ -8,12 +8,23 @@ vi.mock('child_process', () => ({
}));
const mockExecFile = vi.mocked(execFile);
type ExecFileCallback = (error: Error | null, stdout: string, stderr: string) => void;
type ExecFileCallback = NonNullable<Parameters<typeof execFile>[3]>;
function mockChildProcess(): ChildProcess {
return {} as ChildProcess;
}
function mockExecFileOnce(
impl: (callback: ExecFileCallback) => void,
): void {
mockExecFile.mockImplementationOnce((_cmd, _args, _opts, callback) => {
if (typeof callback === 'function') {
impl(callback as ExecFileCallback);
}
return mockChildProcess();
});
}
describe('tailscale', () => {
// Import after mocking
let isTailscaleAvailable: typeof import('./tailscale.js').isTailscaleAvailable;
@@ -33,15 +44,8 @@ describe('tailscale', () => {
describe('isTailscaleAvailable', () => {
it('returns available when tailscale CLI works', async () => {
mockExecFile
.mockImplementationOnce((_cmd, _args, _opts, callback: ExecFileCallback) => {
callback(null, '1.62.0', '');
return mockChildProcess();
})
.mockImplementationOnce((_cmd, _args, _opts, callback: ExecFileCallback) => {
callback(null, '{}', '');
return mockChildProcess();
});
mockExecFileOnce((callback) => callback(null, '1.62.0', ''));
mockExecFileOnce((callback) => callback(null, '{}', ''));
const result = await isTailscaleAvailable();
expect(result.available).toBe(true);
@@ -49,10 +53,7 @@ describe('tailscale', () => {
});
it('returns unavailable when tailscale CLI fails', async () => {
mockExecFile.mockImplementationOnce((_cmd, _args, _opts, callback: ExecFileCallback) => {
callback(new Error('command not found'), '', 'command not found');
return mockChildProcess();
});
mockExecFileOnce((callback) => callback(new Error('command not found'), '', 'command not found'));
const result = await isTailscaleAvailable();
expect(result.available).toBe(false);
@@ -62,17 +63,8 @@ describe('tailscale', () => {
describe('startTailscaleServe', () => {
it('calls tailscale serve with correct args', async () => {
mockExecFile
// serve command
.mockImplementationOnce((_cmd, _args, _opts, callback: ExecFileCallback) => {
callback(null, '', '');
return mockChildProcess();
})
// status for hostname
.mockImplementationOnce((_cmd, _args, _opts, callback: ExecFileCallback) => {
callback(null, JSON.stringify({ Self: { DNSName: 'myhost.tailnet.ts.net.' } }), '');
return mockChildProcess();
});
mockExecFileOnce((callback) => callback(null, '', ''));
mockExecFileOnce((callback) => callback(null, JSON.stringify({ Self: { DNSName: 'myhost.tailnet.ts.net.' } }), ''));
const url = await startTailscaleServe({ localPort: 18800 });
expect(url).toBe('https://myhost.tailnet.ts.net');
@@ -83,15 +75,8 @@ describe('tailscale', () => {
});
it('uses custom serve port', async () => {
mockExecFile
.mockImplementationOnce((_cmd, _args, _opts, callback: ExecFileCallback) => {
callback(null, '', '');
return mockChildProcess();
})
.mockImplementationOnce((_cmd, _args, _opts, callback: ExecFileCallback) => {
callback(null, JSON.stringify({ Self: { DNSName: 'myhost.tailnet.ts.net.' } }), '');
return mockChildProcess();
});
mockExecFileOnce((callback) => callback(null, '', ''));
mockExecFileOnce((callback) => callback(null, JSON.stringify({ Self: { DNSName: 'myhost.tailnet.ts.net.' } }), ''));
const url = await startTailscaleServe({ localPort: 18800, servePort: 8443 });
expect(url).toBe('https://myhost.tailnet.ts.net:8443');
@@ -103,10 +88,7 @@ describe('tailscale', () => {
describe('stopTailscaleServe', () => {
it('calls tailscale serve off', async () => {
mockExecFile.mockImplementationOnce((_cmd, _args, _opts, callback: ExecFileCallback) => {
callback(null, '', '');
return mockChildProcess();
});
mockExecFileOnce((callback) => callback(null, '', ''));
await stopTailscaleServe({ localPort: 18800 });
@@ -117,10 +99,7 @@ describe('tailscale', () => {
});
it('does not throw on failure', async () => {
mockExecFile.mockImplementationOnce((_cmd, _args, _opts, callback: ExecFileCallback) => {
callback(new Error('failed'), '', 'failed');
return mockChildProcess();
});
mockExecFileOnce((callback) => callback(new Error('failed'), '', 'failed'));
// Should not throw
await stopTailscaleServe({ localPort: 18800 });