Files
orca/src/main/ipc/worktrees-test-module-mocks.ts
T
Neil d7767fb196 perf(worktree): remove redundant creation and terminal startup work (#18793)
* perf(worktree): remove redundant creation and terminal startup work

* test(worktree): cover optimized creation call signatures

Preserve explicit branch adoption, WSL callback routing and sparse cleanup expectations.

* perf: preserve user Git checkout worker settings

* perf(git): skip malformed remote base probes

* perf(cli): avoid loading other agent hooks for Codex preflight

* fix(build): retain Codex preflight entry for packaged CLI

* test(ssh): wait for replacement PTY before lease recovery input

* test(ssh): verify recovered shell execution and lease ownership

* test(electron): reap isolated macOS crash reporters on teardown

* test: allow either observed self-exit snapshot ordering

* test: capture frozen-host input recovery evidence
2026-09-05 15:08:22 -07:00

278 lines
11 KiB
TypeScript

import { type Mock, vi } from 'vitest'
import type { computeWorktreePath } from './worktree-logic'
import type { HandlerMap } from './worktrees-test-ipc-surface'
/** Loose signature: one mock stands in for many unrelated module exports. */
export type ModuleMock = Mock<(...args: unknown[]) => unknown>
/** Mocks tests re-implement with a leading path/name/script argument. */
export type StringArgMock = Mock<(value: string, ...rest: unknown[]) => unknown>
/** Lookups tests re-implement per branch, e.g. conflict kind and PR resolution. */
export type RepoBranchMock = Mock<(repoPath: string, branch: string, ...rest: unknown[]) => unknown>
/** Git invocations tests re-implement by inspecting the argv array. */
export type GitArgvMock = Mock<(args: string[], ...rest: unknown[]) => unknown>
export type ParsedWorktreeRow = {
path: string
branch: string
head: string
isBare: boolean
isMainWorktree: boolean
}
export const ORIGINAL_PLATFORM = process.platform
export function setPlatform(platform: NodeJS.Platform): void {
Object.defineProperty(process, 'platform', {
configurable: true,
value: platform
})
}
export const removeWorktreeLinkedPathsMock: ModuleMock = vi.fn()
export const findExistingWorktreeSymlinkPathsMock: ModuleMock = vi.fn()
export const handleMock: Mock<(channel: string, handler: HandlerMap[string]) => void> = vi.fn()
export const removeHandlerMock: ModuleMock = vi.fn()
export const listWorktreesMock: StringArgMock = vi.fn()
export const describeCreatedWorktreeMock: ModuleMock = vi.fn()
export const parseWorktreeListMock: Mock<(output: string) => ParsedWorktreeRow[]> = vi.fn(
(output: string) =>
output
.trim()
.split(/\n\s*\n/)
.filter(Boolean)
.map((block, index) => {
const lines = block.split(/\r?\n/)
const path = lines.find((line) => line.startsWith('worktree '))?.slice(9) ?? ''
const branch = lines.find((line) => line.startsWith('branch '))?.slice(7) ?? ''
return { path, branch, head: String(index), isBare: false, isMainWorktree: index === 0 }
})
)
export const assertWorktreeCleanForRemovalMock: ModuleMock = vi.fn()
export const addWorktreeMock: ModuleMock = vi.fn()
export const addSparseWorktreeMock: ModuleMock = vi.fn()
export const removeWorktreeMock: ModuleMock = vi.fn()
export const forceDeleteLocalBranchMock: ModuleMock = vi.fn()
export const resolveLocalGitUsernameMock: ModuleMock = vi.fn()
export const getBaseRefDefaultMock: ModuleMock = vi.fn()
export const resolveDefaultBaseRefWithLocalGitMock: ModuleMock = vi.fn()
export const resolveDefaultBaseRefViaExecMock: ModuleMock = vi.fn()
export const getDefaultRemoteMock: ModuleMock = vi.fn()
export const getBranchConflictKindMock: RepoBranchMock = vi.fn()
export const getPRForBranchMock: RepoBranchMock = vi.fn()
export const getHostedReviewForBranchMock: ModuleMock = vi.fn()
export const getWorkItemMock: ModuleMock = vi.fn()
export const getPullRequestPushTargetMock: ModuleMock = vi.fn()
export const getEffectiveHooksMock: Mock<(repo?: unknown, worktreePath?: string) => unknown> =
vi.fn()
export const createIssueCommandRunnerScriptMock: ModuleMock = vi.fn()
export const createSetupRunnerScriptMock: ModuleMock = vi.fn()
export const getEffectiveHooksFromConfigMock: ModuleMock = vi.fn()
export const getDefaultTabsLaunchMock: ModuleMock = vi.fn()
export const parseOrcaYamlMock: ModuleMock = vi.fn()
export const shouldRunSetupForCreateMock: ModuleMock = vi.fn()
export const buildPosixRunnerScriptMock: StringArgMock = vi.fn()
export const buildWindowsRunnerScriptMock: StringArgMock = vi.fn()
export const getSetupRunnerEnvVarsMock: Mock<
(repo: { path: string }, worktreePath: string) => Record<string, string>
> = vi.fn()
export const resolveSetupRunnerShellMock: ModuleMock = vi.fn()
export const runHookMock: ModuleMock = vi.fn()
export const hasHooksFileMock: ModuleMock = vi.fn()
export const loadHooksMock: ModuleMock = vi.fn()
export const computeWorktreePathMock: Mock<typeof computeWorktreePath> = vi.fn()
export const ensurePathWithinWorkspaceMock: StringArgMock = vi.fn()
export const gitExecFileAsyncMock: GitArgvMock = vi.fn()
export const getSshGitProviderMock: StringArgMock = vi.fn()
export const getSshFilesystemProviderMock: ModuleMock = vi.fn()
export const getActiveMultiplexerMock: ModuleMock = vi.fn()
export const deleteWorktreeHistoryDirMock: ModuleMock = vi.fn()
export const advertisedUrlWatcherForgetWorktreeMock: ModuleMock = vi.fn()
export const pruneCleanupScanSnapshotMock: ModuleMock = vi.fn().mockResolvedValue(undefined)
export const pruneCleanupScanSnapshotsMock: ModuleMock = vi.fn().mockResolvedValue(undefined)
export const pruneSpaceAnalysisSnapshotMock: ModuleMock = vi.fn().mockResolvedValue(undefined)
export const pruneSpaceAnalysisSnapshotsMock: ModuleMock = vi.fn().mockResolvedValue(undefined)
export const recordRemovalSnapshotPruneMock: ModuleMock = vi.fn()
export const killAllProcessesForWorktreeMock: ModuleMock = vi.fn()
export const clearProviderPtyStateMock: ModuleMock = vi.fn()
export const getLocalPtyProviderMock: ModuleMock = vi.fn()
export const getSshPtyProviderMock: ModuleMock = vi.fn()
// Why: vi.mock factories are hoisted per test file, so each file calls these builders instead of
// closing over module-scope bindings.
export const electronModuleMock = () => ({
ipcMain: {
handle: handleMock,
removeHandler: removeHandlerMock
}
})
export const gitWorktreeModuleMock = () => ({
listWorktrees: listWorktreesMock,
listWorktreesStrict: listWorktreesMock,
listWorktreesSharedStrict: listWorktreesMock,
listWorktreesSharedStrictAllowingTrueEmpty: listWorktreesMock,
describeCreatedWorktree: describeCreatedWorktreeMock,
parseWorktreeList: parseWorktreeListMock,
assertWorktreeCleanForRemoval: assertWorktreeCleanForRemovalMock,
addWorktree: addWorktreeMock,
addSparseWorktree: addSparseWorktreeMock,
removeWorktree: removeWorktreeMock,
forceDeleteLocalBranch: forceDeleteLocalBranchMock
})
export const gitRunnerModuleMock = (): {
gitExecFileAsync: GitArgvMock
gitExecFileSync: ModuleMock
} => ({
gitExecFileAsync: gitExecFileAsyncMock,
gitExecFileSync: vi.fn()
})
export const gitRepoModuleMock = () => ({
getBaseRefDefault: getBaseRefDefaultMock,
resolveDefaultBaseRefWithLocalGit: resolveDefaultBaseRefWithLocalGitMock,
resolveDefaultBaseRefViaExec: resolveDefaultBaseRefViaExecMock,
getDefaultRemote: getDefaultRemoteMock,
getBranchConflictKind: async (
repoPath: string,
branch: string,
base?: string,
options?: { wslDistro?: string },
allowLocalBranch?: () => Promise<boolean>
) => {
// These handler tests stub ref presence; policy tests cover the absent-ref fast path.
if (allowLocalBranch && (await allowLocalBranch())) {
return null
}
return getBranchConflictKindMock(repoPath, branch, base, options)
}
})
export const githubClientModuleMock = () => ({
getPRForBranch: getPRForBranchMock,
getWorkItem: getWorkItemMock,
getPullRequestPushTarget: getPullRequestPushTargetMock
})
export const hostedReviewModuleMock = () => ({
getHostedReviewForBranch: getHostedReviewForBranchMock
})
export const sshGitDispatchModuleMock = () => ({
getSshGitProviderGeneration: () => 0,
getSshGitProvider: getSshGitProviderMock,
SSH_GIT_PROVIDER_UNAVAILABLE_MESSAGE:
'Remote connection dropped. Click Reconnect on the SSH target before retrying.',
requireSshGitProvider: (connectionId: string) => {
const provider = getSshGitProviderMock(connectionId)
if (!provider) {
throw new Error(
'Remote connection dropped. Click Reconnect on the SSH target before retrying.'
)
}
return provider
}
})
export const sshFilesystemDispatchModuleMock = () => ({
getSshFilesystemProvider: getSshFilesystemProviderMock
})
export const worktreeSymlinksModuleMock = (): {
createWorktreeCopiedPaths: ModuleMock
createWorktreeLinkedPaths: ModuleMock
findExistingWorktreeSymlinkPaths: ModuleMock
removeWorktreeLinkedPaths: ModuleMock
} => ({
createWorktreeCopiedPaths: vi.fn(),
createWorktreeLinkedPaths: vi.fn(),
findExistingWorktreeSymlinkPaths: findExistingWorktreeSymlinkPathsMock,
removeWorktreeLinkedPaths: removeWorktreeLinkedPathsMock
})
export const sshModuleMock = () => ({
getActiveMultiplexer: getActiveMultiplexerMock
})
// Why a second builder: getActiveMultiplexer moved to ../ssh/ssh-target-registry so the
// runtime could reach it without ipcMain. Production imports it from there now, so a
// vi.mock('./ssh') factory alone is inert.
export const sshTargetRegistryModuleMock = () => ({
getActiveMultiplexer: getActiveMultiplexerMock
})
export const hooksModuleMock = () => ({
getEffectiveHooks: getEffectiveHooksMock,
loadHooks: loadHooksMock,
parseOrcaYaml: parseOrcaYamlMock,
runHook: runHookMock,
hasHooksFile: hasHooksFileMock
})
// Why: the runner-script/hook-config surface moved out of hooks.ts, so each home
// module needs its own mock or the worktree handlers run the real implementations.
export const setupRunnerScriptTextModuleMock = (actual: Record<string, unknown>) => ({
...actual,
buildPosixRunnerScript: buildPosixRunnerScriptMock,
buildWindowsRunnerScript: buildWindowsRunnerScriptMock
})
export const worktreeRunnerScriptModuleMock = (actual: Record<string, unknown>) => ({
...actual,
createIssueCommandRunnerScript: createIssueCommandRunnerScriptMock,
createSetupRunnerScript: createSetupRunnerScriptMock,
resolveSetupRunnerShell: resolveSetupRunnerShellMock
})
export const effectiveHookConfigModuleMock = (actual: Record<string, unknown>) => ({
...actual,
getDefaultTabsLaunch: getDefaultTabsLaunchMock,
getEffectiveHooksFromConfig: getEffectiveHooksFromConfigMock,
shouldRunSetupForCreate: shouldRunSetupForCreateMock
})
export const setupHookEnvVarsModuleMock = (actual: Record<string, unknown>) => ({
...actual,
getSetupRunnerEnvVars: getSetupRunnerEnvVarsMock
})
export const worktreeLogicModuleMock = (actual: Record<string, unknown>) => ({
...actual,
computeWorktreePath: computeWorktreePathMock,
ensurePathWithinWorkspace: ensurePathWithinWorkspaceMock
})
export const terminalHistoryDeletionModuleMock = () => ({
deleteWorktreeHistoryDir: deleteWorktreeHistoryDirMock
})
export const advertisedUrlWatcherModuleMock = () => ({
advertisedUrlWatcher: {
forgetWorktree: advertisedUrlWatcherForgetWorktreeMock
}
})
export const workspaceCleanupScanSnapshotModuleMock = () => ({
pruneWorkspaceCleanupScanSnapshot: pruneCleanupScanSnapshotMock,
pruneWorkspaceCleanupScanSnapshots: pruneCleanupScanSnapshotsMock
})
export const workspaceSpaceAnalysisSnapshotModuleMock = () => ({
pruneWorkspaceSpaceAnalysisSnapshot: pruneSpaceAnalysisSnapshotMock,
pruneWorkspaceSpaceAnalysisSnapshots: pruneSpaceAnalysisSnapshotsMock
})
export const workspaceCleanupRemovalSnapshotPruneModuleMock = () => ({
recordWorkspaceCleanupRemovalSnapshotPrune: recordRemovalSnapshotPruneMock
})
export const worktreeTeardownModuleMock = () => ({
killAllProcessesForWorktree: killAllProcessesForWorktreeMock
})
export const ptyModuleMock = () => ({
clearProviderPtyState: clearProviderPtyStateMock,
getLocalPtyProvider: getLocalPtyProviderMock,
getSshPtyProvider: getSshPtyProviderMock
})