import { describe, expect, it } from 'vitest' import { createExcludeMatcher, entryContext, sortEntries } from './fileEntries' const dir = (name: string): { name: string, isDirectory: boolean } => ({ name, isDirectory: true }) const file = (name: string): { name: string, isDirectory: boolean } => ({ name, isDirectory: false }) describe('文件树排序', () => { it('目录在前、文件在后,名字不区分大小写', () => { const sorted = sortEntries([file('b.ts'), dir('src'), file('A.ts'), dir('Docs'), file('a.md')]) expect(sorted.map(e => e.name)).toEqual(['Docs', 'src', 'a.md', 'A.ts', 'b.ts']) }) it('名字里的数字按数值比', () => { expect(sortEntries([file('item10.ts'), file('item2.ts'), file('item1.ts')]).map(e => e.name)) .toEqual(['item1.ts', 'item2.ts', 'item10.ts']) }) it('只差大小写的名字次序稳定,不依赖输入顺序', () => { const a = sortEntries([file('readme.md'), file('README.md')]).map(e => e.name) const b = sortEntries([file('README.md'), file('readme.md')]).map(e => e.name) expect(a).toEqual(b) }) }) describe('行的 contextValue', () => { it('工作区根、目录、文件各一种,菜单按它挂「添加注释」', () => { expect(entryContext({ isDirectory: true, isRoot: true })).toBe('root') expect(entryContext({ isDirectory: true, isRoot: false })).toBe('folder') expect(entryContext({ isDirectory: false, isRoot: false })).toBe('file') }) it('文件行可以带标记(「更改」区能暂存的 file unstaged),目录、根不带', () => { expect(entryContext({ isDirectory: false, isRoot: false }, 'unstaged')).toBe('file unstaged') expect(entryContext({ isDirectory: true, isRoot: false }, 'unstaged')).toBe('folder') expect(entryContext({ isDirectory: true, isRoot: true }, 'unstaged')).toBe('root') }) it('删掉的文件行最后带 deleted(菜单按它不挂「打开更改」),改了、新加的不带', () => { expect(entryContext({ isDirectory: false, isRoot: false, change: 'D' })).toBe('file deleted') expect(entryContext({ isDirectory: false, isRoot: false, change: 'D' }, 'unstaged')).toBe('file unstaged deleted') expect(entryContext({ isDirectory: false, isRoot: false, change: 'M' }, 'unstaged')).toBe('file unstaged') expect(entryContext({ isDirectory: false, isRoot: false, change: 'A' })).toBe('file') }) }) describe('files.exclude', () => { const none = new Set() it('默认的排除项(.git、.DS_Store 等)在任意层级都生效', () => { const excluded = createExcludeMatcher({ '**/.git': true, '**/.DS_Store': true, '**/node_modules': true }) expect(excluded('.git', none)).toBe(true) expect(excluded('packages/app/.DS_Store', none)).toBe(true) expect(excluded('node_modules', none)).toBe(true) expect(excluded('src/.gitignore', none)).toBe(false) expect(excluded('src/index.ts', none)).toBe(false) }) it('值为 false 的规则不排除;没有配置时什么都不排除', () => { expect(createExcludeMatcher({ '**/dist': false })('dist', none)).toBe(false) expect(createExcludeMatcher(undefined)('dist', none)).toBe(false) }) it('不带 **/ 的规则只匹配工作区根下的路径', () => { const excluded = createExcludeMatcher({ build: true }) expect(excluded('build', none)).toBe(true) expect(excluded('src/build', none)).toBe(false) }) it('* 也匹配点开头的名字,花括号展开可用', () => { const excluded = createExcludeMatcher({ '**/*.{log,tmp}': true }) expect(excluded('.debug.log', none)).toBe(true) expect(excluded('.github/x.tmp', none)).toBe(true) expect(excluded('x.ts', none)).toBe(false) }) it('when 条件:有同名的兄弟文件才排除', () => { const excluded = createExcludeMatcher({ '**/*.js': { when: '$(basename).ts' } }) expect(excluded('src/app.js', new Set(['app.js', 'app.ts']))).toBe(true) expect(excluded('src/tool.js', new Set(['tool.js', 'app.ts']))).toBe(false) }) })