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.
This commit is contained in:
Tam Nhu Tran
2026-05-10 20:23:02 -04:00
parent 43ece40c21
commit 9d0690e1a8
2 changed files with 21 additions and 1 deletions
@@ -16,6 +16,18 @@ describe('cliproxy routing command dispatch', () => {
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(' ')}`);
},
}));
});
@@ -618,7 +618,15 @@ global.fetch = async (url) => {
const preloadPath = join(tempDir, 'mock-fetch.cjs');
const ccsHome = join(tempDir, 'home');
const fallbackTracePath = join(ccsHome, '.ccs', 'logs', 'websearch-trace.jsonl');
const disallowedTracePath = join(process.cwd(), '.tmp-websearch-trace-unsafe.jsonl');
// disallowedTracePath MUST NOT start with any safe prefix (tmpdir(),
// /var/log, or <CCS_HOME>/.ccs/logs). Anchoring under cwd or homedir
// is unsafe in CI/Bun-test environments where those paths can fall
// under /tmp (CI runner workspace) or under tmpdir (Bun's HOME
// isolation), which would falsely satisfy the tmpdir prefix. Use a
// root-anchored path outside every safe prefix so the hook MUST
// reject it. The hook writes via try/catch; a permission denial here
// also leaves the file absent.
const disallowedTracePath = '/etc/ccs-test-disallowed-websearch-trace-' + Date.now() + '.jsonl';
const html = `
<a class="result__a" href="/l/?uddg=https%3A%2F%2Fexample.com%2Farticle">Example title</a>
<a class="result__snippet">Example snippet</a>