Skip to content

🧪 Add tests for isInRollout algorithm#544

Merged
sunnylqm merged 1 commit intomasterfrom
test-isinrollout-2512462468046287531
Apr 14, 2026
Merged

🧪 Add tests for isInRollout algorithm#544
sunnylqm merged 1 commit intomasterfrom
test-isinrollout-2512462468046287531

Conversation

@sunnylqm
Copy link
Copy Markdown
Contributor

@sunnylqm sunnylqm commented Apr 14, 2026

🎯 What: The testing gap in isInRollout.ts has been addressed. The murmurhash3_32_gc function was not tested for determinism and correct evaluation of UUIDs into rollout percentages.
📊 Coverage: Covered both murmurhash3_32_gc hash outputs (determinism, correct output modulo mapping, empty string) and the isInRollout function (correct comparisons against rollout thresholds, evaluating 0% and 100% rollout bounds). Tests utilize dynamic module imports and mocks to evaluate module-level calculated states cleanly.
Result: Test coverage significantly improved for algorithm-specific logic ensuring safe and predictable deterministic UUID-based percentage distributions. All 10 tests across the isInRollout.test.ts suite are passing.


PR created automatically by Jules for task 2512462468046287531 started by @sunnylqm

Summary by CodeRabbit

  • Tests

    • Added comprehensive test coverage for rollout computation logic, including validation of hash determinism, edge cases, and rollout threshold behavior.
  • Refactor

    • Adjusted internal module exports to support testing infrastructure.

Co-authored-by: sunnylqm <615282+sunnylqm@users.noreply.github.com>
@google-labs-jules
Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 14, 2026

📝 Walkthrough

Walkthrough

A new test suite was added for rollout functionality, including a test file that validates hash determinism and rollout computation logic, a test setup file that mocks React Native version information, and the murmurhash3_32_gc function was exported from the core rollout module.

Changes

Cohort / File(s) Summary
Test Suite
src/__tests__/isInRollout.test.ts, src/__tests__/setup.ts
Added comprehensive tests for hash function behavior and rollout logic, with mocks for React Native version and dynamic module imports to test state isolation.
Core Module Export
src/isInRollout.ts
Exported the murmurhash3_32_gc hash function to make it available for testing and external use; no functional changes to hashing or rollout logic.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A hash test hops with care,
Checking every value fair,
Rollouts spin like wheels of chance,
Murmurhash takes its dance,
100% tests now pass—hooray! 🎉

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: adding tests for the isInRollout algorithm. It is specific and directly related to the changeset's primary purpose.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test-isinrollout-2512462468046287531

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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/__tests__/isInRollout.test.ts (1)

34-36: Consider asserting exact empty-string hash output.

typeof === 'number' is weak here; checking the exact deterministic output gives stronger regression protection.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/__tests__/isInRollout.test.ts` around lines 34 - 36, Replace the weak
typeof assertion in the test for murmurhash3_32_gc('') with an exact equality
check against the deterministic numeric hash
(expect(murmurhash3_32_gc('')).toBe(0)); update the test case in
src/__tests__/isInRollout.test.ts to assert the exact output of
murmurhash3_32_gc for the empty string instead of using typeof.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/__tests__/isInRollout.test.ts`:
- Line 50: The dynamic import cache-busting currently uses Date.now() which can
collide; replace it with a monotonic nonce so each import path is unique across
rapid consecutive tests. In the test where you do const { isInRollout } = await
import(`../isInRollout?id=${Date.now()}`); introduce a monotonic counter (e.g.,
a module-scoped let monotonicNonce = 0 and increment it for each import, or a
helper getMonotonicNonce that returns ++monotonicNonce or
process.hrtime.bigint().toString()) and use that value in the import template
string instead of Date.now(); ensure the helper is declared in the test module
so the import line for isInRollout uses the monotonic value.

---

Nitpick comments:
In `@src/__tests__/isInRollout.test.ts`:
- Around line 34-36: Replace the weak typeof assertion in the test for
murmurhash3_32_gc('') with an exact equality check against the deterministic
numeric hash (expect(murmurhash3_32_gc('')).toBe(0)); update the test case in
src/__tests__/isInRollout.test.ts to assert the exact output of
murmurhash3_32_gc for the empty string instead of using typeof.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 180a7bad-7c77-4e73-b03e-d9e7d95c5f85

📥 Commits

Reviewing files that changed from the base of the PR and between 9317f66 and 425ca55.

