Files
ccs/tests/unit/commands/cliproxy-routing-subcommand.test.ts
T
Tam Nhu Tran 9d0690e1a8 test(ci): make routing mock complete and websearch trace path env-robust
Two pre-existing test bugs surfaced under CCS CI on the new claw self-
hosted runners but stayed hidden locally:

1. tests/unit/commands/cliproxy-routing-subcommand.test.ts mocks the
   routing-subcommand module with only 3 exports, but
   src/commands/cliproxy/index.ts statically imports 6. Bun resolves
   the static import graph against the mock and reports
     SyntaxError: Export named 'handleRoutingAffinitySet' not found
   for every test in the file. Add the missing 3 exports
   (handleRoutingAffinityStatus, handleRoutingAffinityHelp,
   handleRoutingAffinitySet) to the mock and document why the mock
   must mirror every named export of the target module.

2. tests/unit/hooks/websearch-transformer.test.ts builds the
   "disallowed" trace path from process.cwd() and from os.homedir().
   Both fall under the os.tmpdir() safe-prefix in two real
   environments: CI runners with cwd == /tmp/runner/work/... and Bun
   test isolation that re-roots HOME under tmpdir. The hook treats
   them as safe, writes the trace, and the assertion that the file
   does NOT exist fails. Anchor disallowedTracePath under /etc/...
   instead so it cannot satisfy the tmpdir, /var/log, or
   <CCS_HOME>/.ccs/logs prefixes in any host environment.

Both fixes are independent of the OAuth callback traceability change
that this branch otherwise carries, but ship together so the PR
clears CI on the new runner stack.
2026-05-10 20:23:02 -04:00

61 lines
2.0 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, mock } from 'bun:test';
describe('cliproxy routing command dispatch', () => {
let calls: string[] = [];
beforeEach(() => {
calls = [];
mock.module('../../../src/commands/cliproxy/routing-subcommand', () => ({
handleRoutingStatus: async () => {
calls.push('status');
},
handleRoutingExplain: async () => {
calls.push('explain');
},
handleRoutingSet: async (args: string[]) => {
calls.push(`set:${args.join(' ')}`);
},
// Mock module must expose every named export `cliproxy/index.ts`
// statically imports from this module, otherwise Bun reports
// `Export named 'X' not found` at module-graph resolution time.
handleRoutingAffinityStatus: async () => {
calls.push('affinity:status');
},
handleRoutingAffinityHelp: async () => {
calls.push('affinity:help');
},
handleRoutingAffinitySet: async (args: string[]) => {
calls.push(`affinity:set:${args.join(' ')}`);
},
}));
});
afterEach(() => {
mock.restore();
});
async function loadHandleCliproxyCommand() {
const mod = await import(`../../../src/commands/cliproxy/index?test=${Date.now()}-${Math.random()}`);
return mod.handleCliproxyCommand;
}
it('shows routing status by default', async () => {
const handleCliproxyCommand = await loadHandleCliproxyCommand();
await handleCliproxyCommand(['routing']);
expect(calls).toEqual(['status']);
});
it('shows the routing explainer', async () => {
const handleCliproxyCommand = await loadHandleCliproxyCommand();
await handleCliproxyCommand(['routing', 'explain']);
expect(calls).toEqual(['explain']);
});
it('passes the explicit strategy to set', async () => {
const handleCliproxyCommand = await loadHandleCliproxyCommand();
await handleCliproxyCommand(['routing', 'set', 'fill-first']);
expect(calls).toEqual(['set:fill-first']);
});
});