mirror of
https://github.com/stablyai/orca.git
synced 2026-11-13 17:37:40 +00:00
* test: remove low-value suites and cases * test: fix retained timestamps and prune flaky baseline * test: document malformed persisted-provider fixture cast * test: restore types used by retained divergence regressions
157 lines
4.9 KiB
TypeScript
157 lines
4.9 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
|
|
import type { GitStatusEntry } from './git-status-types'
|
|
import {
|
|
buildGitStatusSourceControlTree,
|
|
buildSourceControlTree,
|
|
applyGitStatusEntryAreasToSourceControlTree,
|
|
collectSourceControlTreeFileEntries,
|
|
compactSourceControlTree,
|
|
flattenSourceControlTree,
|
|
namespaceSourceControlTreeDirectoryKeys
|
|
} from './source-control-tree'
|
|
|
|
function entry(partial: Partial<GitStatusEntry> & { path: string }): GitStatusEntry {
|
|
return {
|
|
status: 'modified',
|
|
area: 'unstaged',
|
|
...partial
|
|
}
|
|
}
|
|
|
|
function labels(nodes: ReturnType<typeof flattenSourceControlTree>): string[] {
|
|
return nodes.map((node) => `${node.type}:${node.path}`)
|
|
}
|
|
|
|
describe('buildSourceControlTree', () => {
|
|
it('orders numbered sibling directories naturally, matching the file rows', () => {
|
|
const tree = buildSourceControlTree('unstaged', [
|
|
entry({ path: 'migrations/100 - b/a.sql' }),
|
|
entry({ path: 'migrations/9 - a/a.sql' }),
|
|
entry({ path: 'migrations/99 - c/a.sql' })
|
|
])
|
|
|
|
expect(labels(flattenSourceControlTree(tree, new Set()))).toEqual([
|
|
'directory:migrations',
|
|
'directory:migrations/9 - a',
|
|
'file:migrations/9 - a/a.sql',
|
|
'directory:migrations/99 - c',
|
|
'file:migrations/99 - c/a.sql',
|
|
'directory:migrations/100 - b',
|
|
'file:migrations/100 - b/a.sql'
|
|
])
|
|
})
|
|
|
|
it('keeps conflict rows ahead of normal rows within a directory', () => {
|
|
const tree = buildGitStatusSourceControlTree('unstaged', [
|
|
entry({ path: 'src/a.ts' }),
|
|
entry({
|
|
path: 'src/z.ts',
|
|
conflictKind: 'both_modified',
|
|
conflictStatus: 'unresolved'
|
|
})
|
|
])
|
|
|
|
expect(labels(flattenSourceControlTree(tree, new Set()))).toEqual([
|
|
'directory:src',
|
|
'file:src/z.ts',
|
|
'file:src/a.ts'
|
|
])
|
|
})
|
|
|
|
it('omits collapsed directory descendants from the visible rows', () => {
|
|
const tree = buildSourceControlTree('staged', [
|
|
entry({ path: 'src/app.ts', area: 'staged' }),
|
|
entry({ path: 'docs/readme.md', area: 'staged' })
|
|
])
|
|
const collapsed = new Set(['dir::staged::src'])
|
|
|
|
expect(labels(flattenSourceControlTree(tree, collapsed))).toEqual([
|
|
'directory:docs',
|
|
'file:docs/readme.md',
|
|
'directory:src'
|
|
])
|
|
})
|
|
|
|
it('collects all descendant file entries for directory actions', () => {
|
|
const tree = buildSourceControlTree('unstaged', [
|
|
entry({ path: 'src/app.ts' }),
|
|
entry({ path: 'src/components/Button.tsx' }),
|
|
entry({ path: 'docs/readme.md' })
|
|
])
|
|
|
|
const src = tree.find((node) => node.type === 'directory' && node.path === 'src')
|
|
|
|
expect(src ? collectSourceControlTreeFileEntries(src).map((item) => item.path) : []).toEqual([
|
|
'src/components/Button.tsx',
|
|
'src/app.ts'
|
|
])
|
|
})
|
|
|
|
it('compacts single-child directory chains for visible source-control rows', () => {
|
|
const tree = buildSourceControlTree('branch', [
|
|
{ path: 'src/renderer/src/mockups.css', status: 'modified' },
|
|
{ path: 'src/renderer/src/components/App.tsx', status: 'added' }
|
|
])
|
|
|
|
const compacted = compactSourceControlTree(tree)
|
|
|
|
expect(labels(flattenSourceControlTree(compacted, new Set()))).toEqual([
|
|
'directory:src/renderer/src',
|
|
'directory:src/renderer/src/components',
|
|
'file:src/renderer/src/components/App.tsx',
|
|
'file:src/renderer/src/mockups.css'
|
|
])
|
|
expect(compacted[0]).toMatchObject({
|
|
name: 'src/renderer/src',
|
|
path: 'src/renderer/src',
|
|
depth: 0,
|
|
key: 'dir::branch::src/renderer/src'
|
|
})
|
|
})
|
|
|
|
it('preserves real branching folders when compacting directory chains', () => {
|
|
const tree = buildSourceControlTree('unstaged', [
|
|
entry({ path: 'src/main/index.ts' }),
|
|
entry({ path: 'src/renderer/index.ts' })
|
|
])
|
|
|
|
const compacted = compactSourceControlTree(tree)
|
|
|
|
expect(labels(flattenSourceControlTree(compacted, new Set()))).toEqual([
|
|
'directory:src',
|
|
'directory:src/main',
|
|
'file:src/main/index.ts',
|
|
'directory:src/renderer',
|
|
'file:src/renderer/index.ts'
|
|
])
|
|
})
|
|
|
|
it('can preserve file node areas from mixed conflict section entries', () => {
|
|
const tree = compactSourceControlTree(
|
|
buildGitStatusSourceControlTree('unstaged', [
|
|
entry({
|
|
area: 'staged',
|
|
path: 'src/resolved.ts',
|
|
conflictKind: 'both_modified',
|
|
conflictStatus: 'resolved_locally'
|
|
})
|
|
])
|
|
)
|
|
|
|
const rows = flattenSourceControlTree(
|
|
applyGitStatusEntryAreasToSourceControlTree(
|
|
namespaceSourceControlTreeDirectoryKeys(tree, 'conflicts')
|
|
),
|
|
new Set()
|
|
)
|
|
const directory = rows.find((node) => node.type === 'directory')
|
|
const file = rows.find((node) => node.type === 'file')
|
|
|
|
expect(directory?.key).toBe('dir::conflicts::src')
|
|
expect(directory?.area).toBe('unstaged')
|
|
expect(file?.key).toBe('staged::src/resolved.ts')
|
|
expect(file?.area).toBe('staged')
|
|
})
|
|
})
|