📒 Files selected for processing (3)
  • src/__tests__/isInRollout.test.ts
  • src/__tests__/setup.ts
  • src/isInRollout.ts

describe('isInRollout', () => {
it('should return true when the rollout is greater than the hash modulo', async () => {
mockUuid = 'test1';
const { isInRollout } = await import(`../isInRollout?id=${Date.now()}`);
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.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cd /tmp && find . -name "isInRollout.test.ts" -type f 2>/dev/null | head -5

Repository: reactnativecn/react-native-update

Length of output: 59


🏁 Script executed:

find . -name "isInRollout.test.ts" -type f

Repository: reactnativecn/react-native-update

Length of output: 112


🏁 Script executed:

cat -n ./src/__tests__/isInRollout.test.ts

Repository: reactnativecn/react-native-update

Length of output: 3699


🏁 Script executed:

ls -la ./src/__tests__/ | grep -i setup

Repository: reactnativecn/react-native-update

Length of output: 134


🏁 Script executed:

cat -n ./src/__tests__/setup.ts

Repository: reactnativecn/react-native-update

Length of output: 1443


🏁 Script executed:

cat -n ./src/isInRollout.ts | head -50

Repository: reactnativecn/react-native-update

Length of output: 1773


🏁 Script executed:

cat -n ./src/isInRollout.ts | tail -30

Repository: reactnativecn/react-native-update

Length of output: 928


Use a monotonic nonce instead of Date.now() for dynamic-import cache busting.

Date.now() can repeat within the same millisecond, which risks reusing the same module cache key across consecutive tests and causing test flakiness when mockUuid values differ.

Suggested fix
+let importNonce = 0;
+const importFreshIsInRollout = () => import(`../isInRollout?id=${++importNonce}`);
+
 describe('isInRollout', () => {
   it('should return true when the rollout is greater than the hash modulo', async () => {
     mockUuid = 'test1';
-    const { isInRollout } = await import(`../isInRollout?id=${Date.now()}`);
+    const { isInRollout } = await importFreshIsInRollout();
     expect(isInRollout(25)).toBe(true);
   });

   it('should return false when the rollout is equal to the hash modulo', async () => {
     mockUuid = 'test1';
-    const { isInRollout } = await import(`../isInRollout?id=${Date.now()}`);
+    const { isInRollout } = await importFreshIsInRollout();
     expect(isInRollout(24)).toBe(false);
   });

   it('should return false when the rollout is less than the hash modulo', async () => {
     mockUuid = 'test1';
-    const { isInRollout } = await import(`../isInRollout?id=${Date.now()}`);
+    const { isInRollout } = await importFreshIsInRollout();
     expect(isInRollout(23)).toBe(false);
   });

   it('should evaluate correctly for a different uuid', async () => {
     mockUuid = 'test3';
-    const { isInRollout } = await import(`../isInRollout?id=${Date.now()}`);
+    const { isInRollout } = await importFreshIsInRollout();
     expect(isInRollout(1)).toBe(true);
     expect(isInRollout(0)).toBe(false);
     expect(isInRollout(-1)).toBe(false);
   });

   it('should always return false for 0% rollout', async () => {
     mockUuid = 'test1';
-    const { isInRollout } = await import(`../isInRollout?id=${Date.now()}`);
+    const { isInRollout } = await importFreshIsInRollout();
     expect(isInRollout(0)).toBe(false);
   });

   it('should always return true for 100% rollout', async () => {
     mockUuid = 'test1';
-    const { isInRollout } = await import(`../isInRollout?id=${Date.now()}`);
+    const { isInRollout } = await importFreshIsInRollout();
     expect(isInRollout(100)).toBe(true);
   });
 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/__tests__/isInRollout.test.ts` at line 50, The dynamic import
cache-busting currently uses Date.now() which can collide; replace it with a
monotonic nonce so each import path is unique across rapid consecutive tests. In
the test where you do const { isInRollout } = await
import(`../isInRollout?id=${Date.now()}`); introduce a monotonic counter (e.g.,
a module-scoped let monotonicNonce = 0 and increment it for each import, or a
helper getMonotonicNonce that returns ++monotonicNonce or
process.hrtime.bigint().toString()) and use that value in the import template
string instead of Date.now(); ensure the helper is declared in the test module
so the import line for isInRollout uses the monotonic value.

@sunnylqm sunnylqm merged commit 4d6d410 into master Apr 14, 2026
5 of 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