Depends on
#1963. Do not start work here until enough seams have been extracted for the hooks listed below to be testable with renderHook without massive mock setups. Without that prerequisite, the tests this issue produces will either be trivial (covering already-pure surface) or brittle (RTL with many mocked providers per test). See discussion on #1927.
Scope clarification
The decomposition work extracts new hooks from TorrentTableOptimized.tsx (useTorrentSelection, useTorrentSelectionDerivations, useTorrentTableFilterExpr, useCompactViewSort, useCrossSeedOrchestration, useTorrentTableHotkeys, useBulkActionWrappers, useTorrentTableNotifications, useTorrentTableColumns, useTorrentTableVirtualization, useFilterLifecycle, useColumnDragAndDrop). Those new hooks are tested in their own decomposition PRs and are NOT covered by this issue.
This issue's scope is the pre-existing big hooks (useTorrentActions, useTorrentsList, useCrossSeedSearch, useTorrentExporter, useSpeedUnits, useLocalCrossSeedMatches, usePersistedFilters) plus lib/api.ts contract tests via MSW.
Problem
Cover the hooks with complex state and the API client layer. These are larger and need mocking (renderHook, MSW), so they come after the decomposition work and the pure-utility coverage in #1929.
Scope
Hooks (use renderHook from @testing-library/react)
| File |
Lines |
Priority |
What to cover |
hooks/useTorrentActions.ts |
1130 |
Critical |
All torrent operations, optimistic updates, bulk actions |
hooks/useTorrentsList.ts |
278 |
High |
Pagination, filter/search reset, cross-seed detection |
hooks/useCrossSeedSearch.tsx |
599 |
High |
Search state machine, polling, cooldown |
hooks/useTorrentExporter.ts |
222 |
High |
Export hook; covers dedupeTorrents, buildDownloadName, ensureUniqueFilename (may need light extraction to make internal pure helpers testable) |
lib/speedUnits.ts |
90 |
Medium |
useSpeedUnits hook + pure formatSpeedWithUnit (test together — one source file) |
lib/cross-seed-utils.ts |
152 |
Medium |
useLocalCrossSeedMatches hook + pure normalizePath / isInsideBase / isHardlinkManaged / toCompatibleMatch |
hooks/usePersistedFilters.ts |
~80 |
Medium |
localStorage sync, per-instance filter state |
useTorrentActions.ts is large enough that it should be its own PR (or multiple PRs grouped by operation type).
API (MSW)
lib/api.ts (2696 lines): contract tests for parameter serialization, error handling, response parsing
- Set up MSW handlers mirroring the OpenAPI surface
- Start with the endpoints exercised by the hooks above
Acceptance
- Each hook above has tests for its primary state transitions and at least one error path
- MSW set up under
web/src/test/ (or similar) with handlers for the covered endpoints
make test-frontend runs and passes
Depends on
#1963. Do not start work here until enough seams have been extracted for the hooks listed below to be testable with
renderHookwithout massive mock setups. Without that prerequisite, the tests this issue produces will either be trivial (covering already-pure surface) or brittle (RTL with many mocked providers per test). See discussion on #1927.Scope clarification
The decomposition work extracts new hooks from
TorrentTableOptimized.tsx(useTorrentSelection,useTorrentSelectionDerivations,useTorrentTableFilterExpr,useCompactViewSort,useCrossSeedOrchestration,useTorrentTableHotkeys,useBulkActionWrappers,useTorrentTableNotifications,useTorrentTableColumns,useTorrentTableVirtualization,useFilterLifecycle,useColumnDragAndDrop). Those new hooks are tested in their own decomposition PRs and are NOT covered by this issue.This issue's scope is the pre-existing big hooks (
useTorrentActions,useTorrentsList,useCrossSeedSearch,useTorrentExporter,useSpeedUnits,useLocalCrossSeedMatches,usePersistedFilters) pluslib/api.tscontract tests via MSW.Problem
Cover the hooks with complex state and the API client layer. These are larger and need mocking (renderHook, MSW), so they come after the decomposition work and the pure-utility coverage in #1929.
Scope
Hooks (use
renderHookfrom@testing-library/react)hooks/useTorrentActions.tshooks/useTorrentsList.tshooks/useCrossSeedSearch.tsxhooks/useTorrentExporter.tsdedupeTorrents,buildDownloadName,ensureUniqueFilename(may need light extraction to make internal pure helpers testable)lib/speedUnits.tsuseSpeedUnitshook + pureformatSpeedWithUnit(test together — one source file)lib/cross-seed-utils.tsuseLocalCrossSeedMatcheshook + purenormalizePath/isInsideBase/isHardlinkManaged/toCompatibleMatchhooks/usePersistedFilters.tsuseTorrentActions.tsis large enough that it should be its own PR (or multiple PRs grouped by operation type).API (MSW)
lib/api.ts(2696 lines): contract tests for parameter serialization, error handling, response parsingAcceptance
web/src/test/(or similar) with handlers for the covered endpointsmake test-frontendruns and passes