Skip to content

test(ticket): fix flaky closeWorkflow mock.module race (unblock 3.1.41 deploy)#5

Merged
NindroidA merged 1 commit into
mainfrom
fix/closeworkflow-test-flake
May 30, 2026
Merged

test(ticket): fix flaky closeWorkflow mock.module race (unblock 3.1.41 deploy)#5
NindroidA merged 1 commit into
mainfrom
fix/closeworkflow-test-flake

Conversation

@NindroidA

@NindroidA NindroidA commented May 30, 2026

Copy link
Copy Markdown
Owner

The 3.1.41 hotfix (PR #3) merged to main but the CI run on main failed on 11 archiveAndCloseTicket tests — a bun mock.module process-global race where the SUT bound the real deps at import time (returned archived:false). Passed locally + on the PR check; only the main-push file order hit it. This re-asserts the seam mocks immediately before the dynamic SUT import. Test-only; unblocks the gated deploy.

Verified locally: tsc clean, biome ./src clean, bun test 1171/0 ×3 + synthetic poison-order scenario green.

Summary by CodeRabbit

  • Tests
    • Improved reliability of closeWorkflow unit tests by refactoring mock dependency injection to reduce module-resolution race conditions during test execution.

Review Change Stack

Copilot AI review requested due to automatic review settings May 30, 2026 23:05
@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown

Warning

Review limit reached

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

More reviews will be available in 11 minutes and 18 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 572ee824-6b1a-46cd-b4d7-84afc018c808

📥 Commits

Reviewing files that changed from the base of the PR and between 90dc39b and 372ee22.

📒 Files selected for processing (4)
  • src/utils/api/handlers/ticketHandlers.ts
  • src/utils/ticket/closeWorkflow.ts
  • tests/unit/utils/api/ticketHandlers.test.ts
  • tests/unit/utils/ticket/closeWorkflow.test.ts
📝 Walkthrough

Walkthrough

Test file refactoring that centralizes Bun mock registrations into an installSeamMocks() helper and invokes it both at module load and immediately before dynamic SUT import to prevent module-resolution races when binding seam dependencies.

Changes

Mock Setup Centralization

Layer / File(s) Summary
Mock helper definition and initial installation
tests/unit/utils/ticket/closeWorkflow.test.ts
Relocates transcript and forum-tag fakes (fakeFetchMessages, fakeEnsureForumTag, fakeApplyForumTags) to early scope, then adds installSeamMocks() helper that centralizes Bun mock.module() registrations for verifiedDelete, fetchAllMessages, forumTagManager, and ticket/builtinTypes with builtin passthrough tables and resolveBuiltinPingColumn, and invokes the helper at module load.
Pre-import mock enforcement
tests/unit/utils/ticket/closeWorkflow.test.ts
Re-invokes installSeamMocks() immediately before dynamically importing the SUT to explicitly guard against mock-binding races during import-time module resolution.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly identifies the main change: fixing a flaky mock.module race in closeWorkflow tests.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/closeworkflow-test-flake

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.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/unit/utils/ticket/closeWorkflow.test.ts`:
- Around line 122-147: The test installs seam module mocks via
installSeamMocks() using mock.module for paths like
src/utils/discord/verifiedDelete, src/utils/fetchAllMessages,
src/utils/forumTagManager, and src/utils/ticket/builtinTypes but never restores
them; update the test teardown (afterAll) to restore those mocked modules (e.g.,
call mock.restoreModule for each of the same module paths or re-register the
original exports captured before mocking) so exports like
verifiedThreadDelete/verifiedMessageDelete and resolveTicketType are returned to
the module registry and do not leak into other tests.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ea742230-857a-4592-a7be-cd03a92ee730

📥 Commits

Reviewing files that changed from the base of the PR and between 8ac8a3f and 90dc39b.

📒 Files selected for processing (1)
  • tests/unit/utils/ticket/closeWorkflow.test.ts

Comment thread tests/unit/utils/ticket/closeWorkflow.test.ts Outdated
@NindroidA NindroidA force-pushed the fix/closeworkflow-test-flake branch 5 times, most recently from 54e3064 to 59f0267 Compare May 30, 2026 23:53
…low module

Root cause of the flaky CI (11 archiveAndCloseTicket tests returning
archived:false on the push to main, green on macOS + on the PR check):
ticketHandlers.test.ts did `mock.module("ticket/closeWorkflow", () => ({
archiveAndCloseTicket: fake }))`. bun's mock.module is process-shared and is
NOT undone by mock.restore (verified on 1.2.17). On the Linux runner's file
order, that fake was registered before closeWorkflow.test.ts imported its SUT,
so closeWorkflow's entire suite exercised ticketHandlers' fake — whose return
value a sibling test sets to {archived:false} — instead of the real workflow.
macOS happened to evaluate closeWorkflow's real module first, hiding it.

Fix — remove the shared-module mock; inject instead:
- ticketHandlers.ts: registerTicketHandlers takes an optional injectable
  `archiveAndCloseTicket` (default = real). router.ts caller is unchanged.
- ticketHandlers.test.ts: drop mock.module(closeWorkflow); pass the fake as the
  3rd arg to registerTicketHandlers. Nothing mock.module's ticket/closeWorkflow
  anymore, so closeWorkflow.test always binds the real SUT.

Hardening (same spirit, makes closeWorkflow.test fully injection-based with zero
shared global state — no mock.module, no AppDataSource.getRepository patch):
- closeWorkflow.ts: archiveAndCloseTicket gains an optional `deps`
  (CloseWorkflowDeps) bundling fetchMessagesAsTranscript / ensureForumTag /
  applyForumTags / verifiedChannelDelete / resolveTicketType / builtinTypeInfo /
  archivedTicketRepo, defaulting to the real implementations. Production callers
  (events/ticket/close.ts, api/handlers/ticketHandlers.ts) are unchanged.
- closeWorkflow.test.ts: pass all fakes via `deps`; static-import the SUT; drop
  mock.module and the getRepository patch entirely.

Test-only behavior change; production code paths are identical (real defaults).
Verified: tsc clean, biome ./src clean, bun test 1171/0 (full + isolated +
[ticketHandlers, closeWorkflow] poison order).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@NindroidA NindroidA force-pushed the fix/closeworkflow-test-flake branch from 59f0267 to 372ee22 Compare May 30, 2026 23:53
@NindroidA NindroidA merged commit e432c05 into main May 30, 2026
2 checks passed
@NindroidA NindroidA deleted the fix/closeworkflow-test-flake branch May 30, 2026 23:54
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