Merge pull request #1104 from sgaluza/sgaluza/fix-test-mock-contamination

test(cliproxy): replace process-wide mock.module with DI seams
This commit is contained in:
Kai (Tam Nhu) Tran authored and GitHub committed 2026-04-26 10:17:45 -04:00
commit db3becfbe0
5 files changed
+73 -85

No files matched your search

@@ -1,65 +1,26 @@
import { describe, expect, it, mock } from 'bun:test';
import { describe, expect, it } from 'bun:test';
const ensureBinaryCalls: Array<unknown> = [];
mock.module('../../../src/cliproxy/binary-manager', () => ({
ensureCLIProxyBinary: async (_verbose = false, options?: unknown) => {
ensureBinaryCalls.push(options);
throw new Error(
'CLIProxy Plus binary is not installed locally. Run "ccs cliproxy install" when you have network access.'
);
},
}));
mock.module('../../../src/cliproxy/config-generator', () => ({
ensureConfigDir: () => undefined,
generateConfig: () => '/tmp/cliproxy-config.yaml',
regenerateConfig: () => '/tmp/cliproxy-config.yaml',
configNeedsRegeneration: () => false,
CLIPROXY_DEFAULT_PORT: 8317,
getCliproxyWritablePath: () => '/tmp',
}));
mock.module('../../../src/cliproxy/proxy-detector', () => ({
detectRunningProxy: async () => ({ running: false, verified: false }),
waitForProxyHealthy: async () => false,
}));
mock.module('../../../src/cliproxy/startup-lock', () => ({
withStartupLock: async <T>(fn: () => Promise<T>) => await fn(),
}));
mock.module('../../../src/cliproxy/session-tracker', () => ({
registerSession: () => undefined,
}));
mock.module('../../../src/cliproxy/stats-fetcher', () => ({
isCliproxyRunning: async () => false,
}));
mock.module('../../../src/cliproxy/auth/token-refresh-config', () => ({
getTokenRefreshConfig: () => null,
}));
mock.module('../../../src/cliproxy/auth/token-refresh-worker', () => ({
TokenRefreshWorker: class {
isActive(): boolean {
return false;
}
start(): void {}
stop(): void {}
},
}));
const { ensureCliproxyService } = await import(
`../../../src/cliproxy/service-manager?service-manager-startup=${Date.now()}`
);
import { ensureCliproxyService } from '../../../src/cliproxy/service-manager';
describe('ensureCliproxyService', () => {
it('fails fast without attempting a runtime install when the local binary is missing', async () => {
ensureBinaryCalls.length = 0;
// Inject stubs via the deps seam instead of bun's `mock.module()`. The
// module-level mock approach is process-wide and was previously leaking
// stubbed binary-manager / stats-fetcher modules into unrelated test
// suites (notably cliproxy-stats-routes-*) that import them transitively.
const ensureBinaryCalls: Array<unknown> = [];
const result = await ensureCliproxyService(8317, false);
const result = await ensureCliproxyService(8317, false, {
ensureBinaryFn: async (_verbose, options) => {
ensureBinaryCalls.push(options);
throw new Error(
'CLIProxy Plus binary is not installed locally. Run "ccs cliproxy install" when you have network access.'
);
},
detectRunningProxyFn: async () => ({ running: false, verified: false }),
configNeedsRegenerationFn: () => false,
withStartupLockFn: async (fn) => await fn(),
});
expect(result).toEqual({
started: false,
@@ -91,33 +91,27 @@ describe('version-checker stale cache fallback', () => {
it('skips update lookups when runtime startup prefers the installed binary', async () => {
const { getExecutableName } = await import('../../../src/cliproxy/platform-detector');
const { ensureBinary } = await import('../../../src/cliproxy/binary/lifecycle');
const plusBinDir = path.join(tempHome, '.ccs', 'cliproxy', 'bin', 'plus');
fs.mkdirSync(plusBinDir, { recursive: true });
fs.writeFileSync(path.join(plusBinDir, getExecutableName('plus')), 'binary');
// Verify the contract via dependency injection rather than mock.module().
// bun's mock.module() is process-wide and is NOT undone by mock.restore(),
// which previously leaked a stubbed version-checker into unrelated test
// files (cliproxy-stats-routes-*) that transitively import it.
let checkForUpdatesCalls = 0;
mock.module('../../../src/cliproxy/binary/version-checker', () => ({
checkForUpdates: async () => {
checkForUpdatesCalls += 1;
return {
hasUpdate: false,
currentVersion: '6.8.2-0',
latestVersion: '6.8.2-0',
fromCache: false,
checkedAt: Date.now(),
};
},
fetchLatestVersion: async () => {
throw new Error('fetchLatestVersion should not run when skipAutoUpdate is enabled');
},
isNewerVersion: () => false,
isVersionFaulty: () => false,
}));
const { ensureBinary } = await import(
`../../../src/cliproxy/binary/lifecycle?skip-auto-update=${Date.now()}`
);
const checkForUpdatesSpy = async () => {
checkForUpdatesCalls += 1;
return {
hasUpdate: false,
currentVersion: '6.8.2-0',
latestVersion: '6.8.2-0',
fromCache: false,
checkedAt: Date.now(),
};
};
const binaryPath = await ensureBinary({
version: '6.8.2-0',
@@ -129,6 +123,7 @@ describe('version-checker stale cache fallback', () => {
skipAutoUpdate: true,
allowInstall: true,
backend: 'plus',
checkForUpdatesFn: checkForUpdatesSpy,
});
expect(binaryPath).toBe(path.join(plusBinDir, getExecutableName('plus')));