Skip to main content
Glama
jsonToYamlString.config.test.ts11.9 kB
import { describe, it, expect, beforeAll } from 'vitest'; import { jsonToYamlString, YamlConversionConfig, } from '../src/jsonToYamlString'; import { getTokenizer, countTokens, calculateTokenSavingsPercentage, } from './helpers/tokenizer'; beforeAll(async () => { await getTokenizer(); }); describe('jsonToYamlString Configuration Options', () => { const testData = { name: 'John Doe', age: 30, id: 'user-123', type: 'person', description: 'A test user', active: true, email: 'john@example.com', version: '1.0.0', status: 'active', url: 'https://example.com', path: '/users/john', roles: ['admin', 'user'], settings: { theme: 'dark', notifications: true, language: 'en', }, }; describe('Default behavior (no configuration)', () => { it('should preserve original key order when no config is provided', () => { const yaml = jsonToYamlString(testData); const lines = yaml.split('\n').filter(line => line.trim()); // Should start with 'name' as it's first in the original object expect(lines[0]).toBe('name: "John Doe"'); expect(lines[1]).toBe('age: 30'); expect(lines[2]).toBe('id: "user-123"'); }); it('should preserve original key order with empty config', () => { const yaml = jsonToYamlString(testData, {}); const lines = yaml.split('\n').filter(line => line.trim()); expect(lines[0]).toBe('name: "John Doe"'); expect(lines[1]).toBe('age: 30'); expect(lines[2]).toBe('id: "user-123"'); }); }); describe('sortKeys: true configuration', () => { it('should sort keys alphabetically when sortKeys is true', () => { const config: YamlConversionConfig = { sortKeys: true }; const yaml = jsonToYamlString(testData, config); const lines = yaml .split('\n') .filter(line => line.trim() && !line.startsWith(' ')); // Top-level keys should be in alphabetical order expect(lines[0]).toBe('active: true'); expect(lines[1]).toBe('age: 30'); expect(lines[2]).toBe('description: "A test user"'); expect(lines[3]).toBe('email: "john@example.com"'); expect(lines[4]).toBe('id: "user-123"'); expect(lines[5]).toBe('name: "John Doe"'); }); it('should sort nested object keys alphabetically', () => { const config: YamlConversionConfig = { sortKeys: true }; const yaml = jsonToYamlString(testData, config); // Check that nested settings keys are also sorted expect(yaml).toContain( `settings: language: "en" notifications: true theme: "dark"` ); }); it('should maintain token efficiency with alphabetical sorting', () => { const config: YamlConversionConfig = { sortKeys: true }; const json = JSON.stringify(testData, null, 2); const yaml = jsonToYamlString(testData, config); const jsonTokens = countTokens(json); const yamlTokens = countTokens(yaml); expect(yamlTokens).toBeLessThan(jsonTokens); const savingsPercentage = calculateTokenSavingsPercentage( jsonTokens, yamlTokens ); expect(savingsPercentage).toBeGreaterThan(15); // Should still have significant savings }); }); describe('keysPriority configuration', () => { it('should prioritize specified keys in order', () => { const config: YamlConversionConfig = { keysPriority: ['id', 'name', 'type', 'version'], }; const yaml = jsonToYamlString(testData, config); const lines = yaml .split('\n') .filter(line => line.trim() && !line.startsWith(' ')); // Priority keys should appear first in specified order expect(lines[0]).toBe('id: "user-123"'); expect(lines[1]).toBe('name: "John Doe"'); expect(lines[2]).toBe('type: "person"'); expect(lines[3]).toBe('version: "1.0.0"'); }); it('should place non-priority keys alphabetically after priority keys', () => { const config: YamlConversionConfig = { keysPriority: ['id', 'name'], }; const yaml = jsonToYamlString(testData, config); const lines = yaml .split('\n') .filter(line => line.trim() && !line.startsWith(' ')); // First two should be priority keys expect(lines[0]).toBe('id: "user-123"'); expect(lines[1]).toBe('name: "John Doe"'); // Remaining keys should be alphabetical expect(lines[2]).toBe('active: true'); expect(lines[3]).toBe('age: 30'); expect(lines[4]).toBe('description: "A test user"'); }); it('should handle empty keysPriority array', () => { const config: YamlConversionConfig = { keysPriority: [], }; const yaml = jsonToYamlString(testData, config); const lines = yaml.split('\n').filter(line => line.trim()); // Should preserve original order when keysPriority is empty expect(lines[0]).toBe('name: "John Doe"'); expect(lines[1]).toBe('age: 30'); }); it('should handle keysPriority with non-existent keys', () => { const config: YamlConversionConfig = { keysPriority: ['nonexistent', 'id', 'name', 'alsononexistent'], }; const yaml = jsonToYamlString(testData, config); const lines = yaml .split('\n') .filter(line => line.trim() && !line.startsWith(' ')); // Only existing priority keys should appear first expect(lines[0]).toBe('id: "user-123"'); expect(lines[1]).toBe('name: "John Doe"'); // Rest should be alphabetical expect(lines[2]).toBe('active: true'); }); it('should work with nested objects', () => { const nestedData = { user: { name: 'Alice', id: 'user-456', age: 25, type: 'admin', }, metadata: { version: '2.0.0', created: '2024-01-01', id: 'meta-123', }, }; const config: YamlConversionConfig = { keysPriority: ['id', 'name', 'type'], }; const yaml = jsonToYamlString(nestedData, config); // Check that nested objects also respect priority sorting expect(yaml).toContain( `user: id: "user-456" name: "Alice" type: "admin"` ); expect(yaml).toContain( `metadata: id: "meta-123" created: "2024-01-01" version: "2.0.0"` ); }); }); describe('Configuration precedence', () => { it('should use keysPriority when both sortKeys and keysPriority are provided', () => { const config: YamlConversionConfig = { sortKeys: true, keysPriority: ['name', 'id'], }; const yaml = jsonToYamlString(testData, config); const lines = yaml .split('\n') .filter(line => line.trim() && !line.startsWith(' ')); // keysPriority should take precedence over sortKeys expect(lines[0]).toBe('name: "John Doe"'); expect(lines[1]).toBe('id: "user-123"'); // Remaining keys should still be alphabetical expect(lines[2]).toBe('active: true'); expect(lines[3]).toBe('age: 30'); }); it('should ignore sortKeys when keysPriority is provided', () => { const config1: YamlConversionConfig = { sortKeys: true, keysPriority: ['version', 'name'], }; const config2: YamlConversionConfig = { sortKeys: false, keysPriority: ['version', 'name'], }; const yaml1 = jsonToYamlString(testData, config1); const yaml2 = jsonToYamlString(testData, config2); // Both should produce the same result since keysPriority takes precedence expect(yaml1).toBe(yaml2); }); }); describe('LLM optimization scenarios', () => { it('should optimize for API response data with common priority keys', () => { const apiResponse = { data: [ { created_at: '2024-01-01T00:00:00Z', id: 'item-1', name: 'First Item', type: 'product', description: 'A sample product', status: 'active', updated_at: '2024-01-02T00:00:00Z', version: '1.0.0', }, ], pagination: { total: 100, page: 1, limit: 10, has_more: true, }, status: 'success', message: 'Data retrieved successfully', }; const config: YamlConversionConfig = { keysPriority: ['id', 'name', 'type', 'status', 'version', 'message'], }; const yaml = jsonToYamlString(apiResponse, config); const json = JSON.stringify(apiResponse, null, 2); // Verify token efficiency const jsonTokens = countTokens(json); const yamlTokens = countTokens(yaml); expect(yamlTokens).toBeLessThan(jsonTokens); // Verify important keys appear first in nested objects expect(yaml).toContain( `data: - id: "item-1" name: "First Item" type: "product"` ); expect(yaml).toContain( `status: "success" message: "Data retrieved successfully"` ); }); it('should handle configuration objects with priority sorting', () => { const configData = { environment: 'production', database: { host: 'localhost', port: 5432, name: 'myapp', ssl: true, timeout: 30000, }, cache: { ttl: 3600, host: 'redis-server', port: 6379, enabled: true, }, logging: { level: 'info', format: 'json', enabled: true, }, }; const config: YamlConversionConfig = { keysPriority: [ 'name', 'host', 'port', 'enabled', 'level', 'environment', ], }; const yaml = jsonToYamlString(configData, config); // Verify nested objects respect priority expect(yaml).toContain( `database: name: "myapp" host: "localhost" port: 5432` ); expect(yaml).toContain( `cache: host: "redis-server" port: 6379 enabled: true` ); expect(yaml).toContain(`logging: enabled: true level: "info"`); }); }); describe('Edge cases and error handling', () => { it('should handle null and undefined values in keysPriority', () => { const simpleData = { a: 1, b: 2, c: 3 }; const config: YamlConversionConfig = { keysPriority: ['b', 'a'], }; const yaml = jsonToYamlString(simpleData, config); const lines = yaml.split('\n').filter(line => line.trim()); expect(lines[0]).toBe('b: 2'); expect(lines[1]).toBe('a: 1'); expect(lines[2]).toBe('c: 3'); }); it('should handle arrays correctly with configuration', () => { const arrayData = { items: ['first', 'second', 'third'], count: 3, id: 'list-1', }; const config: YamlConversionConfig = { keysPriority: ['id', 'count'], }; const yaml = jsonToYamlString(arrayData, config); expect(yaml).toContain( `id: "list-1" count: 3 items: - "first" - "second" - "third"` ); }); it('should maintain consistent output format regardless of configuration', () => { const data = { name: 'test', value: 42 }; const yaml1 = jsonToYamlString(data); const yaml2 = jsonToYamlString(data, { sortKeys: true }); const yaml3 = jsonToYamlString(data, { keysPriority: ['value', 'name'] }); // All should use forced quotes and same formatting expect(yaml1).toContain('name: "test"'); expect(yaml2).toContain('name: "test"'); expect(yaml3).toContain('name: "test"'); expect(yaml1).toContain('value: 42'); expect(yaml2).toContain('value: 42'); expect(yaml3).toContain('value: 42'); }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bgauryy/octocode-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server