Skip to content

fix(test): Fixture args accept readonly tuples - #4250

Merged
ntucker merged 1 commit into
masterfrom
claude/project-thread-pbehtu
Oct 6, 2026
Merged

ntucker merged 1 commit into
masterfrom
claude/project-thread-pbehtu

Conversation

@ntucker

@ntucker ntucker commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator

Requested by Nathaniel · project thread

Motivation

Fixtures written with args: [...] as const failed to type-check when passed to MockResolver, renderDataHook(), renderDataCompose() or mockInitialState() ("The type 'readonly [...]' is 'readonly' and cannot be assigned to the mutable type"). #4246 had to drop as const from docs examples to get them checking, and the root and packages/react README "Integrated data mocking" snippets use exactly this shape.

const fixtures = [
  {
    endpoint: TodoResource.getList,
    args: [{ userId: 1 }] as const,
    response: [{ id: 1, title: 'Write tests', userId: 1 }],
  },
];

// Before: type error on `fixtures`. After: works as written
<MockResolver fixtures={fixtures}>
  <TodoList />
</MockResolver>;

Solution

  • SuccessFixtureEndpoint.args and ErrorFixtureEndpoint.args are Readonly<Parameters<E>> in @data-client/core/mock and @data-client/test; core's internal dispatchFixture takes readonly any[]. Interceptors take args as function params, so they're unaffected.
  • Restores as const in the MockResolver and unit-testing docs examples, updates the Fixtures API reference, regenerates skill references and playground editor types.
  • New fixtures typeperf scenario (100 fixture sets with mutable and as const args, typed Fixture<E>, interceptors, MockResolver, mockInitialState).

Type-check cost (TS 7, fixtures scenario): with as const removed, 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-error neutralized is identical before and after on tsconfig.test.json, both examples' typetests and app tsconfigs (946 lines, empty diff). A scratch check of typed and untyped as const fixtures 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 args are typed as Readonly<Parameters<E>> instead of mutable Parameters<E> in @data-client/core and @data-client/test, and mockInitialState’s internal dispatchFixture now accepts readonly any[]. That lets test fixtures use args: [...] as const with MockResolver, mockInitialState(), renderDataHook(), and Vue’s renderDataCompose() without TypeScript assignability errors.

Docs, agent skill references, and playground editor .d.ts files mirror the API change and restore as const in examples. A changeset records patch bumps for core, test, react, and vue. CI typeperf adds a fixtures scenario (mutable and as const args, interceptors, typed fixtures) with a new budget.json entry.

Reviewed by Cursor Bugbot for commit 27f7017. Bugbot is set up for automated code reviews on this repo. Configure here.

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
@ntucker ntucker self-assigned this Oct 6, 2026
@vercel

vercel Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
docs-site Ready Ready Preview Oct 6, 2026 3:36pm UTC

Request Review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-06T15:36:36.240107Z 27f7017 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

ntucker commented Oct 6, 2026

Copy link
Copy Markdown
Collaborator Author

Staff engineer (Cursor agent): LGTM at 27f7017. Widening args to Readonly<Parameters<E>> is the minimal, correct fix: mutable tuples still assign to it, response/interceptors keep spreading Parameters<E>, and nothing at runtime mutates args. The zero-diff diagnostic check across TS versions and the new fixtures typeperf budget (+0.11% instantiations on the like-for-like run) are good evidence, and restoring as const in the docs undoes the #4246 workaround instead of leaving it as drift.

FOLLOW_UP (not for this PR): SuccessFixtureEndpoint / ErrorFixtureEndpoint are still hand-copied in packages/core/src/mock/fixtureTypes.ts and packages/test/src/fixtureTypes.ts, and this PR had to make the identical edit in both. I assume the copy exists because @data-client/test still peers on @data-client/react ^0.12.15. When that floor next moves to a version whose core ships core/mock, @data-client/test can re-export those types instead of duplicating them, so the next fixture typing change lands once.

@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

Size Change: 0 B

Total Size: 103 kB

ℹ️ View Unchanged
Filename Size
examples/test-bundlesize/dist/App.js 1.46 kB
examples/test-bundlesize/dist/polyfill.js 307 B
examples/test-bundlesize/dist/rdcClient.js 10.9 kB
examples/test-bundlesize/dist/rdcEndpoint.js 8.07 kB
examples/test-bundlesize/dist/rdcNextjs.js 12.4 kB
examples/test-bundlesize/dist/rdcPipeableStream.js 9.7 kB
examples/test-bundlesize/dist/react.js 59.7 kB
examples/test-bundlesize/dist/webpack-runtime.js 784 B

compressed-size-action

@github-actions github-actions 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.

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

codecov Bot commented Oct 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.10%. Comparing base (a588e9d) to head (27f7017).
⚠️ Report is 2 commits behind head on master.

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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions github-actions 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.

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.

@ntucker
ntucker merged commit fc4b015 into master Oct 6, 2026
33 checks passed
@ntucker
ntucker deleted the claude/project-thread-pbehtu branch October 6, 2026 16:15

This branch was successfully deployed

1 active deployment
Preview — 27f7017d Deployed Oct 6, 2026 by vercel[bot]
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