104 lines
3.4 KiB
TypeScript
104 lines
3.4 KiB
TypeScript
import { describe, it, expect, afterEach } from 'vitest';
|
|
import { loadConfigSafe, redactSecrets, getConfigPath, getDataDir } from './shared.js';
|
|
import { writeFileSync, mkdirSync, rmSync } from 'fs';
|
|
import { join } from 'path';
|
|
import { tmpdir } from 'os';
|
|
|
|
describe('CLI shared utilities', () => {
|
|
const testDir = join(tmpdir(), 'flynn-test-cli-shared');
|
|
|
|
afterEach(() => {
|
|
try { rmSync(testDir, { recursive: true }); } catch {}
|
|
});
|
|
|
|
describe('getConfigPath', () => {
|
|
it('returns FLYNN_CONFIG env var if set', () => {
|
|
const original = process.env.FLYNN_CONFIG;
|
|
process.env.FLYNN_CONFIG = '/custom/path.yaml';
|
|
expect(getConfigPath()).toBe('/custom/path.yaml');
|
|
if (original !== undefined) {
|
|
process.env.FLYNN_CONFIG = original;
|
|
} else {
|
|
delete process.env.FLYNN_CONFIG;
|
|
}
|
|
});
|
|
|
|
it('returns default path if env var not set', () => {
|
|
const original = process.env.FLYNN_CONFIG;
|
|
delete process.env.FLYNN_CONFIG;
|
|
const path = getConfigPath();
|
|
expect(path).toContain('.config/flynn/config.yaml');
|
|
if (original !== undefined) {
|
|
process.env.FLYNN_CONFIG = original;
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('loadConfigSafe', () => {
|
|
it('returns config on success', () => {
|
|
mkdirSync(testDir, { recursive: true });
|
|
const configPath = join(testDir, 'config.yaml');
|
|
writeFileSync(configPath, `
|
|
telegram:
|
|
bot_token: "test-token"
|
|
allowed_chat_ids: [123]
|
|
models:
|
|
default:
|
|
provider: anthropic
|
|
model: claude-sonnet
|
|
`);
|
|
const result = loadConfigSafe(configPath);
|
|
expect(result.config).toBeDefined();
|
|
expect(result.error).toBeUndefined();
|
|
expect(result.config!.telegram.bot_token).toBe('test-token');
|
|
});
|
|
|
|
it('returns error when file not found', () => {
|
|
const result = loadConfigSafe('/nonexistent/config.yaml');
|
|
expect(result.config).toBeUndefined();
|
|
expect(result.error).toBeDefined();
|
|
});
|
|
|
|
it('returns error on invalid YAML', () => {
|
|
mkdirSync(testDir, { recursive: true });
|
|
const configPath = join(testDir, 'bad.yaml');
|
|
writeFileSync(configPath, '{{{{invalid yaml');
|
|
const result = loadConfigSafe(configPath);
|
|
expect(result.config).toBeUndefined();
|
|
expect(result.error).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('redactSecrets', () => {
|
|
it('redacts bot_token', () => {
|
|
const config = {
|
|
telegram: { bot_token: 'secret-token-123', allowed_chat_ids: [123] },
|
|
models: { default: { provider: 'anthropic', model: 'claude' } },
|
|
};
|
|
const redacted = redactSecrets(config);
|
|
const telegram = redacted.telegram as Record<string, unknown>;
|
|
expect(telegram.bot_token).toBe('***');
|
|
expect(telegram.allowed_chat_ids).toEqual([123]);
|
|
});
|
|
|
|
it('redacts api_key in models', () => {
|
|
const config = {
|
|
telegram: { bot_token: 'token', allowed_chat_ids: [123] },
|
|
models: {
|
|
default: { provider: 'anthropic', model: 'claude', api_key: 'sk-secret' },
|
|
},
|
|
};
|
|
const redacted = redactSecrets(config);
|
|
const models = redacted.models as Record<string, Record<string, unknown>>;
|
|
expect(models.default.api_key).toBe('***');
|
|
});
|
|
});
|
|
|
|
describe('getDataDir', () => {
|
|
it('returns path under home directory', () => {
|
|
const dir = getDataDir();
|
|
expect(dir).toContain('.local/share/flynn');
|
|
});
|
|
});
|
|
});
|