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.
99 lines
4.7 KiB
TypeScript
99 lines
4.7 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import { FEED_VIEWS, FEED_VIEW_SPEC } from "../../lib/feedView";
|
|
import { GRID_GAP, columnsFor, itemWidthFor } from "./gridColumns";
|
|
|
|
// The floor of the viewport contract (1024x768) and its ceiling (ultrawide) are both column-count
|
|
// questions, so they are both testable here without a layout engine.
|
|
const FLOOR_GRID = 700; // the feed's grid width at a 1024px viewport with the filter rail pinned
|
|
const ULTRAWIDE_GRID = 3069; // measured: the feed's grid width at a 3440px viewport
|
|
|
|
describe("columnsFor", () => {
|
|
it("fits as many columns as the width allows when uncapped", () => {
|
|
expect(columnsFor(260, 3069, null)).toBe(11); // the pre-cap ultrawide measurement
|
|
expect(columnsFor(260, 700, null)).toBe(2);
|
|
});
|
|
|
|
// The GUTTERS have to be in the count, not just in itemWidthFor. Every other assertion in this file
|
|
// survives replacing `floor((w + GAP) / (minCol + GAP))` with the naive `floor(w / (minCol + GAP))`
|
|
// — the fixed widths agree, the capped cases are cap-bound, and the two loops compare columnsFor
|
|
// against itself, so they cancel any shared change. These are the exact-fit
|
|
// boundaries where the two formulas first disagree: an n-column row needs n*minCol + (n-1)*GAP, so
|
|
// at exactly that width the naive form loses the last column and wastes a third of the row.
|
|
it("counts the gutters, not one gap per column", () => {
|
|
const exactly3 = 3 * 260 + 2 * GRID_GAP; // 828
|
|
expect(columnsFor(260, exactly3, null)).toBe(3);
|
|
expect(columnsFor(260, exactly3 - 1, null)).toBe(2);
|
|
const exactly2 = 2 * 260 + GRID_GAP; // 536 — the FIRST width where the naive form is wrong
|
|
expect(columnsFor(260, exactly2, null)).toBe(2);
|
|
expect(columnsFor(260, exactly2 - 1, null)).toBe(1);
|
|
});
|
|
|
|
it("never returns 0 columns, however narrow", () => {
|
|
expect(columnsFor(260, 10, null)).toBe(1);
|
|
expect(columnsFor(260, 0, null)).toBe(1);
|
|
});
|
|
|
|
it("returns 1 for the single-column layout regardless of width or cap", () => {
|
|
expect(columnsFor(null, 3069, 8)).toBe(1);
|
|
});
|
|
|
|
it("caps the count, and the saved width goes into the items", () => {
|
|
expect(columnsFor(260, ULTRAWIDE_GRID, 8)).toBe(8);
|
|
expect(itemWidthFor(ULTRAWIDE_GRID, 11)).toBe(264); // uncapped: pinned near minCol
|
|
expect(itemWidthFor(ULTRAWIDE_GRID, 8)).toBe(369); // capped: the width lands in the card
|
|
});
|
|
|
|
it("does nothing below the width where that many columns already fit", () => {
|
|
// The cap must be a pure ultrawide affordance: at every width up to the point where 8 columns
|
|
// fit, capping at 8 has to return exactly what the uncapped grid would have.
|
|
const eightFitsAt = 8 * (260 + GRID_GAP) - GRID_GAP;
|
|
for (let w = 320; w < eightFitsAt; w += 17) {
|
|
expect(columnsFor(260, w, 8)).toBe(columnsFor(260, w, null));
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("FEED_VIEW_SPEC ultrawide policy", () => {
|
|
it("caps every multi-column view and leaves the single-column ones to their width cap", () => {
|
|
for (const view of FEED_VIEWS) {
|
|
const { minCol, maxCols, colMaxWidth } = FEED_VIEW_SPEC[view];
|
|
if (minCol == null) {
|
|
// A single column is capped by reading width, not by a column count.
|
|
expect(maxCols, `${view} is single-column`).toBeNull();
|
|
expect(colMaxWidth, `${view} needs a reading-width cap`).not.toBeNull();
|
|
} else {
|
|
expect(maxCols, `${view} would dilute on an ultrawide`).not.toBeNull();
|
|
}
|
|
}
|
|
});
|
|
|
|
it("keeps a capped view recognisably itself — its item stays near its own minCol", () => {
|
|
// The policy behind each number: on a 3440px ultrawide an item tops out around 1.5x the view's
|
|
// own minimum. Looser and the view dilutes anyway; tighter and e.g. cardsSmall grows into cards.
|
|
for (const view of FEED_VIEWS) {
|
|
const { minCol, maxCols } = FEED_VIEW_SPEC[view];
|
|
if (minCol == null || maxCols == null) continue;
|
|
const w = itemWidthFor(ULTRAWIDE_GRID, columnsFor(minCol, ULTRAWIDE_GRID, maxCols));
|
|
expect(w, `${view} item width at 3440`).toBeGreaterThanOrEqual(minCol);
|
|
expect(w, `${view} item width at 3440`).toBeLessThanOrEqual(Math.round(minCol * 1.6));
|
|
}
|
|
});
|
|
|
|
it("leaves the 1024px floor untouched — the cap never binds there", () => {
|
|
for (const view of FEED_VIEWS) {
|
|
const { minCol, maxCols } = FEED_VIEW_SPEC[view];
|
|
if (minCol == null) continue;
|
|
expect(columnsFor(minCol, FLOOR_GRID, maxCols)).toBe(columnsFor(minCol, FLOOR_GRID, null));
|
|
}
|
|
});
|
|
|
|
it("never lets the dense card grow as wide as the standard card", () => {
|
|
const at = (v: "cards" | "cardsSmall") => {
|
|
const { minCol, maxCols } = FEED_VIEW_SPEC[v];
|
|
return itemWidthFor(ULTRAWIDE_GRID, columnsFor(minCol, ULTRAWIDE_GRID, maxCols));
|
|
};
|
|
expect(at("cardsSmall")).toBeLessThan(at("cards"));
|
|
});
|
|
});
|