Files
orca/src/relay/git-handler-branch-compare.test.ts
T
Jinjing 933345d347 Clarify upstream divergence stats for rebased branches (#16358)
* Clarify upstream divergence stats for rebased branches

When a branch is rebased, it still tracks the pre-rebase upstream
while comparing against the new base. Move upstream arrows to the
head line to prevent them being confused with compare-base counts.

* Show upstream divergence stats independent of compare base

Measure HEAD against upstream regardless of compare-base state,
so divergence indicators stay visible even when comparison is
missing, loading, or failed. Also use cross-platform temp paths
in tests.

* Show commit counts against compare base, not upstream

Upstream divergence (↑/↓ against tracking branch) was confusing for
rebased branches — the counts appeared beside the base ref but measured
against the upstream branch. Show only the compare base count instead,
on the line that names it.

* Report branch divergence in both directions

Rebased branches are typically ahead AND behind their base; a single count
hides this case. Use symmetric range with --left-right --count to capture
both directions efficiently, then expose commitsBehind in the UI alongside
commitsAhead.

* Use semantic names for i18n keys and template variables

Rename hash-based translation keys to descriptive identifiers and replace generic value0/value1 placeholders with semantic variable names like `count` and `ref`. Improves code maintainability and makes translation strings self-documenting.
2026-08-25 22:19:04 -07:00

65 lines
2.2 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest'
import { branchCompare, type GitExec } from './git-handler-ops'
function deferred<T>(): { promise: Promise<T>; resolve: (value: T) => void } {
let resolve!: (value: T) => void
const promise = new Promise<T>((innerResolve) => {
resolve = innerResolve
})
return { promise, resolve }
}
describe('relay branchCompare', () => {
it('launches independent Git reads before waiting for any result', async () => {
const branch = deferred<{ stdout: string; stderr: string }>()
const head = deferred<{ stdout: string; stderr: string }>()
const base = deferred<{ stdout: string; stderr: string }>()
const changes = deferred<Record<string, unknown>[]>()
const git = vi.fn<GitExec>((args) => {
if (args[0] === 'branch') {
return branch.promise
}
if (args[0] === 'rev-parse' && args.includes('HEAD')) {
return head.promise
}
if (args[0] === 'rev-parse') {
return base.promise
}
if (args[0] === 'merge-base') {
return Promise.resolve({ stdout: 'merge-base\n', stderr: '' })
}
if (args[0] === 'rev-list') {
return Promise.resolve({ stdout: '2\t1\n', stderr: '' })
}
throw new Error(`Unexpected git command: ${args.join(' ')}`)
})
const loadBranchChanges = vi.fn(() => changes.promise)
const pending = branchCompare(git, '/repo', 'origin/main', loadBranchChanges)
await Promise.resolve()
expect(git.mock.calls.map(([args]) => args.join(' '))).toEqual([
'branch --show-current',
'rev-parse --verify HEAD',
'rev-parse --verify origin/main'
])
branch.resolve({ stdout: 'feature\n', stderr: '' })
head.resolve({ stdout: 'head\n', stderr: '' })
base.resolve({ stdout: 'base\n', stderr: '' })
await vi.waitFor(() => expect(loadBranchChanges).toHaveBeenCalledOnce())
expect(git.mock.calls.some(([args]) => args[0] === 'rev-list')).toBe(true)
changes.resolve([{ path: 'file.ts' }])
await expect(pending).resolves.toMatchObject({
summary: {
compareRef: 'feature',
changedFiles: 1,
commitsAhead: 1,
commitsBehind: 2,
status: 'ready'
}
})
})
})