From 1f4c0120aff03e11f7bfee8612aa87c3c01f415b Mon Sep 17 00:00:00 2001 From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Date: Sun, 26 Jul 2026 13:18:21 -0700 Subject: [PATCH] test(codex): cover the pane-account registry's real corrupt-file paths The corrupt-file case deleted the registry instead of corrupting it, so neither the malformed-JSON nor the bad-shape branches of parseRegistry were exercised. Assert each rejected shape and that a record still lands afterwards. --- .../codex/codex-stale-pane-accounts.test.ts | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/main/codex/codex-stale-pane-accounts.test.ts b/src/main/codex/codex-stale-pane-accounts.test.ts index 9cd9e6f4492..afdb58d53a8 100644 --- a/src/main/codex/codex-stale-pane-accounts.test.ts +++ b/src/main/codex/codex-stale-pane-accounts.test.ts @@ -1,5 +1,5 @@ import { afterEach, beforeEach, describe, expect, it } from 'vitest' -import { mkdtempSync, rmSync } from 'node:fs' +import { mkdtempSync, rmSync, writeFileSync } from 'node:fs' import { tmpdir } from 'node:os' import { join } from 'node:path' import type { GlobalSettings } from '../../shared/types' @@ -69,13 +69,51 @@ describe('codex pane account registry', () => { expect(getCodexPaneAccount('pty-19')).not.toBeNull() }) - it('reads back nothing when the registry file is corrupt', () => { + it('reads back nothing when the registry file is missing', () => { recordCodexPaneAccount('pty-1', { selectionKey: 'host', accountId: 'account-a' }) rmSync(join(userDataPath, 'codex-pane-accounts.json')) _internals.resetCache() expect(getCodexPaneAccount('pty-1')).toBeNull() }) + + it.each([ + ['unparseable JSON', '{ not json'], + ['a non-object document', '"panes"'], + ['an array document', '[]'], + ['a missing panes map', '{"version":1}'], + ['a non-object panes map', '{"version":1,"panes":[]}'] + ])('reads back nothing and still records when the file holds %s', (_label, contents) => { + writeFileSync(join(userDataPath, 'codex-pane-accounts.json'), contents) + _internals.resetCache() + + expect(getCodexPaneAccount('pty-1')).toBeNull() + // Why: a corrupt file must not wedge the registry — the next spawn has to + // still be attributable, or fix-3 prompts silently die on one bad write. + recordCodexPaneAccount('pty-1', { selectionKey: 'host', accountId: 'account-a' }) + _internals.resetCache() + expect(getCodexPaneAccount('pty-1')).toEqual({ selectionKey: 'host', accountId: 'account-a' }) + }) + + it('drops a malformed record without discarding its valid siblings', () => { + writeFileSync( + join(userDataPath, 'codex-pane-accounts.json'), + JSON.stringify({ + version: 1, + panes: { + 'pty-bad': { selectionKey: 7, accountId: 'account-a' }, + 'pty-good': { selectionKey: 'host', accountId: 'account-a' } + } + }) + ) + _internals.resetCache() + + expect(getCodexPaneAccount('pty-bad')).toBeNull() + expect(getCodexPaneAccount('pty-good')).toEqual({ + selectionKey: 'host', + accountId: 'account-a' + }) + }) }) describe('listStaleCodexPanes', () => {