Skip to content

Conversation

@arv
Copy link
Contributor

@arv arv commented Dec 17, 2025

Add mockRandom() utility for deterministic testing using a seeded pseudo-random number generator (LCG). Returns a Vitest mock that integrates with vi.restoreAllMocks() and supports TypeScript's using keyword for automatic cleanup.

Add mockRandom() utility for deterministic testing using a seeded
pseudo-random number generator (LCG). Returns a Vitest mock that
integrates with vi.restoreAllMocks() and supports TypeScript's
using keyword for automatic cleanup.
@vercel
Copy link

vercel bot commented Dec 17, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
replicache-docs Ready Ready Preview, Comment Jan 6, 2026 10:09pm
zbugs Ready Ready Preview, Comment Jan 6, 2026 10:09pm

@github-actions
Copy link

github-actions bot commented Dec 17, 2025

🐰 Bencher Report

Brancharv/mock-random
TestbedLinux
Click to view all benchmark results
BenchmarkFile SizeBenchmark Result
kilobytes (KB)
(Result Δ%)
Upper Boundary
kilobytes (KB)
(Limit %)
zero-package.tgz📈 view plot
🚷 view threshold
1,770.29 KB
(+0.00%)Baseline: 1,770.27 KB
1,805.68 KB
(98.04%)
zero.js📈 view plot
🚷 view threshold
240.20 KB
(0.00%)Baseline: 240.20 KB
245.00 KB
(98.04%)
zero.js.br📈 view plot
🚷 view threshold
65.95 KB
(0.00%)Baseline: 65.95 KB
67.27 KB
(98.04%)
🐰 View full continuous benchmarking report in Bencher

@github-actions
Copy link

github-actions bot commented Dec 17, 2025

🐰 Bencher Report

Brancharv/mock-random
Testbedself-hosted
Click to view all benchmark results
BenchmarkThroughputBenchmark Result
operations / second (ops/s)
(Result Δ%)
Lower Boundary
operations / second (ops/s)
(Limit %)
src/client/custom.bench.ts > big schema📈 view plot
🚷 view threshold
143,322.00 ops/s
(-77.41%)Baseline: 634,328.77 ops/s
-177,503.28 ops/s
(-123.85%)
src/client/zero.bench.ts > basics > All 1000 rows x 10 columns (numbers)📈 view plot
🚷 view threshold
2,680.93 ops/s
(+4.65%)Baseline: 2,561.72 ops/s
2,277.67 ops/s
(84.96%)
src/client/zero.bench.ts > pk compare > pk = N📈 view plot
🚷 view threshold
69,072.72 ops/s
(+6.78%)Baseline: 64,685.24 ops/s
56,811.68 ops/s
(82.25%)
src/client/zero.bench.ts > with filter > Lower rows 500 x 10 columns (numbers)📈 view plot
🚷 view threshold
4,090.00 ops/s
(+4.56%)Baseline: 3,911.50 ops/s
3,589.79 ops/s
(87.77%)
🐰 View full continuous benchmarking report in Bencher

@github-actions
Copy link

github-actions bot commented Dec 17, 2025

🐰 Bencher Report

