Repository navigation
fix(test): Fixture args accept readonly tuples - #4250
Conversation
Fixtures written with `args: [...] as const` were rejected because `args` was typed as the mutable `Parameters<E>`. Type it as `Readonly<Parameters<E>>` in @data-client/core/mock and @data-client/test, restore `as const` in the docs examples #4246 dropped, and add a `fixtures` typeperf scenario. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K9dm6BAco8rRjbd6aLcJZB
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Staff engineer (Cursor agent): LGTM at 27f7017. Widening FOLLOW_UP (not for this PR): |
|
Size Change: 0 B Total Size: 103 kB ℹ️ View Unchanged
|
There was a problem hiding this comment.
Benchmark React
Details
| Benchmark suite | Current: 27f7017 | Previous: f992c21 | Ratio |
|---|---|---|---|
data-client: getlist-100 |
136.99 ops/s (± 4.1%) |
139.87 ops/s (± 5.1%) |
1.02 |
data-client: getlist-500 |
45.45 ops/s (± 3.2%) |
41.75 ops/s (± 3.9%) |
0.92 |
data-client: update-entity |
392.31 ops/s (± 8.4%) |
363.76 ops/s (± 7.6%) |
0.93 |
data-client: update-user |
350.99 ops/s (± 10.0%) |
312.5 ops/s (± 6.2%) |
0.89 |
data-client: getlist-500-sorted |
45.56 ops/s (± 9.1%) |
42.3 ops/s (± 9.8%) |
0.93 |
data-client: update-entity-sorted |
344.83 ops/s (± 6.6%) |
298.57 ops/s (± 5.1%) |
0.87 |
data-client: update-entity-multi-view |
357.14 ops/s (± 7.1%) |
303.31 ops/s (± 8.8%) |
0.85 |
data-client: list-detail-switch-10 |
9.07 ops/s (± 12.5%) |
6.71 ops/s (± 6.5%) |
0.74 |
data-client: update-user-10000 |
74.36 ops/s (± 14.8%) |
70.92 ops/s (± 11.8%) |
0.95 |
data-client: invalidate-and-resolve |
36.5 ops/s (± 5.7%) |
35.4 ops/s (± 6.3%) |
0.97 |
data-client: unshift-item |
217.39 ops/s (± 5.9%) |
192.31 ops/s (± 7.1%) |
0.88 |
data-client: delete-item |
303.03 ops/s (± 5.3%) |
270.27 ops/s (± 6.1%) |
0.89 |
data-client: move-item |
181.82 ops/s (± 8.7%) |
168.08 ops/s (± 9.9%) |
0.92 |
This comment was automatically generated by workflow using github-action-benchmark.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #4250 +/- ##
=======================================
Coverage 98.10% 98.10%
=======================================
Files 166 166
Lines 3166 3166
Branches 626 626
=======================================
Hits 3106 3106
Misses 18 18
Partials 42 42 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Benchmark
Details
| Benchmark suite | Current: 27f7017 | Previous: f992c21 | Ratio |
|---|---|---|---|
normalizeLong |
536 ops/sec (±3.39%) |
529 ops/sec (±3.12%) |
0.99 |
normalizeLong Values |
462 ops/sec (±1.12%) |
458 ops/sec (±0.66%) |
0.99 |
normalizeLong Scalar |
444 ops/sec (±2.74%) |
438 ops/sec (±2.95%) |
0.99 |
normalizeLong Scalar update |
1109 ops/sec (±0.33%) |
1109 ops/sec (±0.35%) |
1 |
denormalizeLong |
295 ops/sec (±5.76%) |
277 ops/sec (±5.86%) |
0.94 |
denormalizeLong Values |
272 ops/sec (±4.97%) |
263 ops/sec (±3.98%) |
0.97 |
denormalizeLong donotcache |
1335 ops/sec (±1.55%) |
1371 ops/sec (±0.63%) |
1.03 |
denormalizeLong Values donotcache |
947 ops/sec (±0.21%) |
925 ops/sec (±1.35%) |
0.98 |
denormalizeLong Scalar donotcache |
1527 ops/sec (±0.37%) |
1477 ops/sec (±0.37%) |
0.97 |
denormalizeShort donotcache 500x |
1761 ops/sec (±0.07%) |
1657 ops/sec (±0.91%) |
0.94 |
denormalizeShort 500x |
722 ops/sec (±5.74%) |
708 ops/sec (±6.66%) |
0.98 |
denormalizeShort 500x withCache |
9204 ops/sec (±0.09%) |
9194 ops/sec (±1.81%) |
1.00 |
queryShort 500x withCache |
4334 ops/sec (±0.06%) |
4209 ops/sec (±0.21%) |
0.97 |
buildQueryKey All |
67328 ops/sec (±0.52%) |
65146 ops/sec (±0.60%) |
0.97 |
query All withCache |
7321 ops/sec (±3.29%) |
7783 ops/sec (±2.29%) |
1.06 |
denormalizeLong with mixin Entity |
271 ops/sec (±7.42%) |
250 ops/sec (±6.64%) |
0.92 |
denormalizeLong withCache |
9424 ops/sec (±0.22%) |
9591 ops/sec (±0.93%) |
1.02 |
denormalizeLong withCache (Scalar churn) |
9311 ops/sec (±0.76%) |
9512 ops/sec (±0.85%) |
1.02 |
denormalizeLong Values withCache |
8331 ops/sec (±1.06%) |
8300 ops/sec (±1.18%) |
1.00 |
denormalizeLong Scalar withCache |
9631 ops/sec (±0.17%) |
9765 ops/sec (±0.24%) |
1.01 |
denormalizeLong Scalar update withCache |
7238 ops/sec (±0.46%) |
7183 ops/sec (±0.59%) |
0.99 |
denormalizeLong All withCache |
8225 ops/sec (±0.18%) |
8152 ops/sec (±0.36%) |
0.99 |
denormalizeLong Query-sorted withCache |
7737 ops/sec (±2.70%) |
8157 ops/sec (±2.05%) |
1.05 |
denormalizeLongAndShort withEntityCacheOnly |
2024 ops/sec (±0.24%) |
2036 ops/sec (±0.26%) |
1.01 |
denormalize bidirectional 50 |
5193 ops/sec (±10.41%) |
5082 ops/sec (±10.27%) |
0.98 |
denormalize bidirectional 50 donotcache |
57453 ops/sec (±0.21%) |
56500 ops/sec (±0.21%) |
0.98 |
getResponse |
6262 ops/sec (±5.53%) |
6497 ops/sec (±3.96%) |
1.04 |
getResponse (null) |
12763374 ops/sec (±0.44%) |
13044398 ops/sec (±0.44%) |
1.02 |
getResponse (clear cache) |
248 ops/sec (±7.66%) |
236 ops/sec (±7.93%) |
0.95 |
getSmallResponse |
5068 ops/sec (±1.07%) |
4987 ops/sec (±1.08%) |
0.98 |
getSmallInferredResponse |
3879 ops/sec (±0.53%) |
3886 ops/sec (±0.21%) |
1.00 |
getResponse Collection |
7041 ops/sec (±1.43%) |
6885 ops/sec (±1.87%) |
0.98 |
get Collection |
4534 ops/sec (±0.28%) |
4168 ops/sec (±0.28%) |
0.92 |
get Query-sorted |
7462 ops/sec (±2.69%) |
7342 ops/sec (±3.52%) |
0.98 |
setLong |
529 ops/sec (±0.21%) |
528 ops/sec (±0.33%) |
1.00 |
setLongWithMerge |
311 ops/sec (±1.01%) |
302 ops/sec (±0.82%) |
0.97 |
setLongWithSimpleMerge |
327 ops/sec (±0.52%) |
325 ops/sec (±1.20%) |
0.99 |
setSmallResponse 500x |
1121 ops/sec (±1.48%) |
1100 ops/sec (±1.83%) |
0.98 |
setMany 50x one-per-row |
148 ops/sec (±0.27%) |
147 ops/sec (±1.73%) |
0.99 |
setMany 50 batch |
4479 ops/sec (±0.64%) |
4502 ops/sec (±0.58%) |
1.01 |
setMany 500x one-per-row |
15.17 ops/sec (±0.44%) |
14.91 ops/sec (±0.43%) |
0.98 |
setMany 500 batch |
1823 ops/sec (±0.29%) |
1822 ops/sec (±1.06%) |
1.00 |
This comment was automatically generated by workflow using github-action-benchmark.
Requested by Nathaniel · project thread
Motivation
Fixtures written with
args: [...] as constfailed to type-check when passed toMockResolver,renderDataHook(),renderDataCompose()ormockInitialState()("The type 'readonly [...]' is 'readonly' and cannot be assigned to the mutable type"). #4246 had to dropas constfrom docs examples to get them checking, and the root andpackages/reactREADME "Integrated data mocking" snippets use exactly this shape.Solution
SuccessFixtureEndpoint.argsandErrorFixtureEndpoint.argsareReadonly<Parameters<E>>in@data-client/core/mockand@data-client/test; core's internaldispatchFixturetakesreadonly any[]. Interceptors take args as function params, so they're unaffected.as constin the MockResolver and unit-testing docs examples, updates the Fixtures API reference, regenerates skill references and playground editor types.fixturestypeperf scenario (100 fixture sets with mutable andas constargs, typedFixture<E>, interceptors,MockResolver,mockInitialState).Type-check cost (TS 7,
fixturesscenario): withas constremoved, 74,851 → 74,937 instantiations (+0.11%). As written, master reports 500 errors; this branch 0 errors at 76,837 (new budget entry; other budget entries untouched).Zero loss: every diagnostic with
@ts-expect-errorneutralized is identical before and after ontsconfig.test.json, both examples' typetests and app tsconfigs (946 lines, empty diff). A scratch check of typed and untypedas constfixtures passes on TS 4.8, 5.3, 6 and 7, and on 4.0 apart from a pre-existing loose arg check in rest's legacy 4.0 types (unchanged by this PR).🤖 Generated with Claude Code
https://claude.ai/code/session_01K9dm6BAco8rRjbd6aLcJZB
Generated by Claude Code
Note
Low Risk
Narrow TypeScript-only widening for fixture args; runtime mock behavior is unchanged aside from accepting readonly arrays at compile time.
Overview
Fixture
argsare typed asReadonly<Parameters<E>>instead of mutableParameters<E>in@data-client/coreand@data-client/test, andmockInitialState’s internaldispatchFixturenow acceptsreadonly any[]. That lets test fixtures useargs: [...] as constwithMockResolver,mockInitialState(),renderDataHook(), and Vue’srenderDataCompose()without TypeScript assignability errors.Docs, agent skill references, and playground editor
.d.tsfiles mirror the API change and restoreas constin examples. A changeset records patch bumps for core, test, react, and vue. CI typeperf adds afixturesscenario (mutable andas constargs, interceptors, typed fixtures) with a newbudget.jsonentry.Reviewed by Cursor Bugbot for commit 27f7017. Bugbot is set up for automated code reviews on this repo. Configure here.