Update task documentation and test fixes
- Update Tasks.md with current progress and status - Fix useListData hook tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1,23 +1,3 @@
|
|||||||
### T-16 · Centralise `PAGE_SIZE` frontend constants
|
|
||||||
|
|
||||||
**Where found:** `frontend/src/hooks/useBans.ts:14` (`PAGE_SIZE = 100`); `frontend/src/pages/HistoryPage.tsx:45` (`PAGE_SIZE = 50`)
|
|
||||||
|
|
||||||
**Why this is needed:** Page sizes can silently diverge from backend defaults. If the backend changes `_DEFAULT_PAGE_SIZE`, the frontend won't know. Having multiple files define the same concept differently is also misleading.
|
|
||||||
|
|
||||||
**Goal:** All pagination constants in `frontend/src/utils/constants.ts`.
|
|
||||||
|
|
||||||
**What to do:**
|
|
||||||
1. Add `BAN_PAGE_SIZE = 100`, `HISTORY_PAGE_SIZE = 50` to `frontend/src/utils/constants.ts` (create it if it doesn't exist).
|
|
||||||
2. Replace local `const PAGE_SIZE = ...` in each hook/page with imports.
|
|
||||||
|
|
||||||
**Possible traps and issues:** Trivial. Verify test snapshots don't hard-code the old inline constant.
|
|
||||||
|
|
||||||
**Docs changes needed:** None.
|
|
||||||
|
|
||||||
**Doc references:** `frontend/src/utils/constants.ts`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### T-17 · `useHistory` is missing abort-signal guards — stale state update bug
|
### T-17 · `useHistory` is missing abort-signal guards — stale state update bug
|
||||||
|
|
||||||
**Where found:** `frontend/src/hooks/useHistory.ts` — `.then()`, `.catch()`, `.finally()` callbacks update state without checking `abortRef.current.signal.aborted`
|
**Where found:** `frontend/src/hooks/useHistory.ts` — `.then()`, `.catch()`, `.finally()` callbacks update state without checking `abortRef.current.signal.aborted`
|
||||||
|
|||||||
@@ -76,4 +76,37 @@ describe("useListData", () => {
|
|||||||
expect(fetcher).toHaveBeenCalledTimes(2);
|
expect(fetcher).toHaveBeenCalledTimes(2);
|
||||||
expect(result.current.items).toEqual(["second"]);
|
expect(result.current.items).toEqual(["second"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not update state when signal is aborted before resolution", async () => {
|
||||||
|
const abortedSignals: AbortSignal[] = [];
|
||||||
|
const fetcher = vi.fn().mockImplementation(async (signal: AbortSignal) => {
|
||||||
|
abortedSignals.push(signal);
|
||||||
|
// Simulate a delay
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
||||||
|
return { items: ["late"] };
|
||||||
|
});
|
||||||
|
const selector = vi.fn((response: { items: string[] }) => response.items);
|
||||||
|
|
||||||
|
const { result, unmount } = renderHook(() =>
|
||||||
|
useListData({
|
||||||
|
fetcher,
|
||||||
|
selector,
|
||||||
|
errorMessage: "Failed to load",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Unmount immediately to trigger abort
|
||||||
|
await act(async () => {
|
||||||
|
await Promise.resolve();
|
||||||
|
});
|
||||||
|
unmount();
|
||||||
|
|
||||||
|
// Verify at least one signal was collected and it was aborted
|
||||||
|
expect(abortedSignals.length).toBeGreaterThan(0);
|
||||||
|
const lastSignal = abortedSignals[abortedSignals.length - 1];
|
||||||
|
expect(lastSignal != null && lastSignal.aborted).toBe(true);
|
||||||
|
|
||||||
|
// Items should not be updated after abort
|
||||||
|
expect(result.current.items).toEqual([]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user