Test the dock's load-path clamp and keyboard resize direction

- notesDockWidth store initialization now clamps/defaults a bad
  localStorage value on load, not just on write (verified this fails
  without the clamp).
- The keyboard resize test asserts the exact widened/narrowed value
  instead of just that the setter was called, so a swapped or
  inverted arrow-key branch would be caught.
This commit is contained in:
2026-09-01 13:22:35 -07:00
parent 31e8f9df5f
commit 037ed78570
2 changed files with 47 additions and 1 deletions
@@ -95,4 +95,19 @@ describe("NotesDock", () => {
fireEvent.keyDown(handle, { key: "ArrowLeft" });
expect(state.setNotesDockWidth).toHaveBeenCalled();
});
it("widens on ArrowLeft and narrows on ArrowRight, by the exact step", () => {
// The dock sits on the right edge, so dragging or pressing left grows it
// and right shrinks it. Asserting only "was called" would pass even if
// the branches were swapped or the sign inverted.
state.activeTabKey = "home:p1";
render(<NotesDock />);
const handle = screen.getByRole("separator", { name: /resize notes/i });
fireEvent.keyDown(handle, { key: "ArrowLeft" });
expect(state.setNotesDockWidth).toHaveBeenLastCalledWith(368);
fireEvent.keyDown(handle, { key: "ArrowRight" });
expect(state.setNotesDockWidth).toHaveBeenLastCalledWith(336);
});
});
+32 -1
View File
@@ -1,4 +1,4 @@
import { describe, it, expect } from "vitest";
import { describe, it, expect, afterEach, vi } from "vitest";
import {
clampDockWidth,
NOTES_DOCK_MIN_WIDTH,
@@ -29,3 +29,34 @@ describe("clampDockWidth", () => {
expect(clampDockWidth(400.6)).toBe(401);
});
});
// The pure function above is only half the contract: the brief calls out that
// the clamp must guard the *read* path too, because localStorage can carry
// anything a previous version, a hand edit, or a different screen left
// behind. These tests exercise the real store initialization — seeding
// localStorage, then re-importing the module fresh so its top-level
// `loadNotesDockWidth()` call runs against the seeded value — rather than a
// function pulled out just to make this testable. A future refactor that
// dropped the clamp from the load path while keeping it on the write path
// would fail these.
describe("notesDockWidth store initialization", () => {
const WIDTH_KEY = "triple-c.notes.dock.width";
afterEach(() => {
localStorage.removeItem(WIDTH_KEY);
});
it("clamps an out-of-range stored value on load", async () => {
localStorage.setItem(WIDTH_KEY, "99999");
vi.resetModules();
const { useAppState } = await import("./appState");
expect(useAppState.getState().notesDockWidth).toBe(NOTES_DOCK_MAX_WIDTH);
});
it("falls back to the default for a non-numeric stored value on load", async () => {
localStorage.setItem(WIDTH_KEY, "banana");
vi.resetModules();
const { useAppState } = await import("./appState");
expect(useAppState.getState().notesDockWidth).toBe(NOTES_DOCK_DEFAULT_WIDTH);
});
});