From d1bbb8e57e34bbd378a883a49ab3c6e4fb192dfb Mon Sep 17 00:00:00 2001 From: OrcaWin Date: Sun, 25 Oct 2026 13:52:59 -0700 Subject: [PATCH] test: remove redundant renderer and shared checks and strengthen assertions (#33625) Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> --- ...on-run-history-keyboard-navigation.test.ts | 2 +- .../automation-run-output-snapshot.test.ts | 2 +- .../automation-run-view-state.test.ts | 2 +- .../automation-scoped-list-client.test.ts | 47 +++++++--------- .../automation-usage-model.test.ts | 37 ++++++++++--- .../external-automation-scope-gating.test.ts | 8 ++- .../external-automation-scope-keys.test.ts | 4 ++ ...phemeral-vm-runtime-store-rollback.test.ts | 8 --- .../folder-workspace-execution-host.test.ts | 2 +- src/shared/foreground-wrapper-agent.test.ts | 2 +- src/shared/freebuff-launch.spec.ts | 2 +- src/shared/git-branch-line-total.test.ts | 12 ---- src/shared/git-check-ignore-stdio.test.ts | 10 +--- src/shared/git-config-snapshot-runner.test.ts | 55 ++++++++++--------- 14 files changed, 98 insertions(+), 95 deletions(-) diff --git a/src/renderer/src/components/automations/automation-run-history-keyboard-navigation.test.ts b/src/renderer/src/components/automations/automation-run-history-keyboard-navigation.test.ts index 6adc189f8c1..11d03883997 100644 --- a/src/renderer/src/components/automations/automation-run-history-keyboard-navigation.test.ts +++ b/src/renderer/src/components/automations/automation-run-history-keyboard-navigation.test.ts @@ -166,7 +166,7 @@ describe('getAutomationRunHistoryArrowTarget', () => { ).toBe(run1) }) - it('defaults to index 0 on ArrowDown when nothing was selected', () => { + it('moves down from the first run when nothing was selected', () => { expect( getAutomationRunHistoryArrowTarget({ runs, diff --git a/src/renderer/src/components/automations/automation-run-output-snapshot.test.ts b/src/renderer/src/components/automations/automation-run-output-snapshot.test.ts index 4bf868bf94e..96281625b50 100644 --- a/src/renderer/src/components/automations/automation-run-output-snapshot.test.ts +++ b/src/renderer/src/components/automations/automation-run-output-snapshot.test.ts @@ -132,7 +132,7 @@ describe('automation run output snapshot buffer', () => { }) }) - it('owns the exact UTF-16 tail of one oversized chunk', () => { + it('retains the exact UTF-16 tail of one oversized chunk', () => { const buffer = createAutomationRunOutputSnapshotBuffer() const retained = `\ude00${'A'.repeat(256 * 1024 - 2)}\ud83d` diff --git a/src/renderer/src/components/automations/automation-run-view-state.test.ts b/src/renderer/src/components/automations/automation-run-view-state.test.ts index a211c4d390f..294239d0bd1 100644 --- a/src/renderer/src/components/automations/automation-run-view-state.test.ts +++ b/src/renderer/src/components/automations/automation-run-view-state.test.ts @@ -143,7 +143,7 @@ describe('automation run view state', () => { ).toMatchObject({ availability: 'metadata', actionLabel: 'View run', canOpen: false }) }) - it('keeps skipped or missing-workspace runs as metadata-only history', () => { + it('keeps runs without a workspace as metadata-only history', () => { expect( getAutomationRunViewState({ run: makeRun({ workspaceId: null, terminalSessionId: null }), diff --git a/src/renderer/src/components/automations/automation-scoped-list-client.test.ts b/src/renderer/src/components/automations/automation-scoped-list-client.test.ts index a241936c780..c33d0dba1ed 100644 --- a/src/renderer/src/components/automations/automation-scoped-list-client.test.ts +++ b/src/renderer/src/components/automations/automation-scoped-list-client.test.ts @@ -112,6 +112,7 @@ describe('listScopedAutomations', () => { await expect(listScopedAutomations(RUNTIME, { kind: 'self' })).rejects.toThrow( 'runtime_environment_revision_changed' ) + expect(callRuntimeRpc).toHaveBeenCalledTimes(1) }) it('does not query a host that never advertised host scope', async () => { @@ -125,10 +126,10 @@ describe('listScopedAutomations', () => { // An unreachable host proves nothing about its version, so it must not be reported as too old. it('propagates an unreachable authority instead of calling it incompatible', async () => { - const { listScopedAutomations, AutomationHostScopeUnsupportedError } = await client() + const { listScopedAutomations } = await client() getRuntimeEnvironmentStatus.mockRejectedValue(new Error('runtime_unavailable')) - await expect(listScopedAutomations(RUNTIME, { kind: 'self' })).rejects.not.toBeInstanceOf( - AutomationHostScopeUnsupportedError + await expect(listScopedAutomations(RUNTIME, { kind: 'self' })).rejects.toThrow( + 'runtime_unavailable' ) }) }) @@ -136,19 +137,24 @@ describe('listScopedAutomations', () => { describe('capability probe dedupe', () => { it('shares one in-flight probe across concurrent calls to the same incarnation', async () => { const { listScopedAutomations } = await client() - getRuntimeEnvironmentStatus.mockImplementation(async () => { - await new Promise((resolve) => setTimeout(resolve, 0)) - return ALL_CAPABILITIES + let completeProbe = (_status: typeof ALL_CAPABILITIES): void => {} + const probe = new Promise((resolve) => { + completeProbe = resolve }) + getRuntimeEnvironmentStatus.mockReturnValue(probe) callRuntimeRpc.mockResolvedValue({ automations: [], items: [], orphanCount: 0 }) - await Promise.all([ + const requests = [ listScopedAutomations(RUNTIME, { kind: 'self' }), listScopedAutomations(RUNTIME, { kind: 'orphan' }) - ]) + ] + expect(getRuntimeEnvironmentStatus).toHaveBeenCalledTimes(1) + expect(callRuntimeRpc).not.toHaveBeenCalled() + completeProbe(ALL_CAPABILITIES) + await Promise.all(requests) expect(getRuntimeEnvironmentStatus).toHaveBeenCalledTimes(1) }) - it('never re-asks about a capability the incarnation already confirmed', async () => { + it('caches confirmed list capabilities and re-probes mutations', async () => { const { listScopedAutomations, updateAutomationForOwner } = await client() getRuntimeEnvironmentStatus.mockResolvedValue(ALL_CAPABILITIES) callRuntimeRpc.mockResolvedValue({ @@ -159,7 +165,7 @@ describe('capability probe dedupe', () => { }) await listScopedAutomations(RUNTIME, { kind: 'self' }) await listScopedAutomations(RUNTIME, { kind: 'orphan' }) - // A different capability confirmed by the same status answer is also cached. + expect(getRuntimeEnvironmentStatus).toHaveBeenCalledTimes(1) await updateAutomationForOwner(SSH_OWNER, 'a1', { enabled: false }) // Mutations re-probe because in-place runtime replacement can invalidate capabilities under the same pairing. expect(getRuntimeEnvironmentStatus).toHaveBeenCalledTimes(2) @@ -325,11 +331,9 @@ describe('orphan-fenced mutations', () => { // An unreachable host is a retry, not an upgrade prompt — the orphan arm inherits this. it('propagates an unreachable authority instead of calling it incompatible', async () => { - const { deleteOrphanAutomation, AutomationHostScopeUnsupportedError } = await client() + const { deleteOrphanAutomation } = await client() getRuntimeEnvironmentStatus.mockRejectedValue(new Error('runtime_unavailable')) - await expect(deleteOrphanAutomation(RUNTIME, 'a1')).rejects.not.toBeInstanceOf( - AutomationHostScopeUnsupportedError - ) + await expect(deleteOrphanAutomation(RUNTIME, 'a1')).rejects.toThrow('runtime_unavailable') }) it('routes a desktop orphan over the local runtime target, unprobed', async () => { @@ -385,22 +389,13 @@ describe('orphan-fenced mutations', () => { }) // Keep orphan and owned read-only history arms equally unprobed. - it('probes on the orphan history read exactly as often as the owned read does', async () => { + it('does not probe either owned or orphan history reads', async () => { const { listAutomationRunsForOwner, listOrphanAutomationRuns } = await client() callRuntimeRpc.mockResolvedValue({ runs: [] }) await listAutomationRunsForOwner(SSH_OWNER, 'a1') - const ownedProbes = getRuntimeEnvironmentStatus.mock.calls.length - getRuntimeEnvironmentStatus.mockClear() + expect(getRuntimeEnvironmentStatus).not.toHaveBeenCalled() await listOrphanAutomationRuns(RUNTIME, 'a1') - expect(getRuntimeEnvironmentStatus.mock.calls.length).toBe(ownedProbes) - }) - - it('cannot be handed an owner precondition — the fence is not a parameter', async () => { - const { updateOrphanAutomation, ORPHAN_OWNER_PRECONDITION } = await client() - callRuntimeRpc.mockResolvedValue({ automation: { id: 'a1' } }) - await updateOrphanAutomation(DESKTOP, 'a1', { enabled: false }) - expect(callRuntimeRpc.mock.calls[0]?.[2]?.expectedOwner).toEqual(ORPHAN_OWNER_PRECONDITION) - expect(updateOrphanAutomation.length).toBe(3) + expect(getRuntimeEnvironmentStatus).not.toHaveBeenCalled() }) }) diff --git a/src/renderer/src/components/automations/automation-usage-model.test.ts b/src/renderer/src/components/automations/automation-usage-model.test.ts index 09c063e1360..1e1fe8f9305 100644 --- a/src/renderer/src/components/automations/automation-usage-model.test.ts +++ b/src/renderer/src/components/automations/automation-usage-model.test.ts @@ -54,6 +54,29 @@ describe('automation usage model', () => { unavailableMessage: null } }), + makeRun({ + id: 'run-3', + createdAt: 3, + dispatchedAt: 3, + usage: { + status: 'known', + provider: 'claude', + model: 'sonnet', + inputTokens: 200, + outputTokens: 700, + cacheReadTokens: null, + cacheWriteTokens: 50, + reasoningOutputTokens: null, + totalTokens: 900, + estimatedCostUsd: 0.0042, + estimatedCostSource: 'api_equivalent', + providerSessionId: 'session-3', + attribution: 'provider_session_time_window', + collectedAt: 3, + unavailableReason: null, + unavailableMessage: null + } + }), makeRun({ id: 'run-2', usage: { @@ -78,16 +101,16 @@ describe('automation usage model', () => { ]) expect(summary).toEqual({ - knownRuns: 1, + knownRuns: 2, unavailableRuns: 1, - inputTokens: 1000, - outputTokens: 300, - cacheTokens: 400, + inputTokens: 1200, + outputTokens: 1000, + cacheTokens: 450, reasoningOutputTokens: 50, - totalTokens: 1350, - estimatedCostUsd: 0.0042, + totalTokens: 2250, + estimatedCostUsd: 0.0084, lastRunStatus: 'completed', - lastRunAt: 1 + lastRunAt: 3 }) }) diff --git a/src/renderer/src/components/automations/external-automation-scope-gating.test.ts b/src/renderer/src/components/automations/external-automation-scope-gating.test.ts index c147895b47e..0f755933487 100644 --- a/src/renderer/src/components/automations/external-automation-scope-gating.test.ts +++ b/src/renderer/src/components/automations/external-automation-scope-gating.test.ts @@ -99,11 +99,15 @@ describe('engine scope errors', () => { ).toBe(EXTERNAL_AUTOMATION_SCOPE_CODES.targetHidden) }) - it('turns a hidden-target rejection into its own copy, not the generic note', () => { + it('preserves the hidden-target scope code', () => { const gate = externalAutomationScopeGateFromError( new ExternalAutomationScopeError(EXTERNAL_AUTOMATION_SCOPE_CODES.targetHidden) ) - expect(gate?.status).toBe('not-listed') + expect(gate).toEqual({ + status: 'not-listed', + probeOwner: null, + code: EXTERNAL_AUTOMATION_SCOPE_CODES.targetHidden + }) }) it('leaves unrelated failures alone so they are not relabelled as scope limits', () => { diff --git a/src/renderer/src/components/automations/external-automation-scope-keys.test.ts b/src/renderer/src/components/automations/external-automation-scope-keys.test.ts index 5c18efd6285..f34f9198aaf 100644 --- a/src/renderer/src/components/automations/external-automation-scope-keys.test.ts +++ b/src/renderer/src/components/automations/external-automation-scope-keys.test.ts @@ -49,6 +49,10 @@ describe('external automation scope keys', () => { it('escapes components so a hostile ID cannot forge another key', () => { const forged = externalAutomationJobKey(local, 'job|extra') expect(forged).not.toBe(externalAutomationActionKey(local, 'job', 'run')) + expect(forged).not.toBe(externalAutomationJobKey(local, 'job%7Cextra')) + expect(externalAutomationActionKey(local, 'job|extra', 'run')).not.toBe( + externalAutomationActionKey(local, 'job%7Cextra', 'run') + ) expect(forged.split('|')).toHaveLength(4) }) diff --git a/src/shared/ephemeral-vm-runtime-store-rollback.test.ts b/src/shared/ephemeral-vm-runtime-store-rollback.test.ts index 56099cab730..ce36709999e 100644 --- a/src/shared/ephemeral-vm-runtime-store-rollback.test.ts +++ b/src/shared/ephemeral-vm-runtime-store-rollback.test.ts @@ -13,7 +13,6 @@ import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' import { getEphemeralVmRuntimeFeatureStorePath, - featureIdentity, restoreRuntimeFeatureList, MAX_EPHEMERAL_VM_RUNTIME_FEATURE_STORE_FILE_BYTES } from './ephemeral-vm-runtime-feature-store' @@ -302,13 +301,6 @@ describe('runtime feature restoration scaling', () => { createdAt: runtime.createdAt, recipeCheckoutMode: 'provisioned-root' as const })) - for (const runtime of runtimes) { - expect( - features.find((entry) => featureIdentity(entry) === featureIdentity(runtime)) - ).toBeDefined() - } - expect(reads).toBe(500_500) - reads = 0 const restored = restoreRuntimeFeatureList(runtimes, features) expect(reads).toBe(1000) expect(restored.map((runtime) => runtime.id)).toEqual(runtimes.map((runtime) => runtime.id)) diff --git a/src/shared/folder-workspace-execution-host.test.ts b/src/shared/folder-workspace-execution-host.test.ts index 8fc36c603f4..2f203d9b1a1 100644 --- a/src/shared/folder-workspace-execution-host.test.ts +++ b/src/shared/folder-workspace-execution-host.test.ts @@ -35,7 +35,7 @@ function repo(overrides: Partial & Pick): Repo { badgeColor: '#000', addedAt: 0, ...overrides - } as Repo + } } function state(overrides: Partial = {}): FolderWorkspaceHostState { diff --git a/src/shared/foreground-wrapper-agent.test.ts b/src/shared/foreground-wrapper-agent.test.ts index 52a43c652e9..3d63958c2f4 100644 --- a/src/shared/foreground-wrapper-agent.test.ts +++ b/src/shared/foreground-wrapper-agent.test.ts @@ -22,7 +22,7 @@ describe('resolveOuterWrapperForegroundProcess', () => { expect(resolveOuterWrapperForegroundProcess(pi, barePi, [barePi])).toBe('pi') }) - it('leaves a cross-group agent (codex) untouched even under a deeper same-name child', () => { + it('keeps Codex identity beneath a shell parent', () => { const codex = { agent: 'codex' as const, processName: 'codex' } expect( resolveOuterWrapperForegroundProcess( diff --git a/src/shared/freebuff-launch.spec.ts b/src/shared/freebuff-launch.spec.ts index b58dc4bd091..a9c7163d089 100644 --- a/src/shared/freebuff-launch.spec.ts +++ b/src/shared/freebuff-launch.spec.ts @@ -5,7 +5,7 @@ import { pickTuiAgent } from './tui-agent-selection' describe('Freebuff terminal launches', () => { it.each(['darwin', 'linux', 'win32'] as const)( - 'delivers task text through the interactive terminal on %s', + 'plans task text as a follow-up to the interactive launch on %s', (platform) => { const prompt = '--help\nFix "quoted" paths and $HOME handling' const plan = buildAgentStartupPlan({ diff --git a/src/shared/git-branch-line-total.test.ts b/src/shared/git-branch-line-total.test.ts index ddb776b79e9..c3a5a69a750 100644 --- a/src/shared/git-branch-line-total.test.ts +++ b/src/shared/git-branch-line-total.test.ts @@ -203,18 +203,6 @@ describe('buildGitBranchLineTotalDiffArgs', () => { '--' ]) }) - - it('never asks for --cached or -C, which would change the measured range', () => { - const args = buildGitBranchLineTotalDiffArgs(MERGE_BASE) - expect(args).not.toContain('--cached') - expect(args).not.toContain('-C') - expect(args.at(-1)).toBe('--') - }) - - it('exposes a finite timeout budget so a huge branch cannot block the status response', () => { - expect(GIT_BRANCH_LINE_TOTAL_TIMEOUT_MS).toBeGreaterThan(0) - expect(Number.isFinite(GIT_BRANCH_LINE_TOTAL_TIMEOUT_MS)).toBe(true) - }) }) describe('computeGitBranchLineTotal', () => { diff --git a/src/shared/git-check-ignore-stdio.test.ts b/src/shared/git-check-ignore-stdio.test.ts index e0b7ed789da..a08e2cd0348 100644 --- a/src/shared/git-check-ignore-stdio.test.ts +++ b/src/shared/git-check-ignore-stdio.test.ts @@ -1,20 +1,12 @@ import { describe, expect, it } from 'vitest' import { encodeGitCheckIgnorePaths, - GIT_CHECK_IGNORE_STDIN_ARGS, parseGitCheckIgnorePaths, splitGitCheckIgnorePathsByStdinBytes } from './git-check-ignore-stdio' describe('git check-ignore stdio', () => { - it('uses the NUL-delimited stdin command shape', () => { - expect(GIT_CHECK_IGNORE_STDIN_ARGS).toEqual([ - '-c', - 'core.quotePath=false', - 'check-ignore', - '-z', - '--stdin' - ]) + it('encodes exact paths as NUL-delimited stdin records', () => { expect(encodeGitCheckIgnorePaths(['dist/bundle.js', 'line\nbreak.txt', '-leading.txt'])).toBe( 'dist/bundle.js\0line\nbreak.txt\0-leading.txt\0' ) diff --git a/src/shared/git-config-snapshot-runner.test.ts b/src/shared/git-config-snapshot-runner.test.ts index 1e231893433..207b42de0d4 100644 --- a/src/shared/git-config-snapshot-runner.test.ts +++ b/src/shared/git-config-snapshot-runner.test.ts @@ -8,13 +8,13 @@ function listSnapshot(records: string[]): string { return `${records.join('\0')}\0` } -function getGitArgs(call: unknown[]): string[] { - return call[0] as string[] -} +type GitCommandRunner = Parameters[0] -function countCalls(runGit: ReturnType, expectedArgs: string[]): number { - return runGit.mock.calls.filter((call) => { - const args = getGitArgs(call) +function countCalls( + runGit: ReturnType>, + expectedArgs: string[] +): number { + return runGit.mock.calls.filter(([args]) => { return ( args.length === expectedArgs.length && args.every((arg, index) => arg === expectedArgs[index]) ) @@ -31,7 +31,7 @@ function createDeferred(): { promise: Promise; resolve: (value: T) => void describe('createGitConfigSnapshotRunner', () => { it('serves many config --get lookups from one config --list -z call', async () => { - const runGit = vi.fn(async () => ({ + const runGit = vi.fn(async () => ({ stdout: listSnapshot([ 'branch.main.remote\norigin', 'branch.main.merge\nrefs/heads/main', @@ -40,16 +40,22 @@ describe('createGitConfigSnapshotRunner', () => { })) const runner = createGitConfigSnapshotRunner(runGit) - await runner(['config', '--get', 'branch.main.remote']) - await runner(['config', '--get', 'branch.main.merge']) - await runner(['config', '--get', 'remote.pushDefault']) + await expect(runner(['config', '--get', 'branch.main.remote'])).resolves.toEqual({ + stdout: 'origin' + }) + await expect(runner(['config', '--get', 'branch.main.merge'])).resolves.toEqual({ + stdout: 'refs/heads/main' + }) + await expect(runner(['config', '--get', 'remote.pushDefault'])).resolves.toEqual({ + stdout: 'fork' + }) expect(countCalls(runGit, ['config', '--list', '-z'])).toBe(1) - expect(runGit.mock.calls.filter((call) => getGitArgs(call)[1] === '--get')).toHaveLength(0) + expect(runGit.mock.calls.filter(([args]) => args[1] === '--get')).toHaveLength(0) }) it('returns branch and remote values from a representative snapshot', async () => { - const runGit = vi.fn(async () => ({ + const runGit = vi.fn(async () => ({ stdout: listSnapshot([ 'branch.feature.remote\norigin', 'branch.feature.merge\nrefs/heads/feature', @@ -70,7 +76,7 @@ describe('createGitConfigSnapshotRunner', () => { }) it('passes remote commands through unchanged', async () => { - const runGit = vi.fn(async (args: string[]) => ({ stdout: args.join(' ') })) + const runGit = vi.fn(async (args: string[]) => ({ stdout: args.join(' ') })) const runner = createGitConfigSnapshotRunner(runGit) await expect(runner(['remote'])).resolves.toEqual({ stdout: 'remote' }) @@ -83,18 +89,18 @@ describe('createGitConfigSnapshotRunner', () => { }) it('case-folds the requested section and key', async () => { - const runGit = vi.fn(async () => ({ + const runGit = vi.fn(async () => ({ stdout: listSnapshot(['remote.pushdefault\nfork']) })) const runner = createGitConfigSnapshotRunner(runGit) - await expect(runner(['config', '--get', 'remote.pushDefault'])).resolves.toEqual({ + await expect(runner(['config', '--get', 'REMOTE.pushDefault'])).resolves.toEqual({ stdout: 'fork' }) }) it('preserves subsections with dots in lookup keys', async () => { - const runGit = vi.fn(async () => ({ + const runGit = vi.fn(async () => ({ stdout: listSnapshot(['branch.feature.x.merge\nrefs/heads/feature.x']) })) const runner = createGitConfigSnapshotRunner(runGit) @@ -105,7 +111,7 @@ describe('createGitConfigSnapshotRunner', () => { }) it('returns the last multivar value for config --get', async () => { - const runGit = vi.fn(async () => ({ + const runGit = vi.fn(async () => ({ stdout: listSnapshot([ 'branch.main.merge\nrefs/heads/old', 'branch.main.merge\nrefs/heads/new' @@ -119,7 +125,7 @@ describe('createGitConfigSnapshotRunner', () => { }) it('parses valueless boolean keys without corrupting adjacent records', async () => { - const runGit = vi.fn(async () => ({ + const runGit = vi.fn(async () => ({ stdout: listSnapshot([ 'remote.origin.mirror', 'remote.origin.url\ngit@example.com:org/repo.git' @@ -137,7 +143,7 @@ describe('createGitConfigSnapshotRunner', () => { it('rejects an absent key from a loaded snapshot instead of returning empty success', async () => { // Missing keys must reject like config --get, without respawning the command this snapshot coalesces. - const runGit = vi.fn(async () => ({ + const runGit = vi.fn(async () => ({ stdout: listSnapshot(['branch.main.remote\norigin']) })) const runner = createGitConfigSnapshotRunner(runGit) @@ -147,8 +153,7 @@ describe('createGitConfigSnapshotRunner', () => { ) expect(countCalls(runGit, ['config', '--list', '-z'])).toBe(1) expect( - runGit.mock.calls.filter((call) => { - const args = getGitArgs(call) + runGit.mock.calls.filter(([args]) => { return args[0] === 'config' && args[1] === '--get' }) ).toHaveLength(0) @@ -156,7 +161,7 @@ describe('createGitConfigSnapshotRunner', () => { it('single-flights concurrent first config --get lookups', async () => { const snapshot = createDeferred<{ stdout: string }>() - const runGit = vi.fn(async () => await snapshot.promise) + const runGit = vi.fn(async () => await snapshot.promise) const runner = createGitConfigSnapshotRunner(runGit) const lookups = Promise.all([ @@ -184,7 +189,7 @@ describe('createGitConfigSnapshotRunner', () => { }) it('falls back to real config --get after snapshot fetch failure', async () => { - const runGit = vi.fn(async (args: string[]) => { + const runGit = vi.fn(async (args: string[]) => { if (args[0] === 'config' && args[1] === '--list') { throw new Error('snapshot failed') } @@ -203,11 +208,11 @@ describe('createGitConfigSnapshotRunner', () => { }) expect(countCalls(runGit, ['config', '--list', '-z'])).toBe(1) - expect(runGit.mock.calls.filter((call) => getGitArgs(call)[1] === '--get')).toHaveLength(2) + expect(runGit.mock.calls.filter(([args]) => args[1] === '--get')).toHaveLength(2) }) it('passes non-config commands through', async () => { - const runGit = vi.fn(async (args: string[]) => ({ stdout: args.join(' ') })) + const runGit = vi.fn(async (args: string[]) => ({ stdout: args.join(' ') })) const runner = createGitConfigSnapshotRunner(runGit) await expect(runner(['rev-parse', '--abbrev-ref', 'HEAD@{u}'])).resolves.toEqual({