Phase 1 - Security: - Add AES-GCM encryption for localStorage fallback - Enforce WSS protocol for non-localhost WebSocket connections - Add URL sanitization to prevent XSS in markdown links Phase 2 - Domain Reorganization: - Create Intelligence Domain with Valtio store and caching - Add unified intelligence-client for Rust backend integration - Migrate from legacy agent-memory, heartbeat, reflection modules Phase 3 - Core Optimization: - Add virtual scrolling for ChatArea with react-window - Implement LRU cache with TTL for intelligence operations - Add message virtualization utilities Additional: - Add OpenFang compatibility test suite - Update E2E test fixtures - Add audit logging infrastructure - Update project documentation and plans Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
170 lines
4.3 KiB
TypeScript
170 lines
4.3 KiB
TypeScript
/**
|
|
* TOML Utility Tests
|
|
*
|
|
* Tests for TOML parsing and configuration handling.
|
|
*/
|
|
|
|
import { describe, it, expect } from 'vitest';
|
|
import { tomlUtils, TomlParseError, TomlStringifyError } from '../src/lib/toml-utils';
|
|
|
|
describe('tomlUtils', () => {
|
|
describe('parse', () => {
|
|
it('should parse basic TOML correctly', () => {
|
|
const toml = `
|
|
[server]
|
|
host = "127.0.0.1"
|
|
port = 4200
|
|
`;
|
|
const result = tomlUtils.parse(toml);
|
|
expect(result).toEqual({
|
|
server: {
|
|
host: '127.0.0.1',
|
|
port: 4200,
|
|
},
|
|
});
|
|
});
|
|
|
|
it('should parse nested tables correctly', () => {
|
|
const toml = `
|
|
[server]
|
|
host = "127.0.0.1"
|
|
|
|
[server.websocket]
|
|
port = 8080
|
|
path = "/ws"
|
|
`;
|
|
const result = tomlUtils.parse(toml);
|
|
expect(result).toEqual({
|
|
server: {
|
|
host: '127.0.0.1',
|
|
websocket: {
|
|
port: 8080,
|
|
path: '/ws',
|
|
},
|
|
},
|
|
});
|
|
});
|
|
|
|
it('should parse arrays correctly', () => {
|
|
const toml = `
|
|
[[servers]]
|
|
name = "primary"
|
|
port = 4200
|
|
|
|
[[servers]]
|
|
name = "secondary"
|
|
port = 4201
|
|
`;
|
|
const result = tomlUtils.parse(toml);
|
|
expect(result).toEqual({
|
|
servers: [
|
|
{ name: 'primary', port: 4200 },
|
|
{ name: 'secondary', port: 4201 },
|
|
],
|
|
});
|
|
});
|
|
|
|
it('should throw TomlParseError on invalid TOML', () => {
|
|
const invalidToml = `
|
|
[invalid
|
|
key = value
|
|
`;
|
|
expect(() => tomlUtils.parse(invalidToml)).toThrow(TomlParseError);
|
|
});
|
|
});
|
|
|
|
describe('stringify', () => {
|
|
it('should stringify basic objects correctly', () => {
|
|
const data = {
|
|
server: {
|
|
host: '127.0.0.1',
|
|
port: 4200,
|
|
},
|
|
};
|
|
const result = tomlUtils.stringify(data);
|
|
expect(result).toContain('host = "127.0.0.1"');
|
|
expect(result).toContain('port = 4200');
|
|
});
|
|
|
|
it('should throw TomlStringifyError on invalid data', () => {
|
|
const circularData: Record<string, unknown> = { self: {} };
|
|
circularData.self = circularData;
|
|
|
|
expect(() => tomlUtils.stringify(circularData)).toThrow(TomlStringifyError);
|
|
});
|
|
});
|
|
|
|
describe('resolveEnvVars', () => {
|
|
it('should resolve environment variables', () => {
|
|
const content = 'api_key = "${API_KEY}"';
|
|
const envVars = { API_KEY: 'secret-key-123' };
|
|
const result = tomlUtils.resolveEnvVars(content, envVars);
|
|
expect(result).toBe('api_key = "secret-key-123"');
|
|
});
|
|
|
|
it('should return empty string for missing env vars', () => {
|
|
const content = 'api_key = "${MISSING_VAR}"';
|
|
const result = tomlUtils.resolveEnvVars(content);
|
|
expect(result).toBe('api_key = ""');
|
|
});
|
|
|
|
it('should handle multiple env vars', () => {
|
|
const content = `
|
|
key1 = "\${VAR1}"
|
|
key2 = "\${VAR2}"
|
|
`;
|
|
const envVars = { VAR1: 'value1', VAR2: 'value2' };
|
|
const result = tomlUtils.resolveEnvVars(content, envVars);
|
|
expect(result).toContain('key1 = "value1"');
|
|
expect(result).toContain('key2 = "value2"');
|
|
});
|
|
});
|
|
|
|
describe('parseWithEnvVars', () => {
|
|
it('should parse TOML with env var resolution', () => {
|
|
const content = `
|
|
[config]
|
|
api_key = "\${API_KEY}"
|
|
model = "gpt-4"
|
|
`;
|
|
const envVars = { API_KEY: 'test-key-456' };
|
|
const result = tomlUtils.parseWithEnvVars(content, envVars);
|
|
expect(result).toEqual({
|
|
config: {
|
|
api_key: 'test-key-456',
|
|
model: 'gpt-4',
|
|
},
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('hasUnresolvedEnvVars', () => {
|
|
it('should return true when env vars are present', () => {
|
|
const content = 'api_key = "${API_KEY}"';
|
|
expect(tomlUtils.hasUnresolvedEnvVars(content)).toBe(true);
|
|
});
|
|
|
|
it('should return false when no env vars', () => {
|
|
const content = 'api_key = "hardcoded-key"';
|
|
expect(tomlUtils.hasUnresolvedEnvVars(content)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('extractEnvVarNames', () => {
|
|
it('should extract all env var names', () => {
|
|
const content = `
|
|
key1 = "\${VAR1}"
|
|
key2 = "\${VAR2}"
|
|
key1 = "\${VAR1}"
|
|
`;
|
|
const result = tomlUtils.extractEnvVarNames(content);
|
|
expect(result).toEqual(['VAR1', 'VAR2']);
|
|
});
|
|
|
|
it('should return empty array for no env vars', () => {
|
|
const content = 'key = "value"';
|
|
expect(tomlUtils.extractEnvVarNames(content)).toEqual([]);
|
|
});
|
|
});
|
|
});
|