- 标题栏新按钮「未提交的更改」:树里只剩工作区各 git 仓库里没提交的文件(暂存、没暂存、未跟踪、合并冲突),每个有改动的仓库一个根,跟着 git 状态自动重摆;上色和徽标交给 VS Code 自带的 git 装饰
- 两种筛选互斥,由 TreeFilters 统一管,上下文键合并成 superpowers.codeReader.filter(review / uncommitted)
- 改动文件树改成多根,buildChangedTree 挪到 explorer/changedTree 并改吃 {path, change}
- 内置 git 扩展 API 的类型和加载抽到 src/git/gitApi、gitExtension,提交按钮的监听也改用它
- 文件注释按文件所在的工作区文件夹记,不看树从哪个根摆下来
65 lines
3.0 KiB
TypeScript
65 lines
3.0 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { buildChangedTree } from './changedTree'
|
|
|
|
describe('改动的文件树', () => {
|
|
// 原型「审查 · 改动的文件」里的 6 个文件(schemas.py 是改名的,算修改)
|
|
const files = [
|
|
{ path: 'backend/src/luffy_agent/user/routes.py', change: 'M' },
|
|
{ path: 'backend/tests/user/test_avatar.py', change: 'A' },
|
|
{ path: 'backend/src/luffy_agent/core/storage.py', change: 'M' },
|
|
{ path: 'backend/src/luffy_agent/user/legacy_profile.py', change: 'D' },
|
|
{ path: 'backend/src/luffy_agent/user/services.py', change: 'M' },
|
|
{ path: 'backend/src/luffy_agent/user/schemas.py', change: 'M' },
|
|
] as const
|
|
const tree = buildChangedTree(files)
|
|
const names = (dir: string): string[] => (tree.get(dir) ?? []).map(entry => entry.name)
|
|
|
|
it('目录层级照留,每层只有通往改动的文件的目录', () => {
|
|
expect(names('')).toEqual(['backend'])
|
|
expect(names('backend')).toEqual(['src', 'tests'])
|
|
expect(names('backend/src')).toEqual(['luffy_agent'])
|
|
expect(names('backend/src/luffy_agent')).toEqual(['core', 'user'])
|
|
expect(names('backend/src/luffy_agent/core')).toEqual(['storage.py'])
|
|
expect(names('backend/tests/user')).toEqual(['test_avatar.py'])
|
|
})
|
|
|
|
it('同一层里的文件按名字排,带着各自的改动和相对根目录的路径', () => {
|
|
expect(tree.get('backend/src/luffy_agent/user')).toEqual([
|
|
{ name: 'legacy_profile.py', path: 'backend/src/luffy_agent/user/legacy_profile.py', isDirectory: false, change: 'D' },
|
|
{ name: 'routes.py', path: 'backend/src/luffy_agent/user/routes.py', isDirectory: false, change: 'M' },
|
|
{ name: 'schemas.py', path: 'backend/src/luffy_agent/user/schemas.py', isDirectory: false, change: 'M' },
|
|
{ name: 'services.py', path: 'backend/src/luffy_agent/user/services.py', isDirectory: false, change: 'M' },
|
|
])
|
|
})
|
|
|
|
it('目录没有改动,路径相对根目录', () => {
|
|
expect(tree.get('backend')).toEqual([
|
|
{ name: 'src', path: 'backend/src', isDirectory: true },
|
|
{ name: 'tests', path: 'backend/tests', isDirectory: true },
|
|
])
|
|
})
|
|
|
|
it('目录在前、文件在后,名字不区分大小写,和普通的树一样', () => {
|
|
const mixed = buildChangedTree([
|
|
{ path: 'README.md', change: 'M' },
|
|
{ path: 'src/a.ts', change: 'A' },
|
|
{ path: 'Docs/b.md', change: 'A' },
|
|
{ path: 'package.json', change: 'M' },
|
|
])
|
|
expect(mixed.get('')?.map(entry => entry.name)).toEqual(['Docs', 'src', 'package.json', 'README.md'])
|
|
})
|
|
|
|
it('文件换成同名目录(删掉 a、新加 a/b)两项都留着', () => {
|
|
const replaced = buildChangedTree([{ path: 'a', change: 'D' }, { path: 'a/b', change: 'A' }])
|
|
expect(replaced.get('')).toEqual([
|
|
{ name: 'a', path: 'a', isDirectory: true },
|
|
{ name: 'a', path: 'a', isDirectory: false, change: 'D' },
|
|
])
|
|
expect(replaced.get('a')?.map(entry => entry.change)).toEqual(['A'])
|
|
})
|
|
|
|
it('没有改动的文件时根下面是空的', () => {
|
|
expect(buildChangedTree([]).get('')).toEqual([])
|
|
})
|
|
})
|