Files
orca/mobile/src/worktree/worktree-list-completeness.test.ts
T
JinjingandOrca 430d4b9482 Show all worktrees across all hosts on mobile (#7500)
* Show all worktrees across all hosts on mobile

Avoid honoring desktop's host-filtering settings since mobile lacks the
UI to manage or unhide them. This prevents worktrees from being silently
hidden under certain host scopes.

Additionally, this removes worktree filtering based on repo metadata, which
previously caused worktrees to vanish when same-named repos on different
hosts collapsed to a single ID.

* fix(daemon): preserve promisify.custom type through wrapChildProcessApi

The windows-hidden-console-children test (from #7499, admin-merged with a
failing verify) failed tsgo: promisify(wrapped) resolved to its zero-arg
overload because the wrapper erased its argument to a bare variadic function
and the fake never statically carried promisify.custom. Preserve the wrapped
type via a generic overload (accurate: the wrapper copies the call signature
and symbols verbatim) and build the fake as a real CustomPromisify, so
promisify routes through the custom overload as it does in production.

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-05 23:10:48 -07:00

123 lines
4.2 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { buildSections, type Worktree } from './workspace-list-sections'
import {
applyDesktopViewSettings,
type MobileViewState,
type WorkspaceViewSettings
} from './workspace-view-settings'
import { DEFAULT_MOBILE_WORKSPACE_STATUSES } from './mobile-workspace-statuses'
// Regression guard for "host page shows lots of worktrees, repo shows only a
// few". The removed getHostScopedWorktrees filtered the list to worktrees whose
// repoId appeared in the repo.list result — a map keyed by repo DISPLAY NAME.
// Same-named repos on different hosts (a local "orca" and a runtime "orca")
// collapsed to one id, so every worktree under the other id vanished. These
// tests assert the user-visible outcome — every worktree from worktree.ps stays
// in the list — regardless of repo.list contents or desktop host scope, so they
// hold even if the plumbing is refactored, as long as workspaces stop vanishing.
function worktree(repoId: string, id: string, repo = repoId): Worktree {
return {
workspaceKind: 'git',
worktreeId: id,
repoId,
repo,
branch: `feature/${id}`,
displayName: id,
path: `/tmp/orca/${repoId}/${id}`,
liveTerminalCount: 0,
hasAttachedPty: false,
preview: '',
unread: false,
isPinned: false,
linkedPR: null,
status: 'inactive',
agents: []
}
}
const base: MobileViewState = {
groupMode: 'repo',
sortMode: 'recent',
hideSleeping: false,
hideDefaultBranch: false,
filterRepoIds: [],
collapsedGroups: [],
workspaceStatuses: DEFAULT_MOBILE_WORKSPACE_STATUSES
}
// Reconstruct the list the host screen renders: apply the synced desktop
// settings, then build sections exactly as the screen does. `repoIdsByName` is
// the display-name-keyed map the screen builds from repo.list.
function visibleWorktreeIds(
worktrees: Worktree[],
repoIdsByName: Map<string, string>,
desktop: WorkspaceViewSettings = {}
): string[] {
const state = applyDesktopViewSettings(base, desktop)
const sections = buildSections(
worktrees,
state.sortMode,
{
filterRepoIds: new Set(state.filterRepoIds),
hideSleeping: state.hideSleeping,
hideDefaultBranch: state.hideDefaultBranch
},
'',
state.groupMode,
new Set(),
repoIdsByName,
state.workspaceStatuses,
new Set(state.collapsedGroups)
)
return sections.flatMap((section) => section.data.map((w) => w.worktreeId)).sort()
}
describe('every worktree stays visible regardless of repo.list contents', () => {
it('shows worktrees whose repoId is missing from repo.list', () => {
// repo.list only echoes one of the repos the worktrees belong to.
const worktrees = [
worktree('orca-local', 'a'),
worktree('orca-local', 'b'),
worktree('orca-runtime', 'c')
]
const repoIdsByName = new Map([['orca-runtime', 'orca-runtime']])
expect(visibleWorktreeIds(worktrees, repoIdsByName)).toEqual(['a', 'b', 'c'])
})
it('shows every worktree when the same repo name maps to two host-specific ids', () => {
// The exact trigger: a local "orca" and a runtime "orca". repo.list returns
// both under the same displayName; a name-keyed map keeps only the last id.
const worktrees = [
worktree('orca-local', 'local-1', 'orca'),
worktree('orca-local', 'local-2', 'orca'),
worktree('orca-runtime', 'runtime-1', 'orca')
]
// Name-keyed map collapses "orca" to a single id, as the host screen builds it.
const repoIdsByName = new Map([['orca', 'orca-runtime']])
expect(visibleWorktreeIds(worktrees, repoIdsByName)).toEqual([
'local-1',
'local-2',
'runtime-1'
])
})
it('shows every worktree even when the desktop carries a host scope', () => {
// Host scope must never reach the mobile list either (it has no mobile UI).
const worktrees = [worktree('local-repo', 'x'), worktree('runtime-repo', 'y')]
const repoIdsByName = new Map([
['local-repo', 'local-repo'],
['runtime-repo', 'runtime-repo']
])
expect(
visibleWorktreeIds(worktrees, repoIdsByName, {
workspaceHostScope: 'runtime:devbox',
visibleWorkspaceHostIds: ['runtime:devbox']
} as unknown as WorkspaceViewSettings)
).toEqual(['x', 'y'])
})
})