import { describe, it, expect, vi, beforeEach } from 'vitest';
// Mock octocode-shared to control platform values
vi.mock('octocode-shared', () => ({
isWindows: false,
isMac: true,
isLinux: false,
HOME: '/Users/test',
getAppDataPath: vi.fn(() => '/Users/test'),
getLocalAppDataPath: vi.fn(() => '/Users/test'),
getPlatformName: vi.fn(() => 'macOS'),
getArchitecture: vi.fn(() => 'arm64'),
}));
vi.mock('node:fs', () => ({
default: {
existsSync: vi.fn(),
statSync: vi.fn(),
readFileSync: vi.fn(),
writeFileSync: vi.fn(),
mkdirSync: vi.fn(),
copyFileSync: vi.fn(),
},
existsSync: vi.fn(),
statSync: vi.fn(),
readFileSync: vi.fn(),
writeFileSync: vi.fn(),
mkdirSync: vi.fn(),
copyFileSync: vi.fn(),
}));
describe('MCP Config Utilities', () => {
beforeEach(() => {
vi.clearAllMocks();
});
describe('getMCPConfigPath', () => {
it('should return Cursor config path for macOS', async () => {
const { getMCPConfigPath } =
await import('../../src/utils/mcp-config.js');
expect(getMCPConfigPath('cursor')).toBe('/Users/test/.cursor/mcp.json');
});
it('should return Claude Desktop config path for macOS', async () => {
const { getMCPConfigPath } =
await import('../../src/utils/mcp-config.js');
expect(getMCPConfigPath('claude-desktop')).toBe(
'/Users/test/Library/Application Support/Claude/claude_desktop_config.json'
);
});
it('should return Claude Code config path', async () => {
const { getMCPConfigPath } =
await import('../../src/utils/mcp-config.js');
expect(getMCPConfigPath('claude-code')).toBe('/Users/test/.claude.json');
});
it('should return Windsurf config path', async () => {
const { getMCPConfigPath } =
await import('../../src/utils/mcp-config.js');
expect(getMCPConfigPath('windsurf')).toBe(
'/Users/test/.codeium/windsurf/mcp_config.json'
);
});
});
describe('getOctocodeServerConfig', () => {
it('should return npx config', async () => {
const { getOctocodeServerConfig } =
await import('../../src/utils/mcp-config.js');
const config = getOctocodeServerConfig('npx');
expect(config.command).toBe('npx');
expect(config.args).toContain('octocode-mcp@latest');
});
it('should return direct config', async () => {
const { getOctocodeServerConfig } =
await import('../../src/utils/mcp-config.js');
const config = getOctocodeServerConfig('direct');
expect(config.command).toBe('bash');
expect(config.args).toBeDefined();
expect(config.args![0]).toBe('-c');
expect(config.args![1]).toContain('curl');
});
it('should add env options when provided', async () => {
const { getOctocodeServerConfig } =
await import('../../src/utils/mcp-config.js');
const config = getOctocodeServerConfig('npx', {
enableLocal: true,
githubToken: 'test-token',
});
expect(config.env).toBeDefined();
expect(config.env!.ENABLE_LOCAL).toBe('true');
expect(config.env!.GITHUB_TOKEN).toBe('test-token');
});
});
describe('mergeOctocodeConfig', () => {
it('should add octocode to empty config', async () => {
const { mergeOctocodeConfig } =
await import('../../src/utils/mcp-config.js');
const result = mergeOctocodeConfig({ mcpServers: {} }, 'npx');
expect(result.mcpServers?.octocode).toBeDefined();
expect(result.mcpServers?.octocode.command).toBe('npx');
});
it('should preserve existing servers', async () => {
const { mergeOctocodeConfig } =
await import('../../src/utils/mcp-config.js');
const existing = {
mcpServers: {
other: { command: 'node', args: ['other.js'] },
},
};
const result = mergeOctocodeConfig(existing, 'npx');
expect(result.mcpServers?.other).toBeDefined();
expect(result.mcpServers?.octocode).toBeDefined();
});
it('should overwrite existing octocode config', async () => {
const { mergeOctocodeConfig } =
await import('../../src/utils/mcp-config.js');
const existing = {
mcpServers: {
octocode: { command: 'old', args: [] },
},
};
const result = mergeOctocodeConfig(existing, 'npx');
expect(result.mcpServers?.octocode.command).toBe('npx');
});
});
describe('isOctocodeConfigured', () => {
it('should return true if octocode is configured', async () => {
const { isOctocodeConfigured } =
await import('../../src/utils/mcp-config.js');
const config = {
mcpServers: {
octocode: { command: 'npx', args: ['octocode-mcp@latest'] },
},
};
expect(isOctocodeConfigured(config)).toBe(true);
});
it('should return false if octocode is not configured', async () => {
const { isOctocodeConfigured } =
await import('../../src/utils/mcp-config.js');
const config = { mcpServers: {} };
expect(isOctocodeConfigured(config)).toBe(false);
});
it('should return false if mcpServers is undefined', async () => {
const { isOctocodeConfigured } =
await import('../../src/utils/mcp-config.js');
const config = {};
expect(isOctocodeConfigured(config)).toBe(false);
});
});
});