Summary
Add hook-level tests for useOptimisticLike and useOptimisticRepost, which optimistically update TanStack Query cache for video-social-metrics and video-user-interactions, then publish kind 7 / kind 16 / kind 5 events via useNostrPublish. These paths are high-traffic and easy to break silently (wrong keys, missing rollback).
Problem
- Both hooks live in
src/hooks/useOptimisticLike.ts and src/hooks/useOptimisticRepost.ts with no colocated tests.
- Components only mock these hooks (
FullscreenFeed.test.tsx, etc.), so cache updates, rollback on failure, and published event shapes are untested.
useOptimisticRepost depends on useRepostVideo as well — interactions between mutations need explicit assertions.
Expected outcome
renderHook + mocked useQueryClient, useNostrPublish, useToast, and for repost useRepostVideo, verifying:
- Optimistic cache deltas for like/repost counts and interaction flags.
publishEvent / repostVideo called with expected kinds and tags on toggle-on.
- Kind 5 delete path on undo-like / undo-repost when event IDs exist.
- Rollback restores previous cache snapshot when
publishEvent throws (match current catch behaviour).
What needs to be tested
useOptimisticLike.toggleLike
- Unlike: metrics
likeCount decrements (floored at 0); interactions hasLiked: false, likeEventId: null; kind 5 published with e pointing at currentLikeEventId when provided.
- Like: metrics increment; interactions updated; kind 7 (or actual kind used in source) published — assert against
useOptimisticLike implementation.
- Error path: after forced rejection from
publishEvent, prior metrics/interactions restored from snapshots.
useOptimisticRepost.toggleRepost
- Un-repost: repost count decrement;
publishEvent kind 5 with delete tags when currentRepostEventId set.
- Repost:
repostVideo invoked with originalPubkey / vineId; optimistic metrics/interactions updated.
- Error path: rollback behaviour consistent with source.
(Exact event kinds and tag shapes must match current files — do not assume from this issue text alone.)
Mocking strategy
vi.mock('@/hooks/useNostrPublish') → { mutateAsync: vi.fn() }.
vi.mock('@/hooks/usePublishVideo') → expose useRepostVideo with mutateAsync: vi.fn() for repost tests.
- Instantiate real
QueryClient or mock setQueryData/getQueryData — prefer real QueryClient for integration fidelity (same pattern as other hook tests).
Acceptance criteria
Related files
| File |
Role |
src/hooks/useOptimisticLike.ts |
Like / unlike |
src/hooks/useOptimisticRepost.ts |
Repost / un-repost |
src/hooks/useVideoSocialMetrics.ts |
Types for metrics cache shape |
Notes
- Keep tests behaviour-driven: assert public outcomes (cache + mocked publish calls), not internal
debugLog strings.
- If rollback is incomplete in production, tests should document current behaviour and file a follow-up bug — do not “fix” behaviour inside the test-only PR unless trivial.
Summary
Add hook-level tests for
useOptimisticLikeanduseOptimisticRepost, which optimistically update TanStack Query cache forvideo-social-metricsandvideo-user-interactions, then publish kind 7 / kind 16 / kind 5 events viauseNostrPublish. These paths are high-traffic and easy to break silently (wrong keys, missing rollback).Problem
src/hooks/useOptimisticLike.tsandsrc/hooks/useOptimisticRepost.tswith no colocated tests.FullscreenFeed.test.tsx, etc.), so cache updates, rollback on failure, and published event shapes are untested.useOptimisticRepostdepends onuseRepostVideoas well — interactions between mutations need explicit assertions.Expected outcome
renderHook+ mockeduseQueryClient,useNostrPublish,useToast, and for repostuseRepostVideo, verifying:publishEvent/repostVideocalled with expected kinds and tags on toggle-on.publishEventthrows (match currentcatchbehaviour).What needs to be tested
useOptimisticLike.toggleLikelikeCountdecrements (floored at 0); interactionshasLiked: false,likeEventId: null; kind 5 published withepointing atcurrentLikeEventIdwhen provided.useOptimisticLikeimplementation.publishEvent, prior metrics/interactions restored from snapshots.useOptimisticRepost.toggleRepostpublishEventkind 5 with delete tags whencurrentRepostEventIdset.repostVideoinvoked withoriginalPubkey/vineId; optimistic metrics/interactions updated.(Exact event kinds and tag shapes must match current files — do not assume from this issue text alone.)
Mocking strategy
vi.mock('@/hooks/useNostrPublish')→{ mutateAsync: vi.fn() }.vi.mock('@/hooks/usePublishVideo')→ exposeuseRepostVideowithmutateAsync: vi.fn()for repost tests.QueryClientor mocksetQueryData/getQueryData— prefer real QueryClient for integration fidelity (same pattern as other hook tests).Acceptance criteria
src/hooks/useOptimisticLike.test.tsandsrc/hooks/useOptimisticRepost.test.ts(or one file if preferred).npm run test+npx tsc --noEmitclean.Related files
src/hooks/useOptimisticLike.tssrc/hooks/useOptimisticRepost.tssrc/hooks/useVideoSocialMetrics.tsNotes
debugLogstrings.