UNPKG

@boundless-oss/atlas

Version:

Atlas - MCP Server for comprehensive startup project management

240 lines (191 loc) 8.45 kB
import { VariableResolver } from '../variable-resolver.js'; describe('VariableResolver', () => { let resolver: VariableResolver; beforeEach(() => { resolver = new VariableResolver(); }); describe('resolveVariables', () => { it('should resolve simple string variables', async () => { const input = 'Hello ${name}, welcome to ${place}!'; const context = { name: 'John', place: 'Atlas' }; const result = await resolver.resolveVariables(input, context); expect(result).toBe('Hello John, welcome to Atlas!'); }); it('should handle missing variables', async () => { const input = 'Hello ${name}, your score is ${score}'; const context = { name: 'Alice' }; // score is missing const result = await resolver.resolveVariables(input, context); expect(result).toBe('Hello Alice, your score is ${score}'); }); it('should resolve nested object paths', async () => { const input = 'User ${user.name} from ${user.address.city}'; const context = { user: { name: 'Bob', address: { city: 'New York', country: 'USA' } } }; const result = await resolver.resolveVariables(input, context); expect(result).toBe('User Bob from New York'); }); it('should resolve variables in objects', async () => { const input = { greeting: 'Hello ${name}', message: 'Your balance is ${balance}', nested: { info: 'Location: ${location}' } }; const context = { name: 'Charlie', balance: 100, location: 'SF' }; const result = await resolver.resolveVariables(input, context); expect(result).toEqual({ greeting: 'Hello Charlie', message: 'Your balance is 100', nested: { info: 'Location: SF' } }); }); it('should resolve variables in arrays', async () => { const input = ['Hello ${name}', 'Score: ${score}', { msg: '${message}' }]; const context = { name: 'Dave', score: 42, message: 'Well done!' }; const result = await resolver.resolveVariables(input, context); expect(result).toEqual(['Hello Dave', 'Score: 42', { msg: 'Well done!' }]); }); it('should handle non-string primitives', async () => { const input = { num: 42, bool: true, nil: null }; const context = {}; const result = await resolver.resolveVariables(input, context); expect(result).toEqual({ num: 42, bool: true, nil: null }); }); it('should handle complex nested structures', async () => { const input = { users: [ { name: '${users.0.name}', role: '${users.0.role}' }, { name: '${users.1.name}', role: '${users.1.role}' } ], config: { api: { url: '${env.apiUrl}', key: '${env.apiKey}' } } }; const context = { users: [ { name: 'Admin', role: 'administrator' }, { name: 'User', role: 'member' } ], env: { apiUrl: 'https://api.example.com', apiKey: 'secret-key' } }; const result = await resolver.resolveVariables(input, context); expect(result).toEqual({ users: [ { name: 'Admin', role: 'administrator' }, { name: 'User', role: 'member' } ], config: { api: { url: 'https://api.example.com', key: 'secret-key' } } }); }); }); describe('evaluateCondition', () => { it('should evaluate equality conditions', async () => { const context = { status: 'active', count: 5 }; expect(await resolver.evaluateCondition('status == active', context)).toBe(true); expect(await resolver.evaluateCondition('status === active', context)).toBe(true); expect(await resolver.evaluateCondition('status == inactive', context)).toBe(false); expect(await resolver.evaluateCondition('count == 5', context)).toBe(true); }); it('should evaluate inequality conditions', async () => { const context = { status: 'active', count: 5 }; expect(await resolver.evaluateCondition('status != inactive', context)).toBe(true); expect(await resolver.evaluateCondition('status !== inactive', context)).toBe(true); expect(await resolver.evaluateCondition('count != 10', context)).toBe(true); }); it('should evaluate comparison conditions', async () => { const context = { count: 5, price: 99.99 }; expect(await resolver.evaluateCondition('count > 3', context)).toBe(true); expect(await resolver.evaluateCondition('count >= 5', context)).toBe(true); expect(await resolver.evaluateCondition('count < 10', context)).toBe(true); expect(await resolver.evaluateCondition('count <= 5', context)).toBe(true); expect(await resolver.evaluateCondition('price > 100', context)).toBe(false); }); it('should evaluate boolean literals', async () => { const context = {}; expect(await resolver.evaluateCondition('true', context)).toBe(true); expect(await resolver.evaluateCondition('false', context)).toBe(false); }); it('should evaluate variable existence', async () => { const context = { hasFeature: true, emptyValue: '', zero: 0 }; expect(await resolver.evaluateCondition('hasFeature', context)).toBe(true); expect(await resolver.evaluateCondition('missingVar', context)).toBe(false); expect(await resolver.evaluateCondition('emptyValue', context)).toBe(false); expect(await resolver.evaluateCondition('zero', context)).toBe(false); // 0 is falsy }); it('should resolve variables in conditions', async () => { const context = { user: { role: 'admin' }, threshold: 10, value: 15 }; expect(await resolver.evaluateCondition('${user.role} == admin', context)).toBe(true); expect(await resolver.evaluateCondition('${value} > ${threshold}', context)).toBe(true); }); it('should handle string comparisons with quotes', async () => { const context = { message: 'hello world' }; expect(await resolver.evaluateCondition('message == "hello world"', context)).toBe(true); expect(await resolver.evaluateCondition("message == 'hello world'", context)).toBe(true); expect(await resolver.evaluateCondition('message == "goodbye"', context)).toBe(false); }); it('should handle numeric comparisons', async () => { const context = { strNum: '42', actualNum: 42 }; expect(await resolver.evaluateCondition('strNum > 40', context)).toBe(true); expect(await resolver.evaluateCondition('actualNum > 40', context)).toBe(true); }); it('should handle complex expressions with variables', async () => { const context = { order: { total: 150, discount: 20 }, user: { isPremium: true } }; const condition = '${order.total} > 100'; expect(await resolver.evaluateCondition(condition, context)).toBe(true); }); it('should return false for malformed conditions', async () => { const context = { value: 10 }; expect(await resolver.evaluateCondition('invalid expression @#$', context)).toBe(false); expect(await resolver.evaluateCondition('', context)).toBe(false); }); }); describe('evaluateExpression', () => { it('should evaluate simple expressions', async () => { const context = { price: 100, quantity: 3 }; // For now, just variable substitution const result = await resolver.evaluateExpression('Total: ${price} x ${quantity}', context); expect(result).toBe('Total: 100 x 3'); }); it('should handle nested variable paths in expressions', async () => { const context = { product: { name: 'Widget', price: { amount: 99.99, currency: 'USD' } } }; const result = await resolver.evaluateExpression( '${product.name} costs ${product.price.amount} ${product.price.currency}', context ); expect(result).toBe('Widget costs 99.99 USD'); }); }); });