fix(e4): address code-review findings (a11y sweep + dedup guards)
Resolves the 5 /code-review high findings on this branch: - a11y sweep: extend aria-label to the remaining icon-only Plex card buttons the first pass missed — PlexPosterCard Info, SeasonCard watched-toggle + add-season (EpisodeCard already had them). "Fix a principle everywhere, in one sweep." - new shared lib/parseId.ts `parsePositiveIntId`, used by BOTH readSelectedId (now guarding the stored ?pl fallback the same as the URL — was unguarded) and plexSubUrl's ?v=playlist decode; removes the hand-duplicated guard. - PAGE_KEY exported from navigationInit and imported by NavigationProvider (was defined in both). - hoist a `watchedLabel` const per card so title + aria-label can't drift. +8 tests (parseId unit + guarded-stored ?pl); full FE gate green (tsc/eslint/ prettier/knip, 317 vitest).
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { parsePositiveIntId } from "./parseId";
|
||||
|
||||
describe("parsePositiveIntId", () => {
|
||||
it("accepts a positive integer", () => {
|
||||
expect(parsePositiveIntId("1")).toBe(1);
|
||||
expect(parsePositiveIntId("42")).toBe(42);
|
||||
});
|
||||
|
||||
it("rejects empty / nullish", () => {
|
||||
expect(parsePositiveIntId("")).toBeNull();
|
||||
expect(parsePositiveIntId(null)).toBeNull();
|
||||
expect(parsePositiveIntId(undefined)).toBeNull();
|
||||
});
|
||||
|
||||
it("rejects zero, negative, fractional, and non-numeric", () => {
|
||||
expect(parsePositiveIntId("0")).toBeNull();
|
||||
expect(parsePositiveIntId("-1")).toBeNull();
|
||||
expect(parsePositiveIntId("1.5")).toBeNull();
|
||||
expect(parsePositiveIntId("abc")).toBeNull();
|
||||
expect(parsePositiveIntId(" ")).toBeNull(); // Number(" ")===0
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
/** Parse a raw value to a positive-integer id, or null if it isn't one. A bare "" gives
|
||||
* Number("")===0 (finite but not positive), "1.5" is fractional, "-1"/"abc" invalid — all rejected.
|
||||
* The single guard behind the ?pl / ?v=playlist id params AND the stored playlist selection, so a bad
|
||||
* value (a malformed link, a legacy/corrupted storage entry) never selects a non-existent playlist. */
|
||||
export function parsePositiveIntId(raw: string | null | undefined): number | null {
|
||||
if (raw == null || raw === "") return null;
|
||||
const n = Number(raw);
|
||||
return Number.isInteger(n) && n > 0 ? n : null;
|
||||
}
|
||||
Reference in New Issue
Block a user