Thanks to visit codestin.com
Credit goes to github.com

Skip to content

test: cover login-menu manage actions and prompt fallbacks - #560

Merged
ndycode merged 2 commits into
mainfrom
claude/audit-42-login-menu-actions-tests
Jun 11, 2026
Merged

ndycode merged 2 commits into
mainfrom
claude/audit-42-login-menu-actions-tests

Conversation

@ndycode

@ndycode ndycode commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Summary

Continues the direct-coverage push for the phase-4-extracted login machinery (sibling of #559, independent — based on main). lib/codex-manager/login-menu-actions.ts previously had only indirect CLI coverage; this adds test/login-menu-actions.test.ts (14 tests) for handleManageAction and the three prompt fallbacks.

The mocking is deliberately narrow: the real findMatchingAccountIndex runs (that identity matching is the thing under test), and only withAccountStorageTransaction is faked so each test controls the storage the handler reloads and captures exactly what it persists. runSwitchCommand, the login-oauth flow functions, and persistAndSyncSelectedAccount are mocked at the module boundary. process.stdin/stdout.isTTY are forced false (and restored) so the prompt fallbacks are deterministic regardless of the runner.

What the tests pin

Delete (the concurrency-safety core):

  • The account is re-resolved by identity inside the transaction — when a concurrent writer reordered on-disk storage, the right account is deleted at its new position, not whatever now sits at the menu's stale index.
  • activeIndex and every activeIndexByFamily entry rebalance: indexes after the removed row shift left, indexes pointing at the removed row clamp, families without an explicit entry inherit the adjusted activeIndex.
  • Vanished account → strict no-op: nothing persisted, the in-memory menu storage untouched, no "Deleted" message.
  • Deleting the last account resets activeIndex and all family indexes to 0.
  • On success the in-memory menu storage is synced to the persisted state.

Toggle: flips enabled both in the persisted storage and the in-memory copy, reports "Enabled"/"Disabled" with the 1-based row, and no-ops when the account vanished.

Switch: delegates to runSwitchCommand with the 1-based index and the storage deps bundle, without opening a transaction.

Refresh: non-TTY sign-in mode resolves to "browser" without prompting; success path resolves the selection then persistAccountPool([resolved], false) + syncSelectionToCodex(resolved); a failed OAuth flow is reported via console.error without persisting; an out-of-range index is ignored entirely.

Prompt fallbacks (non-TTY): sign-in → "browser", backup restore → "latest", manual backup → first entry or null.

Validation

  • vitest run test/login-menu-actions.test.ts — 14/14 passing
  • npm run typecheck — clean
  • npx eslint test/login-menu-actions.test.ts --max-warnings=0 — clean

https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB


Generated by Claude Code

note: greptile review for oc-chatgpt-multi-auth. cite files like lib/foo.ts:123. confirm regression tests + windows concurrency/token redaction coverage.

Greptile Summary

this pr adds test/login-menu-actions.test.ts — 14 direct-coverage tests for handleManageAction and the three non-tty prompt fallbacks in lib/codex-manager/login-menu-actions.ts. the mocking strategy is well-scoped: real findMatchingAccountIndex runs so identity-matching is exercised, and only withAccountStorageTransaction is faked to control disk state.

  • delete suite pins concurrency-safety (re-resolve by identity after concurrent reorder), index rebalancing across activeIndex/activeIndexByFamily, no-op on vanished account, and last-account reset.
  • toggle suite mirrors the same concurrency/no-op/enable/disable axes, including the reorder scenario that was flagged as missing in the prior review.
  • refresh suite now covers browser, manual, cancel (tty-mocked), non-transport bail-out, failed oauth, and out-of-range index paths — all gaps called out in the prior round are closed.

Confidence Score: 5/5

test-only change adding direct coverage for previously-untested login menu action handlers; no production code touched, no token or filesystem paths modified.

the change is purely additive test code. the mocking boundaries are correct, tty state is saved and restored in afterEach, and all concurrency/no-op/index-rebalance scenarios are explicitly exercised. the two unfilled assertion slots in the manual-refresh and last-account-deleted tests are harmless gaps, not regressions.

no files require special attention; the two minor assertion gaps in the manual-refresh and last-account-deleted tests are worth tightening but do not block merge.

Important Files Changed

Filename Overview
test/login-menu-actions.test.ts adds 14 direct-coverage tests for handleManageAction and the three prompt fallbacks; mocking strategy is correct and narrow; prior review gaps (toggle concurrent-reorder, no-op storage guard, refresh cancel/manual paths) all addressed; two minor assertion gaps remain in the manual-refresh and last-account-deleted cases

Fix All in Codex

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
test/login-menu-actions.test.ts:396-415
**manual refresh test under-asserted**

the browser-path test fully pins `persistAccountPoolMock`, `syncSelectionToCodexMock`, and `logSpy("Refreshed account 1.")`. the manual-mode test only checks `runOAuthFlowMock` was called with `"manual"` and `syncSelectionToCodexMock` was called. if the success branch were accidentally gated to browser-only (missing `persistAccountPool` call or no log line), the manual test would still pass. adding `expect(persistAccountPoolMock).toHaveBeenCalledWith([resolved], false)` and `expect(logSpy).toHaveBeenCalledWith("Refreshed account 1.")` closes that gap.

### Issue 2 of 2
test/login-menu-actions.test.ts:218-236
**"last account deleted" test skips in-memory sync assertions**

the first delete test explicitly asserts `storage.accounts` and `storage.activeIndex` are synced to the persisted state via `replaceManageActionStorage`. the "last account deleted" case only checks `persisted[0]` — it never verifies that the caller's in-memory `storage` object was mutated to reflect the empty state. adding `expect(storage.accounts).toEqual([])` and `expect(storage.activeIndex).toBe(0)` would confirm `replaceManageActionStorage` fired on this code path too.

Reviews (2): Last reviewed commit: "test: strengthen login-menu-actions cove..." | Re-trigger Greptile

The phase-4-extracted login-menu-actions.ts had only indirect CLI
coverage. This suite drives handleManageAction with the REAL
findMatchingAccountIndex (only the transaction wrapper is faked, so
each test controls the reloaded storage and captures persists):

- switch delegates to runSwitchCommand with a 1-based index and the
  storage deps bundle
- delete re-resolves the account by identity inside the transaction
  (stale-reorder safe), rebalances activeIndex and every
  activeIndexByFamily entry, no-ops when the account vanished, and
  resets all indexes when the pool empties
- toggle flips enabled in both persisted and in-memory storage and
  no-ops on vanished accounts
- refresh runs the OAuth flow (non-TTY mode resolves to browser),
  persists/syncs the resolved selection, reports failures without
  persisting, and ignores out-of-range indexes
- non-TTY fallbacks for the three prompts (browser / latest / first
  backup or null)

https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@ndycode, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 23 minutes and 39 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d6b07fd6-e298-40db-a0d0-328bf16aca1e

📥 Commits

Reviewing files that changed from the base of the PR and between 6ede089 and 0dc9288.

📒 Files selected for processing (1)
  • test/login-menu-actions.test.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/audit-42-login-menu-actions-tests
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/audit-42-login-menu-actions-tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment thread test/login-menu-actions.test.ts
Comment thread test/login-menu-actions.test.ts
Comment thread test/login-menu-actions.test.ts
Add the toggle concurrent-reorder scenario (same identity
re-resolution pipeline the delete suite proves), assert the in-memory
storage stays untouched on the toggle no-op, and cover the refresh
prompt's cancel/manual/non-transport branches by flipping TTY on with
the UI select stubbed (the prompt is same-module, so a module-boundary
mock cannot intercept it).

https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants