Files
siftlode/frontend/src/lib/listNav.scope.dom.test.tsx
T
peter 4aaaaa7860 chore(comments): drop epic, sprint and review-round ids from the code
The code cited its plan instead of saying why: `E28 review J4`, `(R6 S3b)`, `S1 justified…`,
`deep-review round 5`. That plan lives in the private ops repo, so for every reader of this one the
citation was noise, and a sentence whose subject was the plan step ("round 2 showed…") hid its
lesson behind an id. Each one is gone and the "why" kept: a bare citation is deleted, a sentence
carrying a lesson is reworded around it ("a later attempt showed…").

Measured (`scripts/audit_metrics.py`, product code): 652 lines in 270 files carried an epic code by
the definition the next commit holds (507 / 241 by the old, two-digit-only one) -> 0. Across all
code, tests, scripts and configs: ~1100 epic-code lines plus ~320 sprint/round ids.

Behaviour unchanged, checked mechanically: every changed .py file has the same AST once docstrings
are blanked; css/sh/toml/yml/json files are identical once comments are stripped; the only
non-comment changes in TS/JS are test titles, one description string in a contract table, and five
ESLint messages, whose text is all the gates snapshot diff holds. Not touched: Markdown (docs and
the changelog keep their history), Alembic migrations, TV episode notation (`S2 · E5`), DESIGN.md
ids (`C1`, `B4`, `S3h`), tracker ids (`SEC-16`, `DX-17`).

One stale claim fixed on the way: test_hls_reaper's docstring said the player checkpoints "every
10 s whether or not it is playing", which plex/stream.py calls wrong; it now says what the code does.
2026-10-05 00:19:39 +02:00

67 lines
2.4 KiB
TypeScript

// @vitest-environment jsdom
//
// The `list` key scope — what puts j/k, the arrows and Enter on the cheat sheet — is live only while a
// registered list has an item to land on. An empty download queue, a list still loading or one that
// failed mounts its container all the same, and the sheet listed the keys over nothing.
// Its own file: listNav keeps module state.
import { useRef } from "react";
import { afterEach, describe, expect, it } from "vitest";
import { cleanup, render, screen, waitFor } from "@testing-library/react";
import { navItemAttrs, useListNav } from "./listNav";
import { useActiveScopes } from "./keymap";
afterEach(cleanup);
function Scopes() {
return <output data-testid="scopes">{useActiveScopes().join(" ")}</output>;
}
function Queue({ count, onDelete }: { count: number; onDelete?: (i: number) => void }) {
const ref = useRef<HTMLDivElement>(null);
useListNav(ref, { enabled: true, onDelete });
return (
<div ref={ref}>
{count === 0 ? (
<p>Nothing queued</p>
) : (
Array.from({ length: count }, (_, i) => (
<div key={i} {...navItemAttrs(i)}>
item
</div>
))
)}
</div>
);
}
const page = (count: number, onDelete?: (i: number) => void) => (
<>
<Scopes />
<Queue count={count} onDelete={onDelete} />
</>
);
const scopes = () => screen.getByTestId("scopes").textContent!.split(" ");
describe("useListNav · the list key scope", () => {
it("is not live over a list with nothing in it, and is while it has items", async () => {
const { rerender } = render(page(0));
expect(scopes()).not.toContain("list");
rerender(page(2));
await waitFor(() => expect(scopes()).toContain("list"));
rerender(page(0));
await waitFor(() => expect(scopes()).not.toContain("list"));
});
// Delete is on the sheet only where a list can take an item out — a playlist's rows, not
// the feed or a Plex grid, where nothing answers it.
it("puts Delete on the sheet only for a list that removes items", async () => {
const { rerender } = render(page(2));
await waitFor(() => expect(scopes()).toContain("list"));
expect(scopes()).not.toContain("listDelete");
rerender(page(2, () => {}));
await waitFor(() => expect(scopes()).toContain("listDelete"));
rerender(page(0, () => {}));
await waitFor(() => expect(scopes()).not.toContain("listDelete"));
});
});