@@ -29,6 +29,17 @@ import {
2929 mkdirSync
3030} from "node:fs" ;
3131import { homedir } from "node:os" ;
32+ import { join } from "node:path" ;
33+
34+ // The router builds config paths with path.join, which uses backslashes on
35+ // Windows. Build the expected paths the same way (content keys inside the
36+ // JSON fixtures stay POSIX — they come from the mocked homedir()).
37+ const HOME = "/home/user" ;
38+ const CLAUDE_JSON = join ( HOME , ".claude.json" ) ;
39+ const CODEX_DIR = join ( HOME , ".codex" ) ;
40+ const CODEX_TOML = join ( CODEX_DIR , "config.toml" ) ;
41+ const OPENCODE_DIR = join ( HOME , ".config" , "opencode" ) ;
42+ const OPENCODE_JSON = join ( OPENCODE_DIR , "opencode.json" ) ;
3243
3344const createCaller = createCallerFactory ( appRouter ) ;
3445
@@ -119,7 +130,7 @@ describe("mcpConfig router", () => {
119130
120131 it ( "reads claude installation when .claude.json has nodetool MCP server" , async ( ) => {
121132 ( existsSync as ReturnType < typeof vi . fn > ) . mockImplementation (
122- ( p : string ) => p === "/home/user/.claude.json"
133+ ( p : string ) => p === CLAUDE_JSON
123134 ) ;
124135 ( readFileSync as ReturnType < typeof vi . fn > ) . mockReturnValue (
125136 JSON . stringify ( {
@@ -138,12 +149,12 @@ describe("mcpConfig router", () => {
138149 const claude = result . targets . find ( ( t ) => t . target === "claude" ) ;
139150 expect ( claude ?. installed ) . toBe ( true ) ;
140151 expect ( claude ?. url ) . toBe ( "http://127.0.0.1:7777/mcp" ) ;
141- expect ( claude ?. configPath ) . toBe ( "/home/user/.claude.json" ) ;
152+ expect ( claude ?. configPath ) . toBe ( CLAUDE_JSON ) ;
142153 } ) ;
143154
144155 it ( "reads codex installation by regex from config.toml" , async ( ) => {
145156 ( existsSync as ReturnType < typeof vi . fn > ) . mockImplementation (
146- ( p : string ) => p === "/home/user/.codex/config.toml"
157+ ( p : string ) => p === CODEX_TOML
147158 ) ;
148159 ( readFileSync as ReturnType < typeof vi . fn > ) . mockReturnValue (
149160 `# BEGIN NODETOOL MCP
@@ -162,7 +173,7 @@ url = "http://127.0.0.1:7777/mcp"
162173
163174 it ( "reads opencode installation from opencode.json" , async ( ) => {
164175 ( existsSync as ReturnType < typeof vi . fn > ) . mockImplementation (
165- ( p : string ) => p === "/home/user/.config/opencode/opencode.json"
176+ ( p : string ) => p === OPENCODE_JSON
166177 ) ;
167178 ( readFileSync as ReturnType < typeof vi . fn > ) . mockReturnValue (
168179 JSON . stringify ( {
@@ -216,7 +227,7 @@ url = "http://127.0.0.1:7777/mcp"
216227 expect ( result . results ) . toHaveLength ( 1 ) ;
217228 expect ( result . results [ 0 ] ?. target ) . toBe ( "claude" ) ;
218229 expect ( result . results [ 0 ] ?. success ) . toBe ( true ) ;
219- expect ( result . results [ 0 ] ?. configPath ) . toBe ( "/home/user/.claude.json" ) ;
230+ expect ( result . results [ 0 ] ?. configPath ) . toBe ( CLAUDE_JSON ) ;
220231 } ) ;
221232
222233 it ( "uses provided url when specified" , async ( ) => {
@@ -233,11 +244,11 @@ url = "http://127.0.0.1:7777/mcp"
233244 ( existsSync as ReturnType < typeof vi . fn > ) . mockReturnValue ( false ) ;
234245 const caller = createCaller ( makeCtx ( ) ) ;
235246 await caller . mcpConfig . install ( { targets : [ "codex" , "opencode" ] } ) ;
236- expect ( mkdirSync ) . toHaveBeenCalledWith ( "/home/user/.codex" , {
247+ expect ( mkdirSync ) . toHaveBeenCalledWith ( CODEX_DIR , {
237248 recursive : true
238249 } ) ;
239250 expect ( mkdirSync ) . toHaveBeenCalledWith (
240- "/home/user/.config/opencode" ,
251+ OPENCODE_DIR ,
241252 { recursive : true }
242253 ) ;
243254 } ) ;
@@ -246,7 +257,7 @@ url = "http://127.0.0.1:7777/mcp"
246257 ( existsSync as ReturnType < typeof vi . fn > ) . mockReturnValue ( false ) ;
247258 ( writeFileSync as ReturnType < typeof vi . fn > ) . mockImplementation (
248259 ( p : string ) => {
249- if ( p === "/home/user/.claude.json" ) throw new Error ( "disk full" ) ;
260+ if ( p === CLAUDE_JSON ) throw new Error ( "disk full" ) ;
250261 }
251262 ) ;
252263
@@ -281,7 +292,7 @@ url = "http://127.0.0.1:7777/mcp"
281292
282293 it ( "removes nodetool entry from .claude.json when present" , async ( ) => {
283294 ( existsSync as ReturnType < typeof vi . fn > ) . mockImplementation (
284- ( p : string ) => p === "/home/user/.claude.json"
295+ ( p : string ) => p === CLAUDE_JSON
285296 ) ;
286297 ( readFileSync as ReturnType < typeof vi . fn > ) . mockReturnValue (
287298 JSON . stringify ( {
@@ -310,7 +321,7 @@ url = "http://127.0.0.1:7777/mcp"
310321
311322 it ( "removes block from codex config.toml" , async ( ) => {
312323 ( existsSync as ReturnType < typeof vi . fn > ) . mockImplementation (
313- ( p : string ) => p === "/home/user/.codex/config.toml"
324+ ( p : string ) => p === CODEX_TOML
314325 ) ;
315326 ( readFileSync as ReturnType < typeof vi . fn > ) . mockReturnValue (
316327 `[something_else]
0 commit comments