Readarr handler tests never asserted which block the search and filter keys push, so transposing searching_block and filtering_block in a TableHandlingConfig went undetected. History already had both tests; add the five missing search key tests and the three missing filter key tests, covering the authors, books, author history, editions and book history tables. The books and editions tables configure no filtering_block, so they get no filter test.
No test moved a table or list selection off index 0 either, which made current_selection() and items[0] indistinguishable. Select a non-zero index in the tests covering every handler that reads a selected row, adding a decoy entry at index 0 so existing expected values stay meaningful. The profile, monitor and root folder lists inside the add author, edit author and add root folder prompts are a separate gap that a table-only sweep misses, so those are covered too, as are the book files, editions and releases tables held on the book details modal.
Several fixtures also asserted against a default value, so the expected result was indistinguishable from an unset field. The add author, edit author and add root folder bodies now expect non-default monitor options, and the quality and metadata profile ids are drawn from disjoint id pairs so the two lookups cannot be transposed.
An author's overview renders as the last line of a description box that
does not scroll, so a long overview overflows with no way to read the
rest. Pressing v on the author details Books tab now opens a popup
holding the full overview.
The popup owns its own ScrollableText, built fresh from the author's
overview when it opens and torn down on Esc so a reopened popup starts
at the top. Scrolling mutates only that owned state. The background
paragraph renders the Author record's overview, which carries no scroll
offset, so it cannot scroll along with the popup.
Add a view keybinding bound to v, cite it from the author details
context clues, and give the popup its own clue set so it does not
inherit the hints of the view underneath.
Handles the delete book prompt opened from the author details view,
toggling whether to delete files on disk and whether to add a list
exclusion before confirming.
Backing out of the prompt resets both toggles, so preferences from an
abandoned delete cannot leak into the next one.
Handles the delete author prompt, toggling whether to delete files on
disk and whether to add a list exclusion before confirming.
Backing out of the prompt resets both toggles, so preferences from an
abandoned delete cannot leak into the next one.
Handles the multi-step edit prompt covering monitored, monitor new
items, quality profile, metadata profile, path, tags, and confirmation.
The prompt can be opened from either the author list or the author
details view, so the originating block is threaded through to the
sub-block pushes and Esc returns to the view the user came from.
Handles the add author search input, search results, and the multi-step
add prompt covering root folder, monitor, monitor new items, quality
profile, metadata profile, tags, and confirmation.
Selecting a search result whose foreign author id already exists in the
library routes to the already-in-library popup instead of the add
prompt, so a duplicate add cannot be submitted.
Add EditionDetailsHandler, the single block popup opened from the editions
table. It owns the arrow, Home and End scrolling over its ScrollableText body,
and the Esc that pops the popup and clears the edition details modal.
The handler is nested under BookDetailsHandler, which claims the block ahead
of its own tables. It never sees the keypress that opens it, so it performs no
build, and it dispatches no network events: the popup is assembled from an
already loaded row.
Scrolling is implemented rather than stubbed. The body is mostly the edition
overview, which routinely overflows the popup, so empty scroll methods would
leave the arrow keys dead on the longest text in the view.
Add BookDetailsHandler, covering the editions, history and manual search
tables, the automatic search, manual download and delete book file prompts,
and tab movement across the book details modal.
Selecting an edition builds the EditionDetailsModal client side from the
already loaded row and pushes the popup block. Readarr has no edition detail
endpoint, so there is no network request and no event to dispatch.
The delete book file prompt is guarded on the book files table being
populated. Unlike Lidarr, where a track row carries its own file id, an
edition carries none and the file id comes from a separate table that can be
empty while editions are present.
Add LibraryHandler, which owns the authors table and its sort, search,
and filter overlays through TableHandlingConfig, along with the add,
edit, toggle monitoring, update all, and refresh key actions and the
delete prompt. Dispatch into it from ReadarrHandler and add the main tab
left and right movement helper.
authors_sorting_options offers eight sorts: name, status, quality
profile, metadata profile, books, size, monitored, and tags. It omits
the type and tracks sorts that the artists table has. GET /author never
returns authorType, so that column would be empty on every row, and
author statistics carry no track count.
Also cover the Readarr arm of handle_events, which was previously
unreachable from any test: neutering the arm entirely left the suite
green.