mirror of
https://github.com/stablyai/orca.git
synced 2026-10-23 08:03:39 +00:00
179 lines
6.4 KiB
TypeScript
179 lines
6.4 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest'
|
|
import type { Repo } from './types'
|
|
import {
|
|
buildDefaultWorktreeSourcePreferenceUpdate,
|
|
buildWorktreeSourcePreferenceUpdate
|
|
} from './worktree-visibility-source-preferences'
|
|
import {
|
|
createWorktreeVisibilitySourceMatcher,
|
|
effectiveBuiltInWorktreeSourceVisibility,
|
|
effectiveCustomWorktreeSourceVisibility,
|
|
normalizeCustomWorktreeVisibilitySources,
|
|
normalizeWorktreeVisibilitySourcePreferences,
|
|
resolveCustomWorktreeVisibilitySources
|
|
} from './worktree-visibility-sources'
|
|
|
|
function repo(overrides: Partial<Repo> = {}): Repo {
|
|
return {
|
|
id: 'repo-1',
|
|
path: '/repo',
|
|
displayName: 'repo',
|
|
addedAt: 1,
|
|
...overrides,
|
|
badgeColor: overrides.badgeColor ?? '#fff'
|
|
}
|
|
}
|
|
|
|
describe('worktree visibility sources', () => {
|
|
it('classifies each built-in independently across linked checkouts', () => {
|
|
const classify = createWorktreeVisibilitySourceMatcher(['/repo', '/worktrees/feature'])
|
|
expect(classify('/repo/.claude/worktrees/review')).toEqual({
|
|
kind: 'built-in',
|
|
id: 'claude'
|
|
})
|
|
expect(classify('/worktrees/feature/.gsd-workspaces/phase-1')).toEqual({
|
|
kind: 'built-in',
|
|
id: 'gsd'
|
|
})
|
|
expect(classify('/other/.claude/worktrees/review')).toBeNull()
|
|
})
|
|
|
|
it('matches custom descendants with Windows and WSL comparison semantics', () => {
|
|
const windows = createWorktreeVisibilitySourceMatcher(
|
|
[],
|
|
[{ id: 'team', rootPath: 'C:\\Users\\Dev\\Team' }]
|
|
)
|
|
expect(windows('c:\\users\\dev\\team\\feature')).toEqual({
|
|
kind: 'custom',
|
|
id: 'team'
|
|
})
|
|
|
|
const wsl = createWorktreeVisibilitySourceMatcher(
|
|
[],
|
|
[{ id: 'linux', rootPath: '//wsl$/Ubuntu/home/dev/team' }]
|
|
)
|
|
expect(wsl('//wsl.localhost/Ubuntu/home/dev/team/feature')).toEqual({
|
|
kind: 'custom',
|
|
id: 'linux'
|
|
})
|
|
expect(wsl('//wsl.localhost/Ubuntu/home/Dev/team/feature')).toBeNull()
|
|
})
|
|
|
|
it('gives built-ins precedence over overlapping custom roots', () => {
|
|
const classify = createWorktreeVisibilitySourceMatcher(
|
|
['/repo'],
|
|
[{ id: 'overlap', rootPath: '/repo/.claude/worktrees' }]
|
|
)
|
|
expect(classify('/repo/.claude/worktrees/review')).toEqual({
|
|
kind: 'built-in',
|
|
id: 'claude'
|
|
})
|
|
})
|
|
|
|
it('normalizes each candidate once regardless of checkout count', () => {
|
|
const classify = createWorktreeVisibilitySourceMatcher(
|
|
Array.from({ length: 200 }, (_, index) => `/repo/worktree-${index}`),
|
|
Array.from({ length: 32 }, (_, index) => ({
|
|
id: `custom-${index}`,
|
|
rootPath: `/custom/${index}`
|
|
}))
|
|
)
|
|
const normalize = vi.spyOn(String.prototype, 'normalize')
|
|
|
|
classify('/unmatched/worktree')
|
|
|
|
expect(normalize).toHaveBeenCalledTimes(1)
|
|
normalize.mockRestore()
|
|
})
|
|
|
|
it('migrates the optional legacy agent policy lazily for both built-ins', () => {
|
|
const legacy = repo({ agentWorktreeVisibility: 'show' })
|
|
expect(effectiveBuiltInWorktreeSourceVisibility(legacy, 'claude')).toBe('show')
|
|
expect(effectiveBuiltInWorktreeSourceVisibility(legacy, 'gsd')).toBe('show')
|
|
expect(
|
|
buildWorktreeSourcePreferenceUpdate(legacy, { kind: 'built-in', id: 'claude' }, 'hide')
|
|
).toEqual({ builtIn: { claude: 'hide', gsd: 'show' } })
|
|
})
|
|
|
|
it('inherits global built-in and custom visibility without stamping sibling defaults', () => {
|
|
const defaults = {
|
|
external: 'hide' as const,
|
|
customSources: [{ id: 'team', rootPath: '/srv/team' }],
|
|
sourcePreferences: {
|
|
builtIn: { claude: 'show' as const, gsd: 'show' as const },
|
|
custom: { team: 'show' as const }
|
|
}
|
|
}
|
|
const inherited = repo()
|
|
|
|
expect(effectiveBuiltInWorktreeSourceVisibility(inherited, 'gsd', defaults)).toBe('show')
|
|
expect(effectiveCustomWorktreeSourceVisibility(inherited, 'team', defaults)).toBe('show')
|
|
expect(
|
|
buildWorktreeSourcePreferenceUpdate(inherited, { kind: 'built-in', id: 'claude' }, 'hide')
|
|
).toEqual({ builtIn: { claude: 'hide' } })
|
|
expect(
|
|
buildWorktreeSourcePreferenceUpdate(inherited, { kind: 'custom', id: 'team' }, 'hide')
|
|
).toEqual({ custom: { team: 'hide' } })
|
|
expect(inherited.worktreeVisibilitySourcePreferences).toBeUndefined()
|
|
})
|
|
|
|
it('resolves global custom roots for every repo and keeps new global defaults isolated', () => {
|
|
const defaults = {
|
|
external: 'hide' as const,
|
|
customSources: [{ id: 'global', rootPath: '/srv/global-worktrees' }]
|
|
}
|
|
for (const checkout of ['/repos/alpha', '/repos/beta']) {
|
|
const current = repo({ path: checkout })
|
|
const classify = createWorktreeVisibilitySourceMatcher(
|
|
[checkout],
|
|
resolveCustomWorktreeVisibilitySources(current, defaults)
|
|
)
|
|
expect(classify('/srv/global-worktrees/feature')).toEqual({
|
|
kind: 'custom',
|
|
id: 'global'
|
|
})
|
|
}
|
|
expect(
|
|
buildDefaultWorktreeSourcePreferenceUpdate(defaults, { kind: 'custom', id: 'global' }, 'hide')
|
|
).toEqual({ custom: { global: 'hide' } })
|
|
})
|
|
|
|
it('bounds and sanitizes persisted source definitions and preferences', () => {
|
|
expect(
|
|
normalizeCustomWorktreeVisibilitySources([
|
|
{ id: 'team', rootPath: ' /srv/team/ ' },
|
|
{ id: 'duplicate-root', rootPath: '/srv/team' },
|
|
{ id: 'relative', rootPath: '../team' },
|
|
{ id: 'bad id', rootPath: '/srv/other' }
|
|
])
|
|
).toEqual([{ id: 'team', rootPath: '/srv/team/' }])
|
|
expect(
|
|
normalizeWorktreeVisibilitySourcePreferences({
|
|
builtIn: { claude: 'show', gsd: 'invalid', unknown: 'show' },
|
|
custom: { team: 'hide', nope: 'invalid' }
|
|
})
|
|
).toEqual({ builtIn: { claude: 'show' }, custom: { team: 'hide' } })
|
|
})
|
|
|
|
it('rejects drive-relative Windows roots and caps after validation', () => {
|
|
const invalid = Array.from({ length: 32 }, (_, index) => ({
|
|
id: `bad-${index}`,
|
|
rootPath: 'relative'
|
|
}))
|
|
expect(
|
|
normalizeCustomWorktreeVisibilitySources([...invalid, { id: 'team', rootPath: '/srv/team' }])
|
|
).toEqual([{ id: 'team', rootPath: '/srv/team' }])
|
|
expect(
|
|
normalizeCustomWorktreeVisibilitySources([
|
|
{ id: 'drive-relative', rootPath: 'C:Users\\dev\\team' },
|
|
{ id: 'root-relative', rootPath: '\\Users\\dev\\team' },
|
|
{ id: 'drive', rootPath: 'C:\\Users\\dev\\team' },
|
|
{ id: 'unc', rootPath: '\\\\server\\share\\team' }
|
|
])
|
|
).toEqual([
|
|
{ id: 'drive', rootPath: 'C:\\Users\\dev\\team' },
|
|
{ id: 'unc', rootPath: '\\\\server\\share\\team' }
|
|
])
|
|
})
|
|
})
|