mirror of
https://github.com/stablyai/orca.git
synced 2026-09-26 08:02:38 +00:00
426 lines
13 KiB
TypeScript
426 lines
13 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import type { GlobalSettings, Repo, Worktree, WorktreeMeta } from './types'
|
|
import {
|
|
buildKnownOrcaWorkspaceLayouts,
|
|
classifyWorktreeOwnership,
|
|
effectiveExternalWorktreeVisibility,
|
|
isLegacyRepoForExternalWorktreeVisibility,
|
|
shouldShowWorktree,
|
|
toDetectedWorktree,
|
|
EXTERNAL_WORKTREE_VISIBILITY_ROLLOUT_AT
|
|
} from './worktree-ownership'
|
|
|
|
const LARGE_WORKSPACE_HISTORY_COUNT = 150_000
|
|
|
|
function makeRepo(overrides: Partial<Repo> = {}): Repo {
|
|
return {
|
|
id: 'repo-1',
|
|
path: '/repos/app',
|
|
displayName: 'app',
|
|
badgeColor: '#000',
|
|
addedAt: EXTERNAL_WORKTREE_VISIBILITY_ROLLOUT_AT + 1,
|
|
kind: 'git',
|
|
...overrides
|
|
}
|
|
}
|
|
|
|
function makeWorktree(overrides: Partial<Worktree> = {}): Worktree {
|
|
return {
|
|
id: `repo-1::${overrides.path ?? '/repos/app'}`,
|
|
repoId: 'repo-1',
|
|
path: '/repos/app',
|
|
head: 'abc',
|
|
branch: 'refs/heads/main',
|
|
isBare: false,
|
|
isMainWorktree: true,
|
|
displayName: 'main',
|
|
comment: '',
|
|
linkedIssue: null,
|
|
linkedPR: null,
|
|
linkedLinearIssue: null,
|
|
linkedGitLabMR: null,
|
|
linkedGitLabIssue: null,
|
|
isArchived: false,
|
|
isUnread: false,
|
|
isPinned: false,
|
|
sortOrder: 0,
|
|
lastActivityAt: 0,
|
|
workspaceStatus: 'todo',
|
|
...overrides
|
|
}
|
|
}
|
|
|
|
function makeMeta(overrides: Partial<WorktreeMeta> = {}): WorktreeMeta {
|
|
return {
|
|
displayName: '',
|
|
comment: '',
|
|
linkedIssue: null,
|
|
linkedPR: null,
|
|
linkedLinearIssue: null,
|
|
linkedGitLabMR: null,
|
|
linkedGitLabIssue: null,
|
|
isArchived: false,
|
|
isUnread: false,
|
|
isPinned: false,
|
|
sortOrder: 0,
|
|
lastActivityAt: 0,
|
|
workspaceStatus: 'todo',
|
|
...overrides
|
|
}
|
|
}
|
|
|
|
function makeSettings(overrides: Partial<GlobalSettings> = {}): GlobalSettings {
|
|
return {
|
|
workspaceDir: '/orca/workspaces',
|
|
nestWorkspaces: true,
|
|
workspaceDirHistory: [],
|
|
refreshLocalBaseRefOnWorktreeCreate: false,
|
|
localBaseRefSuggestionDismissed: false,
|
|
branchPrefix: 'none',
|
|
branchPrefixCustom: '',
|
|
enableGitHubAttribution: false,
|
|
theme: 'system',
|
|
appFontFamily: 'Geist',
|
|
editorAutoSave: false,
|
|
editorAutoSaveDelayMs: 1000,
|
|
editorMinimapEnabled: false,
|
|
markdownReviewToolsEnabled: true,
|
|
terminalFontSize: 14,
|
|
terminalFontFamily: 'monospace',
|
|
terminalFontWeight: 400,
|
|
terminalLineHeight: 1.2,
|
|
...overrides
|
|
} as GlobalSettings
|
|
}
|
|
|
|
describe('worktree ownership classification', () => {
|
|
it('treats explicit Orca metadata as managed even outside the workspace root', () => {
|
|
const repo = makeRepo()
|
|
const settings = makeSettings()
|
|
expect(
|
|
classifyWorktreeOwnership({
|
|
repo,
|
|
settings,
|
|
worktree: makeWorktree({ path: '/tmp/outside' }),
|
|
meta: makeMeta({ orcaCreatedAt: 1 }),
|
|
knownOrcaLayouts: buildKnownOrcaWorkspaceLayouts(settings, repo)
|
|
})
|
|
).toBe('orca-managed')
|
|
})
|
|
|
|
it('treats nested Orca workspace paths without metadata as external', () => {
|
|
const repo = makeRepo()
|
|
const settings = makeSettings()
|
|
const layouts = buildKnownOrcaWorkspaceLayouts(settings, repo)
|
|
expect(
|
|
classifyWorktreeOwnership({
|
|
repo,
|
|
settings,
|
|
worktree: makeWorktree({ path: '/orca/workspaces/app/feature' }),
|
|
knownOrcaLayouts: layouts
|
|
})
|
|
).toBe('external')
|
|
expect(
|
|
classifyWorktreeOwnership({
|
|
repo,
|
|
settings,
|
|
worktree: makeWorktree({ path: '/orca/workspaces/other/feature' }),
|
|
knownOrcaLayouts: layouts
|
|
})
|
|
).toBe('external')
|
|
})
|
|
|
|
it('treats explicit Orca creation layout metadata as managed', () => {
|
|
const repo = makeRepo()
|
|
const settings = makeSettings()
|
|
expect(
|
|
classifyWorktreeOwnership({
|
|
repo,
|
|
settings,
|
|
worktree: makeWorktree({ path: '/orca/workspaces/app/feature' }),
|
|
meta: makeMeta({
|
|
orcaCreationWorkspaceLayout: { path: '/orca/workspaces', nestWorkspaces: true }
|
|
}),
|
|
knownOrcaLayouts: buildKnownOrcaWorkspaceLayouts(settings, repo)
|
|
})
|
|
).toBe('orca-managed')
|
|
})
|
|
|
|
it('does not treat metadata-free nested workspace paths as Orca-managed for new repos', () => {
|
|
const repo = makeRepo({ externalWorktreeVisibility: 'hide' })
|
|
const settings = makeSettings()
|
|
const detected = toDetectedWorktree({
|
|
repo,
|
|
settings,
|
|
worktree: makeWorktree({
|
|
path: '/orca/workspaces/app/manual-git-worktree',
|
|
isMainWorktree: false
|
|
}),
|
|
knownOrcaLayouts: buildKnownOrcaWorkspaceLayouts(settings, repo)
|
|
})
|
|
|
|
expect(detected.ownership).toBe('external')
|
|
expect(detected.visible).toBe(false)
|
|
})
|
|
|
|
it('does not treat generic discovery metadata on nested workspace paths as Orca-managed', () => {
|
|
const repo = makeRepo({ externalWorktreeVisibility: 'hide' })
|
|
const settings = makeSettings()
|
|
const detected = toDetectedWorktree({
|
|
repo,
|
|
settings,
|
|
worktree: makeWorktree({
|
|
path: '/orca/workspaces/app/manual-git-worktree',
|
|
isMainWorktree: false
|
|
}),
|
|
meta: makeMeta({ displayName: 'manual-git-worktree' }),
|
|
knownOrcaLayouts: buildKnownOrcaWorkspaceLayouts(settings, repo)
|
|
})
|
|
|
|
expect(detected.ownership).toBe('external')
|
|
expect(detected.visible).toBe(false)
|
|
})
|
|
|
|
it('keeps nested workspace paths visible for legacy repos without explicit visibility', () => {
|
|
const repo = makeRepo()
|
|
const settings = makeSettings()
|
|
const detected = toDetectedWorktree({
|
|
repo,
|
|
settings,
|
|
worktree: makeWorktree({
|
|
path: '/orca/workspaces/app/manual-git-worktree',
|
|
isMainWorktree: false
|
|
}),
|
|
knownOrcaLayouts: buildKnownOrcaWorkspaceLayouts(settings, repo)
|
|
})
|
|
|
|
expect(detected.ownership).toBe('external')
|
|
expect(detected.visible).toBe(true)
|
|
})
|
|
|
|
it('hides metadata-free nested workspace paths for legacy repos that hide external worktrees', () => {
|
|
const repo = makeRepo({
|
|
externalWorktreeVisibility: 'hide',
|
|
externalWorktreeVisibilityLegacy: true
|
|
})
|
|
const settings = makeSettings()
|
|
const detected = toDetectedWorktree({
|
|
repo,
|
|
settings,
|
|
worktree: makeWorktree({
|
|
path: '/orca/workspaces/app/manual-git-worktree',
|
|
isMainWorktree: false
|
|
}),
|
|
knownOrcaLayouts: buildKnownOrcaWorkspaceLayouts(settings, repo)
|
|
})
|
|
|
|
expect(detected.ownership).toBe('external')
|
|
expect(detected.visible).toBe(false)
|
|
})
|
|
|
|
it('treats flat workspace-root descendants as unknown legacy without strong metadata', () => {
|
|
const repo = makeRepo()
|
|
const settings = makeSettings({ nestWorkspaces: false })
|
|
expect(
|
|
classifyWorktreeOwnership({
|
|
repo,
|
|
settings,
|
|
worktree: makeWorktree({ path: '/orca/workspaces/feature' }),
|
|
knownOrcaLayouts: buildKnownOrcaWorkspaceLayouts(settings, repo)
|
|
})
|
|
).toBe('unknown-legacy')
|
|
})
|
|
|
|
it('keeps flat-layout history weak after switching the same root to nested mode', () => {
|
|
const repo = makeRepo()
|
|
const settings = makeSettings({
|
|
nestWorkspaces: true,
|
|
workspaceDirHistory: [{ path: '/orca/workspaces', nestWorkspaces: false }]
|
|
})
|
|
expect(
|
|
classifyWorktreeOwnership({
|
|
repo,
|
|
settings,
|
|
worktree: makeWorktree({ path: '/orca/workspaces/feature' }),
|
|
knownOrcaLayouts: buildKnownOrcaWorkspaceLayouts(settings, repo)
|
|
})
|
|
).toBe('unknown-legacy')
|
|
})
|
|
|
|
it('uses each historical layout nest mode when matching old roots', () => {
|
|
const repo = makeRepo()
|
|
const settings = makeSettings({
|
|
workspaceDir: '/new/workspaces',
|
|
workspaceDirHistory: [{ path: '/old/workspaces', nestWorkspaces: true }]
|
|
})
|
|
expect(
|
|
classifyWorktreeOwnership({
|
|
repo,
|
|
settings,
|
|
worktree: makeWorktree({ path: '/old/workspaces/app/feature' }),
|
|
knownOrcaLayouts: buildKnownOrcaWorkspaceLayouts(settings, repo)
|
|
})
|
|
).toBe('external')
|
|
})
|
|
|
|
it('builds known layouts from large workspace history lists', () => {
|
|
const repo = makeRepo()
|
|
const workspaceDirHistory = Array.from(
|
|
{ length: LARGE_WORKSPACE_HISTORY_COUNT },
|
|
(_, index) => ({
|
|
path: `/history/workspaces-${index}`,
|
|
nestWorkspaces: index % 2 === 0
|
|
})
|
|
)
|
|
const settings = makeSettings({
|
|
workspaceDir: '/new/workspaces',
|
|
workspaceDirHistory
|
|
})
|
|
|
|
const layouts = buildKnownOrcaWorkspaceLayouts(settings, repo)
|
|
|
|
expect(layouts).toHaveLength(LARGE_WORKSPACE_HISTORY_COUNT + 1)
|
|
expect(layouts[0]).toEqual({ path: '/new/workspaces', nestWorkspaces: true })
|
|
expect(layouts[1]).toEqual({ path: '/history/workspaces-0', nestWorkspaces: true })
|
|
expect(layouts.at(-1)).toEqual({
|
|
path: `/history/workspaces-${LARGE_WORKSPACE_HISTORY_COUNT - 1}`,
|
|
nestWorkspaces: false
|
|
})
|
|
})
|
|
|
|
it('handles Windows drive casing and separators', () => {
|
|
const repo = makeRepo({ path: 'C:\\repos\\App' })
|
|
const settings = makeSettings({ workspaceDir: 'C:\\Orca\\Workspaces' })
|
|
expect(
|
|
classifyWorktreeOwnership({
|
|
repo,
|
|
settings,
|
|
worktree: makeWorktree({
|
|
id: 'repo-1::C:\\ORCA\\WORKSPACES\\App\\Feature',
|
|
path: 'C:\\ORCA\\WORKSPACES\\App\\Feature',
|
|
isMainWorktree: false
|
|
}),
|
|
knownOrcaLayouts: buildKnownOrcaWorkspaceLayouts(settings, repo)
|
|
})
|
|
).toBe('external')
|
|
})
|
|
|
|
it('keeps selected linked checkouts visible without trusting Git main-worktree', () => {
|
|
const repo = makeRepo({ path: '/repos/app-linked', externalWorktreeVisibility: 'hide' })
|
|
const settings = makeSettings()
|
|
const selected = toDetectedWorktree({
|
|
repo,
|
|
settings,
|
|
worktree: makeWorktree({
|
|
path: '/repos/app-linked',
|
|
isMainWorktree: false
|
|
}),
|
|
knownOrcaLayouts: buildKnownOrcaWorkspaceLayouts(settings, repo)
|
|
})
|
|
const gitMain = toDetectedWorktree({
|
|
repo,
|
|
settings,
|
|
worktree: makeWorktree({
|
|
path: '/repos/app-main',
|
|
isMainWorktree: true
|
|
}),
|
|
knownOrcaLayouts: buildKnownOrcaWorkspaceLayouts(settings, repo)
|
|
})
|
|
|
|
expect(selected.visible).toBe(true)
|
|
expect(gitMain.visible).toBe(false)
|
|
expect(gitMain.ownership).toBe('external')
|
|
})
|
|
})
|
|
|
|
describe('external worktree visibility policy', () => {
|
|
it('defaults undefined visibility to hide for new repos and show for legacy repos', () => {
|
|
expect(effectiveExternalWorktreeVisibility(makeRepo(), false)).toBe('hide')
|
|
expect(effectiveExternalWorktreeVisibility(makeRepo(), true)).toBe('show')
|
|
})
|
|
|
|
it('treats persisted repos without explicit visibility as legacy for upgrade safety', () => {
|
|
expect(isLegacyRepoForExternalWorktreeVisibility(makeRepo())).toBe(true)
|
|
})
|
|
|
|
it('computes legacy status from rollout timing, not from the stored visibility value', () => {
|
|
expect(
|
|
isLegacyRepoForExternalWorktreeVisibility(
|
|
makeRepo({
|
|
addedAt: EXTERNAL_WORKTREE_VISIBILITY_ROLLOUT_AT - 1,
|
|
externalWorktreeVisibility: 'hide'
|
|
})
|
|
)
|
|
).toBe(true)
|
|
})
|
|
|
|
it('honors an explicit legacy marker after visibility changes', () => {
|
|
expect(
|
|
isLegacyRepoForExternalWorktreeVisibility(
|
|
makeRepo({
|
|
externalWorktreeVisibility: 'hide',
|
|
externalWorktreeVisibilityLegacy: true
|
|
})
|
|
)
|
|
).toBe(true)
|
|
expect(
|
|
isLegacyRepoForExternalWorktreeVisibility(
|
|
makeRepo({
|
|
externalWorktreeVisibility: 'hide',
|
|
externalWorktreeVisibilityLegacy: false
|
|
})
|
|
)
|
|
).toBe(false)
|
|
})
|
|
|
|
it('treats repos without a valid addedAt as legacy for upgrade safety', () => {
|
|
expect(
|
|
isLegacyRepoForExternalWorktreeVisibility(makeRepo({ addedAt: undefined as never }))
|
|
).toBe(true)
|
|
expect(isLegacyRepoForExternalWorktreeVisibility(makeRepo({ addedAt: Number.NaN }))).toBe(true)
|
|
})
|
|
|
|
it('shows explicitly imported external worktrees while repo visibility stays hide', () => {
|
|
const repo = makeRepo({
|
|
externalWorktreeVisibility: 'hide',
|
|
importedExternalWorktreePaths: ['/scratch/imported']
|
|
})
|
|
expect(
|
|
shouldShowWorktree({
|
|
repo,
|
|
worktree: makeWorktree({ path: '/scratch/imported', isMainWorktree: false }),
|
|
ownership: 'external',
|
|
isLegacyRepoForVisibility: false,
|
|
isSelectedCheckout: false,
|
|
importedExternalWorktreePaths: repo.importedExternalWorktreePaths
|
|
})
|
|
).toBe(true)
|
|
expect(
|
|
shouldShowWorktree({
|
|
repo,
|
|
worktree: makeWorktree({ path: '/scratch/other', isMainWorktree: false }),
|
|
ownership: 'external',
|
|
isLegacyRepoForVisibility: false,
|
|
isSelectedCheckout: false,
|
|
importedExternalWorktreePaths: repo.importedExternalWorktreePaths
|
|
})
|
|
).toBe(false)
|
|
})
|
|
|
|
it('keeps unknown legacy rows visible for legacy repos after hiding external rows', () => {
|
|
const repo = makeRepo({
|
|
addedAt: EXTERNAL_WORKTREE_VISIBILITY_ROLLOUT_AT - 1,
|
|
externalWorktreeVisibility: 'hide'
|
|
})
|
|
expect(
|
|
shouldShowWorktree({
|
|
repo,
|
|
worktree: makeWorktree({ path: '/orca/workspaces/feature' }),
|
|
ownership: 'unknown-legacy',
|
|
isLegacyRepoForVisibility: true,
|
|
isSelectedCheckout: false
|
|
})
|
|
).toBe(true)
|
|
})
|
|
})
|