/** * Unit tests for findBrainFiles TTL cache. */ import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; import { findBrainFiles, invalidateBrainFilesCache } from '../src/utils'; function makeBrain(): string { const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'astra-brain-cache-')); fs.writeFileSync(path.join(dir, 'a.md'), '# A'); fs.writeFileSync(path.join(dir, 'b.md'), '# B'); return dir; } describe('findBrainFiles TTL cache', () => { let brain: string; beforeEach(() => { brain = makeBrain(); invalidateBrainFilesCache(); }); afterEach(() => { try { fs.rmSync(brain, { recursive: true, force: true }); } catch { /* noop */ } }); test('initial walk lists current files', () => { const files = findBrainFiles(brain); expect(files.length).toBe(2); expect(files.some((f) => f.endsWith('a.md'))).toBe(true); }); test('within TTL: cache returns stale list when files added', () => { findBrainFiles(brain); // prime cache fs.writeFileSync(path.join(brain, 'c.md'), '# C'); const files = findBrainFiles(brain); // Cache hit returns the previous list expect(files.length).toBe(2); }); test('explicit invalidation forces fresh walk', () => { findBrainFiles(brain); // prime fs.writeFileSync(path.join(brain, 'c.md'), '# C'); invalidateBrainFilesCache(brain); const files = findBrainFiles(brain); expect(files.length).toBe(3); }); test('invalidateBrainFilesCache() with no arg clears all entries', () => { const a = makeBrain(); const b = makeBrain(); try { findBrainFiles(a); findBrainFiles(b); fs.writeFileSync(path.join(a, 'extra.md'), 'x'); fs.writeFileSync(path.join(b, 'extra.md'), 'x'); invalidateBrainFilesCache(); expect(findBrainFiles(a).length).toBe(3); expect(findBrainFiles(b).length).toBe(3); } finally { fs.rmSync(a, { recursive: true, force: true }); fs.rmSync(b, { recursive: true, force: true }); } }); test('returned array is a copy — mutations do not poison cache', () => { const first = findBrainFiles(brain); first.length = 0; // mutate caller's copy const second = findBrainFiles(brain); expect(second.length).toBe(2); }); test('non-existent directory returns empty list and does not throw', () => { const fake = path.join(os.tmpdir(), 'astra-no-such-dir-' + Date.now()); const files = findBrainFiles(fake); expect(files).toEqual([]); }); });