Skip to content

fix(test): prevent cross-file mock leak in SDK executor tests - #1075

Merged
namastex888 merged 1 commit into
devfrom
fix/sdk-mock-leak-ci
Apr 5, 2026
Merged

namastex888 merged 1 commit into
devfrom
fix/sdk-mock-leak-ci

Conversation

@namastex888

Copy link
Copy Markdown
Contributor

Summary

  • Remove mock.restore() from afterAll in both SDK test files -- it clears all process-global mock.module registrations, breaking whichever file runs second in CI
  • Add resetAllMocks() to shared _sdk-mocks.ts that does mockReset() + mockImplementation() for every shared mock (stronger than mockClear() which only clears call counts)
  • Use resetAllMocks() in both test files' beforeEach to guarantee clean slate regardless of file execution order
  • Use shared queryMock directly in concurrent delivery tests instead of dynamic imports

Root cause

Three interrelated issues caused CI-only failures (11 tests):

  1. mock.restore() in afterAll clears ALL process-global mock.module registrations, so whichever test file runs second loses its mocks
  2. mockClear() only clears call counts but does NOT reset mockImplementation() overrides set by other files' nested describe blocks
  3. Concurrent delivery afterEach restored queryMock via dynamic import without session_id in result events

Test plan

  • All 48 SDK executor tests pass (claude-sdk + claude-sdk-resume + sdk-session-capture)
  • Full suite: 2163/2163 pass, 0 fail
  • Typecheck clean
  • Lint clean (only pre-existing warnings)
  • Knip dead-code check clean

@coderabbitai

coderabbitai Bot commented Apr 5, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2426f604-d62c-4e52-bcd4-3b63cd924e54

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/sdk-mock-leak-ci

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.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a centralized resetAllMocks function in the shared test mocks file to ensure a clean state between tests and prevent cross-file leaks in the Bun test environment. It replaces manual mock clearing with this unified reset and removes afterAll(mock.restore()) calls in favor of per-test resets. Feedback focuses on ensuring all shared mocks, specifically directoryResolveMock, are included in the reset logic and moving the reset call to a top-level hook in claude-sdk.test.ts to guarantee isolation for all test cases.

terminateExecutorMock.mockReset();
terminateExecutorMock.mockImplementation(async () => undefined);

resetQueryMock();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The resetAllMocks function is missing a reset for directoryResolveMock. Since this mock is shared across test files and can be overridden (e.g., in claude-sdk.test.ts), it should be restored to its default implementation to ensure test isolation and prevent cross-file leaks.

  resetQueryMock();

  directoryResolveMock.mockReset();
  directoryResolveMock.mockImplementation(async (name: string) => ({
    entry: {
      name,
      dir: '/tmp/test',
      promptMode: 'system' as const,
      model: 'sonnet',
      registeredAt: new Date().toISOString(),
      permissions: { preset: 'full' },
    },
    builtin: false,
  }));

createAndLinkExecutorMock.mockClear();
updateExecutorStateMock.mockClear();
terminateExecutorMock.mockClear();
resetAllMocks();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

In this file, resetAllMocks() is only called within the World A registry integration block. To fully prevent cross-test leaks as intended by this PR, it should be moved to the top-level beforeEach (around line 35). This ensures that earlier tests (like spawn and deliver) also start with a clean slate, which is important since they rely on shared mocks like directory.resolve and queryMock.

Root cause: three interrelated issues caused CI-only failures:
1. mock.restore() in afterAll clears all process-global mock.module
   registrations, breaking whichever test file runs second
2. mockClear() only clears call counts but not mockImplementation()
   overrides set by other test files' nested describe blocks
3. Concurrent delivery afterEach set queryMock via dynamic import
   without session_id in result events

Fix:
- Add resetAllMocks() to _sdk-mocks.ts that does mockReset() +
  mockImplementation() for every shared mock function
- Use resetAllMocks() in both test files' beforeEach blocks
- Remove mock.restore() from both files' afterAll
- Use shared queryMock directly instead of dynamic imports
@namastex888
namastex888 force-pushed the fix/sdk-mock-leak-ci branch from da9ba74 to cafa880 Compare April 5, 2026 20:27
@namastex888
namastex888 merged commit c6ce9ff into dev Apr 5, 2026
6 checks passed
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.

1 participant