Brancharv/mock-random
Testbedself-hosted
Click to view all benchmark results
BenchmarkThroughputBenchmark Result
operations / second (ops/s)
(Result Δ%)
Lower Boundary
operations / second (ops/s)
(Limit %)
1 exists: track.exists(album)📈 view plot
🚷 view threshold
15,007.36 ops/s
(+1.40%)Baseline: 14,800.30 ops/s
13,698.73 ops/s
(91.28%)
10 exists (AND)📈 view plot
🚷 view threshold
222,182.61 ops/s
(+1.71%)Baseline: 218,448.73 ops/s
211,894.32 ops/s
(95.37%)
10 exists (OR)📈 view plot
🚷 view threshold
4,356.79 ops/s
(+2.87%)Baseline: 4,235.11 ops/s
3,938.76 ops/s
(90.41%)
12 exists (AND)📈 view plot
🚷 view threshold
194,077.75 ops/s
(+0.68%)Baseline: 192,757.45 ops/s
184,362.37 ops/s
(94.99%)
12 exists (OR)📈 view plot
🚷 view threshold
3,600.10 ops/s
(+0.02%)Baseline: 3,599.21 ops/s
3,366.50 ops/s
(93.51%)
12 level nesting📈 view plot
🚷 view threshold
3,202.37 ops/s
(+2.08%)Baseline: 3,137.02 ops/s
2,928.73 ops/s
(91.46%)
2 exists (AND): track.exists(album).exists(genre)📈 view plot
🚷 view threshold
5,640.78 ops/s
(+0.67%)Baseline: 5,603.24 ops/s
5,214.19 ops/s
(92.44%)
3 exists (AND)📈 view plot
🚷 view threshold
2,243.07 ops/s
(+4.01%)Baseline: 2,156.63 ops/s
1,990.31 ops/s
(88.73%)
3 exists (OR)📈 view plot
🚷 view threshold
1,122.66 ops/s
(+3.39%)Baseline: 1,085.89 ops/s
1,001.04 ops/s
(89.17%)
5 exists (AND)📈 view plot
🚷 view threshold
351.34 ops/s
(+3.07%)Baseline: 340.88 ops/s
318.24 ops/s
(90.58%)
5 exists (OR)📈 view plot
🚷 view threshold
185.45 ops/s
(+2.98%)Baseline: 180.08 ops/s
167.36 ops/s
(90.25%)
Nested 2 levels: track > album > artist📈 view plot
🚷 view threshold
4,966.12 ops/s
(+2.67%)Baseline: 4,836.77 ops/s
4,509.45 ops/s
(90.80%)
Nested 4 levels: playlist > tracks > album > artist📈 view plot
🚷 view threshold
818.35 ops/s
(+3.01%)Baseline: 794.43 ops/s
740.99 ops/s
(90.55%)
Nested with filters: track > album > artist (filtered)📈 view plot
🚷 view threshold
4,157.37 ops/s
(+3.23%)Baseline: 4,027.20 ops/s
3,718.86 ops/s
(89.45%)
planned: playlist.exists(tracks)📈 view plot
🚷 view threshold
641.03 ops/s
(-1.82%)Baseline: 652.92 ops/s
623.22 ops/s
(97.22%)
planned: track.exists(album) OR exists(genre)📈 view plot
🚷 view threshold
174.10 ops/s
(+1.09%)Baseline: 172.22 ops/s
162.00 ops/s
(93.05%)
planned: track.exists(album) where title="Big Ones"📈 view plot
🚷 view threshold
8,089.00 ops/s
(+1.61%)Baseline: 7,960.76 ops/s
7,574.18 ops/s
(93.64%)
planned: track.exists(album).exists(genre)📈 view plot
🚷 view threshold
41.58 ops/s
(-0.16%)Baseline: 41.65 ops/s
40.05 ops/s
(96.31%)
planned: track.exists(album).exists(genre) with filters📈 view plot
🚷 view threshold
5,507.14 ops/s
(-2.19%)Baseline: 5,630.51 ops/s
5,335.20 ops/s
(96.88%)
planned: track.exists(playlists)📈 view plot
🚷 view threshold
4.23 ops/s
(+0.13%)Baseline: 4.23 ops/s
4.06 ops/s
(95.84%)
unplanned: playlist.exists(tracks)📈 view plot
🚷 view threshold
628.24 ops/s
(-0.90%)Baseline: 633.92 ops/s
606.36 ops/s
(96.52%)
unplanned: track.exists(album) OR exists(genre)📈 view plot
🚷 view threshold
47.55 ops/s
(-0.10%)Baseline: 47.60 ops/s
45.20 ops/s
(95.05%)
unplanned: track.exists(album) where title="Big Ones"📈 view plot
🚷 view threshold
59.12 ops/s
(-0.65%)Baseline: 59.50 ops/s
56.88 ops/s
(96.22%)
unplanned: track.exists(album).exists(genre)📈 view plot
🚷 view threshold
41.82 ops/s
(+0.89%)Baseline: 41.46 ops/s
39.81 ops/s
(95.17%)
unplanned: track.exists(album).exists(genre) with filters📈 view plot
🚷 view threshold
55.54 ops/s
(-4.02%)Baseline: 57.86 ops/s
55.50 ops/s
(99.92%)
unplanned: track.exists(playlists)📈 view plot
🚷 view threshold
4.11 ops/s
(-2.70%)Baseline: 4.23 ops/s
4.07 ops/s
(98.89%)
zpg: all playlists📈 view plot
🚷 view threshold
5.80 ops/s
(-0.27%)Baseline: 5.82 ops/s
5.69 ops/s
(98.09%)
zql: all playlists📈 view plot
🚷 view threshold
8.51 ops/s
(+6.65%)Baseline: 7.98 ops/s
6.99 ops/s
(82.12%)
zql: edit for limited query, inside the bound📈 view plot
🚷 view threshold
211,476.33 ops/s
(-3.50%)Baseline: 219,137.22 ops/s
201,420.43 ops/s
(95.24%)
zql: edit for limited query, outside the bound📈 view plot
🚷 view threshold
211,239.13 ops/s
(-7.51%)Baseline: 228,382.36 ops/s
197,931.95 ops/s
(93.70%)
zql: push into limited query, inside the bound📈 view plot
🚷 view threshold
112,343.91 ops/s
(-0.68%)Baseline: 113,110.04 ops/s
107,346.16 ops/s
(95.55%)
zql: push into limited query, outside the bound📈 view plot
🚷 view threshold
434,697.12 ops/s
(+4.81%)Baseline: 414,757.85 ops/s
360,849.20 ops/s
(83.01%)
zql: push into unlimited query📈 view plot
🚷 view threshold
345,460.43 ops/s
(+0.62%)Baseline: 343,341.03 ops/s
312,872.24 ops/s
(90.57%)
zqlite: all playlists📈 view plot
🚷 view threshold
1.90 ops/s
(+1.38%)Baseline: 1.88 ops/s
1.79 ops/s
(93.75%)
zqlite: edit for limited query, inside the bound📈 view plot
🚷 view threshold
78,111.27 ops/s
(-1.88%)Baseline: 79,610.27 ops/s
71,956.86 ops/s
(92.12%)
zqlite: edit for limited query, outside the bound📈 view plot
🚷 view threshold
79,886.82 ops/s
(-0.55%)Baseline: 80,331.51 ops/s
69,271.99 ops/s
(86.71%)
zqlite: push into limited query, inside the bound📈 view plot
🚷 view threshold
4,298.40 ops/s
(+3.88%)Baseline: 4,137.79 ops/s
3,984.95 ops/s
(92.71%)
zqlite: push into limited query, outside the bound📈 view plot
🚷 view threshold
91,616.95 ops/s
(+0.77%)Baseline: 90,918.67 ops/s
83,412.68 ops/s
(91.05%)
zqlite: push into unlimited query📈 view plot
🚷 view threshold
132,575.39 ops/s
(+2.29%)Baseline: 129,604.21 ops/s
119,588.30 ops/s
(90.20%)
🐰 View full continuous benchmarking report in Bencher

