From b8687aec1dd3acb953d9893559a306ddf2c7070c Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 22 Nov 2025 01:59:49 +0100 Subject: [PATCH] test: strengthen claude import coverage --- src/config/imports/external.ts | 4 ++- tests/config-imports-unit.test.ts | 55 +++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/config/imports/external.ts b/src/config/imports/external.ts index 3cbc32e..293272c 100644 --- a/src/config/imports/external.ts +++ b/src/config/imports/external.ts @@ -235,7 +235,9 @@ function resolveContainerDescriptor( // For claude-code, only allow root fallback for legacy root-style files (.claude.json, .claude/mcp.json). // Settings files like .claude/settings.json require proper mcpServers/servers/mcp containers. if (importKind === 'claude-code' && filePath) { - const allowRootFallback = filePath.endsWith('.claude.json') || filePath.endsWith(`${path.sep}mcp.json`); + const normalized = path.normalize(filePath); + const allowRootFallback = + normalized.endsWith('.claude.json') || normalized.endsWith(`${path.sep}.claude${path.sep}mcp.json`); return { allowMcpServers: true, allowServers: true, diff --git a/tests/config-imports-unit.test.ts b/tests/config-imports-unit.test.ts index eda15d5..5308ee3 100644 --- a/tests/config-imports-unit.test.ts +++ b/tests/config-imports-unit.test.ts @@ -258,6 +258,61 @@ describe('config import helpers', () => { expect(entries?.has('folder-server')).toBe(true); }); + it('disallows root fallback for mcp.json outside .claude', async () => { + const nestedDir = path.join(TEMP_DIR, 'nested'); + await fs.mkdir(nestedDir, { recursive: true }); + const jsonPath = path.join(nestedDir, 'mcp.json'); + await fs.writeFile( + jsonPath, + JSON.stringify({ + stray: { + command: 'node', + args: ['server.js'], + }, + }), + 'utf8' + ); + const entries = await readExternalEntries(jsonPath, { importKind: 'claude-code' }); + expect(entries?.size ?? 0).toBe(0); + }); + + it('ignores settings.local.json metadata without containers', async () => { + const claudeDir = path.join(TEMP_DIR, '.claude'); + await fs.mkdir(claudeDir, { recursive: true }); + const jsonPath = path.join(claudeDir, 'settings.local.json'); + await fs.writeFile( + jsonPath, + JSON.stringify({ + statusLine: { type: 'command', command: 'bash script.sh' }, + tipsHistory: { shown: ['tip1', 'tip2'] }, + }), + 'utf8' + ); + const entries = await readExternalEntries(jsonPath, { importKind: 'claude-code' }); + expect(entries?.size ?? 0).toBe(0); + }); + + it('respects settings.local.json containers when present', async () => { + const claudeDir = path.join(TEMP_DIR, '.claude'); + await fs.mkdir(claudeDir, { recursive: true }); + const jsonPath = path.join(claudeDir, 'settings.local.json'); + await fs.writeFile( + jsonPath, + JSON.stringify({ + mcpServers: { + 'local-server': { + command: 'node', + args: ['server.js'], + }, + }, + }), + 'utf8' + ); + const entries = await readExternalEntries(jsonPath, { importKind: 'claude-code' }); + expect(entries?.size).toBe(1); + expect(entries?.has('local-server')).toBe(true); + }); + it('uses mcpServers container in settings.json when present', async () => { await fs.mkdir(TEMP_DIR, { recursive: true }); const jsonPath = path.join(TEMP_DIR, 'settings.json');