84 lines
2.9 KiB
TypeScript
84 lines
2.9 KiB
TypeScript
|
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||
|
|
import { mkdtempSync, rmSync, existsSync } from 'node:fs';
|
||
|
|
import { join } from 'node:path';
|
||
|
|
import { tmpdir } from 'node:os';
|
||
|
|
import { loadConfig, saveConfig, mergeConfig, getConfigPath, DEFAULT_CONFIG } from '../../src/config/index.js';
|
||
|
|
|
||
|
|
let tempDir: string;
|
||
|
|
|
||
|
|
beforeEach(() => {
|
||
|
|
tempDir = mkdtempSync(join(tmpdir(), 'mcpctl-test-'));
|
||
|
|
});
|
||
|
|
|
||
|
|
afterEach(() => {
|
||
|
|
rmSync(tempDir, { recursive: true, force: true });
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('getConfigPath', () => {
|
||
|
|
it('returns path within config dir', () => {
|
||
|
|
const path = getConfigPath('/tmp/mcpctl');
|
||
|
|
expect(path).toBe('/tmp/mcpctl/config.json');
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('loadConfig', () => {
|
||
|
|
it('returns defaults when no config file exists', () => {
|
||
|
|
const config = loadConfig({ configDir: tempDir });
|
||
|
|
expect(config).toEqual(DEFAULT_CONFIG);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('loads config from file', () => {
|
||
|
|
saveConfig({ ...DEFAULT_CONFIG, daemonUrl: 'http://custom:5000' }, { configDir: tempDir });
|
||
|
|
const config = loadConfig({ configDir: tempDir });
|
||
|
|
expect(config.daemonUrl).toBe('http://custom:5000');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('applies defaults for missing fields', () => {
|
||
|
|
const { writeFileSync } = require('node:fs') as typeof import('node:fs');
|
||
|
|
writeFileSync(join(tempDir, 'config.json'), '{"daemonUrl":"http://x:1"}');
|
||
|
|
const config = loadConfig({ configDir: tempDir });
|
||
|
|
expect(config.daemonUrl).toBe('http://x:1');
|
||
|
|
expect(config.registries).toEqual(['official', 'glama', 'smithery']);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('saveConfig', () => {
|
||
|
|
it('creates config file', () => {
|
||
|
|
saveConfig(DEFAULT_CONFIG, { configDir: tempDir });
|
||
|
|
expect(existsSync(join(tempDir, 'config.json'))).toBe(true);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('creates config directory if missing', () => {
|
||
|
|
const nested = join(tempDir, 'nested', 'dir');
|
||
|
|
saveConfig(DEFAULT_CONFIG, { configDir: nested });
|
||
|
|
expect(existsSync(join(nested, 'config.json'))).toBe(true);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('round-trips configuration', () => {
|
||
|
|
const custom = {
|
||
|
|
...DEFAULT_CONFIG,
|
||
|
|
daemonUrl: 'http://custom:9000',
|
||
|
|
registries: ['official' as const],
|
||
|
|
outputFormat: 'json' as const,
|
||
|
|
};
|
||
|
|
saveConfig(custom, { configDir: tempDir });
|
||
|
|
const loaded = loadConfig({ configDir: tempDir });
|
||
|
|
expect(loaded).toEqual(custom);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('mergeConfig', () => {
|
||
|
|
it('merges overrides into existing config', () => {
|
||
|
|
saveConfig(DEFAULT_CONFIG, { configDir: tempDir });
|
||
|
|
const merged = mergeConfig({ daemonUrl: 'http://new:1234' }, { configDir: tempDir });
|
||
|
|
expect(merged.daemonUrl).toBe('http://new:1234');
|
||
|
|
expect(merged.registries).toEqual(DEFAULT_CONFIG.registries);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('works when no config file exists', () => {
|
||
|
|
const merged = mergeConfig({ outputFormat: 'yaml' }, { configDir: tempDir });
|
||
|
|
expect(merged.outputFormat).toBe('yaml');
|
||
|
|
expect(merged.daemonUrl).toBe('http://localhost:3000');
|
||
|
|
});
|
||
|
|
});
|