Files
orca/mobile/src/session/use-missing-worktree-bounce.test.ts
T

79 lines
2.6 KiB
TypeScript

import { createElement } from 'react'
import { act, create, type ReactTestRenderer } from 'react-test-renderer'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import type { WorktreeShowResolution } from '../worktree/worktree-show-resolution'
import { isSyntheticWorkspaceRoute } from './synthetic-workspace-route'
import {
shouldBounceMissingWorktree,
useMissingWorktreeBounce
} from './use-missing-worktree-bounce'
describe('shouldBounceMissingWorktree', () => {
it('bounces only a host-proven missing worktree', () => {
expect(shouldBounceMissingWorktree('repo::wt', 'missing')).toBe(true)
expect(shouldBounceMissingWorktree('repo::wt', 'unknown')).toBe(false)
expect(shouldBounceMissingWorktree('repo::wt', 'present')).toBe(false)
})
it('never bounces synthetic routes the host cannot resolve', () => {
expect(isSyntheticWorkspaceRoute('folder:/Users/x/dir')).toBe(true)
expect(shouldBounceMissingWorktree('folder:/Users/x/dir', 'missing')).toBe(false)
expect(shouldBounceMissingWorktree('global-floating-terminal', 'missing')).toBe(false)
})
})
describe('useMissingWorktreeBounce', () => {
let renderer: ReactTestRenderer | null = null
const bounce = vi.fn()
beforeEach(() => {
bounce.mockReset()
renderer = null
})
function Harness(props: { worktreeId: string; resolution: WorktreeShowResolution }): null {
useMissingWorktreeBounce({
hostId: 'host-1',
worktreeId: props.worktreeId,
resolution: props.resolution,
bounce
})
return null
}
function render(worktreeId: string, resolution: WorktreeShowResolution): void {
act(() => {
const element = createElement(Harness, { worktreeId, resolution })
if (renderer) {
renderer.update(element)
} else {
renderer = create(element)
}
})
}
it('bounces exactly once per worktree even across re-renders', () => {
render('repo::wt', 'unknown')
expect(bounce).not.toHaveBeenCalled()
render('repo::wt', 'missing')
expect(bounce).toHaveBeenCalledExactlyOnceWith('host-1')
// Why: navigation lands after the render, so the pre-unmount renders must not re-fire.
render('repo::wt', 'missing')
expect(bounce).toHaveBeenCalledTimes(1)
act(() => renderer?.unmount())
})
it('re-arms for a different worktree on the reused screen', () => {
render('repo::wt-1', 'missing')
expect(bounce).toHaveBeenCalledTimes(1)
render('repo::wt-2', 'unknown')
expect(bounce).toHaveBeenCalledTimes(1)
render('repo::wt-2', 'missing')
expect(bounce).toHaveBeenCalledTimes(2)
act(() => renderer?.unmount())
})
})