Skip to content

Commit 97dbfb2

Browse files
committed
test(client-react): give the package a test harness and pin realtime hook behavior (#4682)
`packages/client-react` shipped 8 public hooks with `build` and `typecheck` as its only scripts and zero test files. `tsc --noEmit` is structurally blind to what actually breaks in a hook: a dependency array is a value, not a type, so a missing entry, a missing cleanup and a callback that never fires all typecheck perfectly. #4678 was exactly that shape — `useAutoRefresh` ignored predicate writes, the case that dirties a list hardest, and no type noticed. Adds the workspace's first DOM test environment (jsdom + @testing-library/react, `environment: 'jsdom'`; every other package runs `node`) and 17 tests over the realtime hooks covering the three things the type checker cannot see: - re-subscription driven by the dependency array — changing `object` opens a subscription on the new name and releases the old one, an unrelated re-render churns nothing, and the hooks key on the primitive `options?.recordId` / `options?.packageId` rather than the options object's identity, so an equal-but-new object stays a no-op; - release on unmount, including `useAutoRefresh`, which holds two subscriptions; - delivery — events reach state and callbacks, and `useAutoRefresh` refetches on the per-record *and* the bulk stream (the #4678 regression pin). Every assertion was verified by sabotage rather than assumed: dropping the `object` dep (1 failure), deleting a cleanup (3) and reverting `useAutoRefresh` to the single-stream version (3) each turn the suite red; reverting turns it green again. CI needs no wiring — `Test Core` partitions by package off `turbo ls`, and the new `test` script puts client-react on shard 2 (verified with scripts/partition-test-shards.mjs). No runtime code changed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LYnZrTwXbrctB8E8HpJAPT
1 parent 742cebb commit 97dbfb2

6 files changed

Lines changed: 926 additions & 88 deletions

File tree

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
"@objectstack/client-react": patch
3+
---
4+
5+
test(client-react): give the package a test harness and pin the realtime hooks' behavior (#4682)
6+
7+
`packages/client-react` shipped 8 public hooks with `build` and `typecheck` as
8+
its only scripts and not a single test file. `tsc --noEmit` cannot see any of
9+
what actually breaks in a hook: a dependency array is a value, not a type, so a
10+
missing entry, a missing cleanup, and a callback that never fires all typecheck
11+
perfectly. #4678 was precisely that shape — `useAutoRefresh` ignored predicate
12+
writes, the one case that dirties a list hardest, and no type noticed.
13+
14+
Adds the workspace's first DOM test environment (`jsdom` + `@testing-library/
15+
react`, `environment: 'jsdom'` — every other package runs `node`) and 17 tests
16+
over the realtime hooks, covering the three things the type checker is blind to:
17+
18+
- **Re-subscription on dependency change** — changing `object` opens a
19+
subscription on the new name and releases the old one; a re-render that
20+
changes nothing must not churn. Also pins that the hooks key on the primitive
21+
`options?.recordId` / `options?.packageId` rather than on the options object's
22+
identity, so an equal-but-new object stays a no-op.
23+
- **Release on unmount** — every subscription hook unsubscribes, including
24+
`useAutoRefresh`, which holds two.
25+
- **Delivery** — events reach state and callbacks, and `useAutoRefresh`
26+
refetches on the per-record *and* the bulk stream (the #4678 regression pin).
27+
28+
Each assertion was verified by sabotage: dropping the `object` dep, deleting a
29+
cleanup, and reverting `useAutoRefresh` to the single-stream version each turn
30+
the suite red, and only reverting turns it green again.
31+
32+
The package is picked up by CI's `Test Core` shards automatically — they
33+
partition by package off `turbo ls`, so a `test` script is all that was needed.
34+
35+
No runtime code changed.

packages/client-react/package.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
},
1515
"scripts": {
1616
"build": "tsup src/index.tsx --config ../../tsup.config.ts",
17+
"test": "vitest run",
18+
"test:watch": "vitest",
1719
"typecheck": "tsc --noEmit"
1820
},
1921
"peerDependencies": {
@@ -25,8 +27,14 @@
2527
"@objectstack/spec": "workspace:*"
2628
},
2729
"devDependencies": {
30+
"@testing-library/react": "^16.3.2",
2831
"@types/react": "^19.2.17",
29-
"typescript": "^6.0.3"
32+
"@types/react-dom": "^19.2.3",
33+
"jsdom": "^30.0.1",
34+
"react": "^19.2.8",
35+
"react-dom": "^19.2.8",
36+
"typescript": "^6.0.3",
37+
"vitest": "^4.1.10"
3038
},
3139
"keywords": [
3240
"objectstack",

0 commit comments

Comments
 (0)