- Updated playwright dependency from ^1.53.2 to ^1.57.0 in:
  - packages/replicache-perf/package.json
  - packages/replicache/package.json
  - packages/shared/package.json
  - packages/zero-client/package.json

feat: add polyfill for Symbol.dispose in mock-random.ts

- Added a polyfill for Symbol.dispose to support environments lacking this feature.

fix: update vitest config to target es2022 and handle 'using' keyword

- Set target to es2022 in vitest config.
- Added support configuration to force transpilation of 'using' keyword for compatibility with Safari.
* const mock = mockRandom();
* expect(Math.random()).toBeCloseTo(0.00028, 5);
* expect(Math.random()).toBeCloseTo(0.75595, 5);
* mock.mockRestore();
Copy link
Contributor

Choose a reason for hiding this comment

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

this should technically be done in afterEach? since the mock wouldn't be restored if expect throws?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

using mock = mockRandom() would be the best

@@ -0,0 +1,53 @@
import {vi, type Mock} from 'vitest';

if (!Symbol.dispose) {
Copy link
Contributor

Choose a reason for hiding this comment

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

is the intent to add [dispose] to the mock returned by mockRandom?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This could use a comment.

I will explain in the code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

mocks are already Disposable

Copy link
Contributor Author

Choose a reason for hiding this comment

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

but that raises a question... what happens in the mocks code, investigating

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here it is:

if (Symbol.dispose) {
  mock[Symbol.dispose] = () => mock.mockRestore();
}

so if we provide the symbol before the mock is created it becomes Disposable.

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.

3 participants