Skip to main content
Glama
filePlaceholderResolver.test.ts8.98 kB
import { describe, it, expect, beforeEach, afterEach } from '@jest/globals'; import { writeFileSync, mkdirSync, rmSync, existsSync } from 'fs'; import { join } from 'path'; import { resolveFilePlaceholders, hasFilePlaceholders, extractFilePlaceholders } from '../utils/filePlaceholderResolver.js'; import { FilePlaceholderError, FILE_PLACEHOLDER_ERROR_CODES } from '../utils/filePlaceholderTypes.js'; describe('File Placeholder Resolver', () => { const testDir = join(process.cwd(), 'test-files'); const testFile1 = join(testDir, 'script1.js'); const testFile2 = join(testDir, 'template.html'); const testFile3 = join(testDir, 'config.json'); const largeFile = join(testDir, 'large.txt'); beforeEach(() => { // Create test directory if (!existsSync(testDir)) { mkdirSync(testDir, { recursive: true }); } // Create test files writeFileSync(testFile1, 'console.log("Hello from script1");\nconst x = 42;'); writeFileSync(testFile2, '<div>Hello World</div>\n<p>This is a template</p>'); writeFileSync(testFile3, '{"name": "test", "value": 123}'); // Create a large file (2MB) for size testing const largeContent = 'x'.repeat(2 * 1024 * 1024); writeFileSync(largeFile, largeContent); }); afterEach(() => { // Clean up test files if (existsSync(testDir)) { rmSync(testDir, { recursive: true, force: true }); } }); describe('Basic placeholder resolution', () => { it('should resolve simple file placeholder', () => { const input = `{{file:${testFile1}}}`; const result = resolveFilePlaceholders(input); expect(result.data).toBe('console.log("Hello from script1");\nconst x = 42;'); expect(result.result.resolved).toBe(true); expect(result.result.placeholderCount).toBe(1); expect(result.result.resolvedFiles).toEqual([testFile1]); }); it('should resolve multiple placeholders in single string', () => { const input = `Script: {{file:${testFile1}}}\nTemplate: {{file:${testFile2}}}`; const result = resolveFilePlaceholders(input); expect(result.data).toContain('console.log("Hello from script1")'); expect(result.data).toContain('<div>Hello World</div>'); expect(result.result.placeholderCount).toBe(2); expect(result.result.resolvedFiles).toEqual([testFile1, testFile2]); }); it('should handle strings without placeholders', () => { const input = 'This is a normal string without placeholders'; const result = resolveFilePlaceholders(input); expect(result.data).toBe(input); expect(result.result.resolved).toBe(false); expect(result.result.placeholderCount).toBe(0); }); }); describe('Object and array resolution', () => { it('should resolve placeholders in objects', () => { const input = { name: 'test', script: `{{file:${testFile1}}}`, template: `{{file:${testFile2}}}`, value: 123 }; const result = resolveFilePlaceholders(input); expect(result.data.name).toBe('test'); expect(result.data.script).toContain('console.log("Hello from script1")'); expect(result.data.template).toContain('<div>Hello World</div>'); expect(result.data.value).toBe(123); expect(result.result.placeholderCount).toBe(2); }); it('should resolve placeholders in arrays', () => { const input = [ `{{file:${testFile1}}}`, 'normal string', `{{file:${testFile2}}}` ]; const result = resolveFilePlaceholders(input); expect(result.data[0]).toContain('console.log("Hello from script1")'); expect(result.data[1]).toBe('normal string'); expect(result.data[2]).toContain('<div>Hello World</div>'); expect(result.result.placeholderCount).toBe(2); }); it('should resolve placeholders in nested structures', () => { const input = { scripts: [ { name: 'script1', content: `{{file:${testFile1}}}` }, { name: 'script2', content: 'normal content' } ], config: { template: `{{file:${testFile2}}}`, value: 42 } }; const result = resolveFilePlaceholders(input); expect(result.data.scripts[0].content).toContain('console.log("Hello from script1")'); expect(result.data.scripts[1].content).toBe('normal content'); expect(result.data.config.template).toContain('<div>Hello World</div>'); expect(result.data.config.value).toBe(42); expect(result.result.placeholderCount).toBe(2); }); }); describe('Error handling', () => { it('should throw error for non-existent file', () => { const input = '{{file:/nonexistent/file.js}}'; expect(() => resolveFilePlaceholders(input)).toThrow(FilePlaceholderError); try { resolveFilePlaceholders(input); } catch (error) { expect(error).toBeInstanceOf(FilePlaceholderError); expect((error as FilePlaceholderError).code).toBe(FILE_PLACEHOLDER_ERROR_CODES.FILE_PLACEHOLDER_NOT_FOUND); expect((error as FilePlaceholderError).placeholder).toBe('{{file:/nonexistent/file.js}}'); } }); it('should throw error for file size exceeded', () => { const input = `{{file:${largeFile}}}`; expect(() => resolveFilePlaceholders(input)).toThrow(FilePlaceholderError); try { resolveFilePlaceholders(input); } catch (error) { expect(error).toBeInstanceOf(FilePlaceholderError); expect((error as FilePlaceholderError).code).toBe(FILE_PLACEHOLDER_ERROR_CODES.FILE_PLACEHOLDER_SIZE_EXCEEDED); } }); it('should throw error for relative paths', () => { const input = '{{file:test-files/script1.js}}'; expect(() => resolveFilePlaceholders(input)).toThrow(FilePlaceholderError); try { resolveFilePlaceholders(input); } catch (error) { expect(error).toBeInstanceOf(FilePlaceholderError); expect((error as FilePlaceholderError).code).toBe(FILE_PLACEHOLDER_ERROR_CODES.FILE_PLACEHOLDER_INVALID_PATH); expect((error as FilePlaceholderError).message).toContain('must be absolute'); } }); it('should throw error for directory traversal attempts', () => { const input = '{{file:/etc/../../../etc/passwd}}'; expect(() => resolveFilePlaceholders(input)).toThrow(FilePlaceholderError); try { resolveFilePlaceholders(input); } catch (error) { expect(error).toBeInstanceOf(FilePlaceholderError); expect((error as FilePlaceholderError).code).toBe(FILE_PLACEHOLDER_ERROR_CODES.FILE_PLACEHOLDER_INVALID_PATH); } }); }); describe('Configuration', () => { it('should use custom max file size', () => { const input = `{{file:${largeFile}}}`; // Should work with larger size limit const result = resolveFilePlaceholders(input, { maxFileSize: 5 * 1024 * 1024 }); expect(result.result.resolved).toBe(true); }); }); describe('Utility functions', () => { it('should detect file placeholders', () => { expect(hasFilePlaceholders('{{file:test.js}}')).toBe(true); expect(hasFilePlaceholders('normal string')).toBe(false); expect(hasFilePlaceholders('{{file:test.js}} and {{file:other.js}}')).toBe(true); }); it('should extract file placeholders', () => { const input = '{{file:test.js}} and {{file:other.js}} and normal text'; const placeholders = extractFilePlaceholders(input); expect(placeholders).toEqual(['test.js', 'other.js']); }); it('should handle malformed placeholders gracefully', () => { const input = '{{file:test.js} and {{file:}} and normal text'; const result = resolveFilePlaceholders(input); // Should not resolve any placeholders (all are malformed) expect(result.data).toBe(input); expect(result.result.placeholderCount).toBe(0); }); }); describe('Edge cases', () => { it('should handle empty strings', () => { const result = resolveFilePlaceholders(''); expect(result.data).toBe(''); expect(result.result.resolved).toBe(false); }); it('should handle null and undefined', () => { expect(resolveFilePlaceholders(null).data).toBe(null); expect(resolveFilePlaceholders(undefined).data).toBe(undefined); }); it('should handle numbers and booleans', () => { expect(resolveFilePlaceholders(42).data).toBe(42); expect(resolveFilePlaceholders(true).data).toBe(true); }); it('should preserve file content exactly', () => { const input = '{{file:test-files/script1.js}}'; const result = resolveFilePlaceholders(input); // Should preserve exact content including newlines expect(result.data).toBe('console.log("Hello from script1");\nconst x = 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/ClearSkye/SkyeNet-MCP-ACE'

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