import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import fs from 'fs/promises';
import path from 'path';
import { handleSearchByTime } from '../src/tools/searchByTime/handler.js';
const TEST_ROOT = path.resolve(__dirname, 'test-env');
// Mock config
process.env.ALLOW_ROOTS = TEST_ROOT;
describe('fs.search_by_time', () => {
beforeAll(async () => {
// Setup test environment
await fs.mkdir(TEST_ROOT, { recursive: true });
const now = Date.now();
// File A: 1 hour ago
await fs.writeFile(path.join(TEST_ROOT, 'fileA.txt'), 'A');
await fs.utimes(path.join(TEST_ROOT, 'fileA.txt'), new Date(now - 3600000), new Date(now - 3600000));
// File B: 2 hours ago
await fs.writeFile(path.join(TEST_ROOT, 'fileB.txt'), 'B');
await fs.utimes(path.join(TEST_ROOT, 'fileB.txt'), new Date(now - 7200000), new Date(now - 7200000));
// File C: 30 mins ago
await fs.writeFile(path.join(TEST_ROOT, 'fileC.md'), 'C');
await fs.utimes(path.join(TEST_ROOT, 'fileC.md'), new Date(now - 1800000), new Date(now - 1800000));
// Subdir
await fs.mkdir(path.join(TEST_ROOT, 'subdir'));
await fs.writeFile(path.join(TEST_ROOT, 'subdir', 'fileD.txt'), 'D');
await fs.utimes(path.join(TEST_ROOT, 'subdir', 'fileD.txt'), new Date(now - 100000), new Date(now - 100000));
});
afterAll(async () => {
// Cleanup
await fs.rm(TEST_ROOT, { recursive: true, force: true });
});
it('should find all files sorted by time desc', async () => {
const result = await handleSearchByTime({
root: TEST_ROOT,
path: "",
timeField: "modified",
recursive: true,
includeFiles: true,
includeDirectories: false,
sort: "time_desc",
limit: 10
});
expect(result.results).toHaveLength(4);
// Order: D (newest), C, A, B (oldest)
expect(result.results[0].path).toContain('fileD.txt');
expect(result.results[1].path).toBe('fileC.md');
expect(result.results[2].path).toBe('fileA.txt');
expect(result.results[3].path).toBe('fileB.txt');
});
it('should filter by glob', async () => {
const result = await handleSearchByTime({
root: TEST_ROOT,
path: "",
timeField: "modified",
recursive: true,
includeFiles: true,
includeDirectories: false,
sort: "time_desc",
limit: 10,
glob: "**/*.md"
});
expect(result.results).toHaveLength(1);
expect(result.results[0].path).toBe('fileC.md');
});
it('should filter by time range', async () => {
const now = Date.now();
const result = await handleSearchByTime({
root: TEST_ROOT,
path: "",
timeField: "modified",
recursive: true,
includeFiles: true,
includeDirectories: false,
sort: "time_desc",
limit: 10,
from: new Date(now - 4000000).toISOString(), // ~1.1 hours ago
to: new Date(now - 1000000).toISOString() // ~0.3 hours ago
});
expect(result.results).toHaveLength(2);
const paths = result.results.map(r => r.path).sort();
expect(paths).toEqual(['fileA.txt', 'fileC.md']);
});
it('should handle pagination', async () => {
// Page 1: limit 2
const result1 = await handleSearchByTime({
root: TEST_ROOT,
path: "",
timeField: "modified",
recursive: true,
includeFiles: true,
includeDirectories: false,
sort: "time_desc",
limit: 2
});
expect(result1.results).toHaveLength(2);
expect(result1.nextCursor).toBeDefined();
// Page 2
const result2 = await handleSearchByTime({
root: TEST_ROOT,
path: "",
timeField: "modified",
recursive: true,
includeFiles: true,
includeDirectories: false,
sort: "time_desc",
limit: 2,
cursor: result1.nextCursor
});
expect(result2.results).toHaveLength(2);
const allPaths = [...result1.results, ...result2.results].map(r => r.path);
expect(allPaths).toContain('subdir/fileD.txt');
expect(allPaths).toContain('fileC.md');
expect(allPaths).toContain('fileA.txt');
expect(allPaths).toContain('fileB.txt');
});
});