Skip to main content
Glama
edge-cases.test.ts7.06 kB
import { describe, test, expect, vi, beforeEach } from 'vitest'; import * as fsUtils from '../fs-utils.js'; import * as searchUtils from '../search-utils.js'; import { getMimeType } from '../mime-types.js'; // Mock modules vi.mock('../fs-utils.js'); vi.mock('../search-utils.js'); describe('Edge Cases', () => { beforeEach(() => { vi.clearAllMocks(); }); describe('Empty directories', () => { test('handles empty directories correctly', async () => { vi.mocked(fsUtils.listDirectory).mockResolvedValue([]); const result = await fsUtils.listDirectory('/empty', '.', true, 10); expect(result).toEqual([]); }); test('handles directories with only subdirectories', async () => { const dirOnlyStructure = [ { name: 'src', path: '/src', type: 'directory' as const, children: [] }, { name: 'tests', path: '/tests', type: 'directory' as const, children: [] } ]; vi.mocked(fsUtils.listDirectory).mockResolvedValue(dirOnlyStructure); const result = await fsUtils.listDirectory('/project', '.', true, 10); expect(result).toHaveLength(2); expect(result.every(item => item.type === 'directory')).toBe(true); }); }); describe('Very long file paths', () => { test('handles paths near system limits', async () => { // Most systems have a 255 character filename limit const longFileName = 'a'.repeat(250) + '.txt'; const longPath = '/very/deep/nested/directory/structure/' + longFileName; vi.mocked(fsUtils.readFileContent).mockResolvedValue('content'); const content = await fsUtils.readFileContent(longPath); expect(content).toBe('content'); }); test('handles deeply nested paths', async () => { // Create a path with 50 levels const deepPath = Array(50).fill('level').join('/') + '/file.txt'; vi.mocked(fsUtils.normalizeAndValidatePath).mockReturnValue(deepPath); const normalized = fsUtils.normalizeAndValidatePath('/root', deepPath); expect(normalized).toBe(deepPath); }); }); describe('Special characters in filenames', () => { test('handles Unicode filenames', async () => { const unicodeFiles = [ { name: '测试文件.txt', path: '/测试文件.txt', type: 'file' as const }, { name: 'файл.js', path: '/файл.js', type: 'file' as const }, { name: '🚀🎉.md', path: '/🚀🎉.md', type: 'file' as const } ]; vi.mocked(fsUtils.listDirectory).mockResolvedValue(unicodeFiles); const result = await fsUtils.listDirectory('/unicode', '.', true, 10); expect(result).toEqual(unicodeFiles); }); test('handles filenames with spaces and special chars', async () => { const specialFiles = [ { name: 'file with spaces.txt', path: '/file with spaces.txt', type: 'file' as const }, { name: 'file-with-dashes.js', path: '/file-with-dashes.js', type: 'file' as const }, { name: 'file_with_underscores.py', path: '/file_with_underscores.py', type: 'file' as const }, { name: 'file@symbol.txt', path: '/file@symbol.txt', type: 'file' as const } ]; vi.mocked(fsUtils.listDirectory).mockResolvedValue(specialFiles); const result = await fsUtils.listDirectory('/special', '.', true, 10); expect(result).toHaveLength(4); }); }); describe('Symbolic links', () => { test('handles symbolic links safely', async () => { const filesWithSymlink = [ { name: 'real-file.txt', path: '/real-file.txt', type: 'file' as const }, { name: 'link-to-file', path: '/link-to-file', type: 'file' as const } // symlink ]; vi.mocked(fsUtils.listDirectory).mockResolvedValue(filesWithSymlink); const result = await fsUtils.listDirectory('/links', '.', true, 10); expect(result).toHaveLength(2); }); test('prevents circular symlink traversal', async () => { // Simulate a directory that links to itself vi.mocked(fsUtils.listDirectory).mockImplementation(async (root, dir, recursive, depth) => { if (!depth || depth <= 0) return []; return [{ name: 'circular', path: '/circular', type: 'directory' as const, children: [] // Would normally cause infinite loop }]; }); const result = await fsUtils.listDirectory('/circular', '.', true, 5); expect(result).toBeDefined(); }); }); describe('File size edge cases', () => { test('handles zero-byte files', async () => { vi.mocked(fsUtils.readFileContent).mockResolvedValue(''); const content = await fsUtils.readFileContent('/empty.txt'); expect(content).toBe(''); }); test('handles very large files', async () => { // Simulate a 100MB file const largeContent = 'x'.repeat(100 * 1024 * 1024); vi.mocked(fsUtils.readFileContent).mockResolvedValue(largeContent); const content = await fsUtils.readFileContent('/large.bin'); expect(content.length).toBe(100 * 1024 * 1024); }); }); describe('MIME type edge cases', () => { test('handles files without extensions', () => { expect(getMimeType('README')).toBe('text/plain'); expect(getMimeType('Dockerfile')).toBe('text/plain'); expect(getMimeType('Makefile')).toBe('text/plain'); }); test('handles multiple extensions', () => { expect(getMimeType('archive.tar.gz')).toBe('application/gzip'); expect(getMimeType('file.test.js')).toBe('application/javascript'); }); test('handles unknown extensions', () => { expect(getMimeType('file.xyz123')).toBe('text/plain'); expect(getMimeType('file.unknown')).toBe('text/plain'); }); }); describe('Search pattern edge cases', () => { test('handles empty search results', async () => { vi.mocked(searchUtils.searchByPath).mockResolvedValue([]); const results = await searchUtils.searchByPath('/root', '*.nonexistent'); expect(results).toEqual([]); }); test('handles special regex characters in search', async () => { vi.mocked(searchUtils.searchContent).mockResolvedValue([]); // These characters have special meaning in regex const specialQueries = ['[test]', '(test)', 'test.', 'test*', 'test+', 'test?']; for (const query of specialQueries) { await searchUtils.searchContent('/root', query); expect(searchUtils.searchContent).toHaveBeenCalled(); } }); test('handles very long search patterns', async () => { const longPattern = '*'.repeat(100) + '.txt'; vi.mocked(searchUtils.searchByPath).mockResolvedValue([]); const results = await searchUtils.searchByPath('/root', longPattern); expect(results).toEqual([]); }); }); });

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/davstr1/peekabooMCP'

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