// @vitest-environment node import { describe, it, expect, beforeAll, afterAll } from 'vitest' import { mkdtempSync, writeFileSync, mkdirSync, rmSync } from 'fs' import { tmpdir } from 'os' import { join } from 'path' import { searchInDir } from '../file-system' describe('searchInDir (主进程多文件搜索)', () => { let dir: string beforeAll(() => { dir = mkdtempSync(join(tmpdir(), 'marklite-search-')) mkdirSync(join(dir, 'sub')) mkdirSync(join(dir, 'node_modules')) writeFileSync(join(dir, 'a.md'), '# Hello\nline two\nWorld hello again\n') writeFileSync(join(dir, 'sub', 'b.markdown'), 'nothing here\nHELLO UPPER\n') writeFileSync(join(dir, 'skip.js'), 'hello in js\n') writeFileSync(join(dir, 'node_modules', 'c.md'), 'hello in deps\n') writeFileSync(join(dir, '.hidden.md'), 'hello hidden\n') }) afterAll(() => { rmSync(dir, { recursive: true, force: true }) }) it('should find matches across files (case-insensitive default)', async () => { const result = await searchInDir({ dirPath: dir, query: 'hello' }) expect(result.success).toBe(true) // a.md: 2 处(# Hello / World hello again) + b.markdown: 1 处(HELLO UPPER) expect(result.matches).toHaveLength(3) expect(result.totalFiles).toBe(2) }) it('should respect case-sensitive option', async () => { const result = await searchInDir({ dirPath: dir, query: 'HELLO', caseSensitive: true }) expect(result.success).toBe(true) expect(result.matches).toHaveLength(1) expect(result.matches?.[0].filePath).toContain('b.markdown') }) it('should support regex search', async () => { const result = await searchInDir({ dirPath: dir, query: '^line', useRegex: true }) expect(result.success).toBe(true) expect(result.matches).toHaveLength(1) expect(result.matches?.[0].line).toBe(2) }) it('should reject invalid regex with error', async () => { const result = await searchInDir({ dirPath: dir, query: '([', useRegex: true }) expect(result.success).toBe(false) expect(result.error).toBe('无效的正则表达式') }) it('should skip node_modules and dotfiles', async () => { const result = await searchInDir({ dirPath: dir, query: 'hidden' }) expect(result.success).toBe(true) expect(result.matches).toHaveLength(0) }) it('should reject empty query', async () => { const result = await searchInDir({ dirPath: dir, query: '' }) expect(result.success).toBe(false) }) it('should return error for invalid directory', async () => { const result = await searchInDir({ dirPath: join(dir, 'nope'), query: 'x' }) // 目录不存在:walk 内部吞掉 readdir 错误,返回 0 结果(success: true) expect(result.success).toBe(true) expect(result.matches).toHaveLength(0) }) })