965c62c5cf
The Workspace page rendered `ConsoleArea` from two sites, picked by `currentLane`. Every flip of that value unmounted the whole console subtree and mounted it again at the other site: the terminal died, the run history went with it, and `LaneConsolePane`'s lane-switch effect wiped a half-typed prompt. It flipped on every page load (lanes arrive, `refreshLanes` selects `lanes[0]`), on a lane being removed, and on any refetch that re-picked the selection. `lane-detail` is now always rendered and holds the only `ConsoleArea`; the header and info block are the conditional parts. Same rule the RunConsole already followed one level down — collapse with CSS, never by unmounting — now enforced above it too. Second half: every poller fed `setState` a brand-new object graph each tick, re-rendering the lane strip, the card and the console area several times a minute on a completely idle dashboard. `keepIfSame` keeps the previous reference when the payload is value-identical, applied to the 5 s run/session poll, the lane list and counts, the `lane_update` WS branch, and LaneCard's git/runtime/locks pollers. Verified: npm run test:client (44 files / 454 tests), tsc --noEmit clean, check-headers.sh clean. The Run screen snapshot was regenerated — the diff is the added `<section>` wrapper and one indent level, no content change.
37 lines
1.2 KiB
TypeScript
37 lines
1.2 KiB
TypeScript
/**
|
|
* @file keepIfSame.test.ts
|
|
* @description Covers the identity contract `keepIfSame` exists for: a polled
|
|
* payload that is value-identical must keep the PREVIOUS reference (so React
|
|
* bails out of the re-render), and any real change must yield the new one.
|
|
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
|
*/
|
|
|
|
import { describe, it, expect } from "vitest";
|
|
import { keepIfSame } from "../keepIfSame";
|
|
|
|
describe("keepIfSame", () => {
|
|
it("keeps the previous reference when the fetched payload is value-identical", () => {
|
|
const prev = [{ id: 1, stage: "implement" }];
|
|
const fetched = [{ id: 1, stage: "implement" }];
|
|
|
|
expect(keepIfSame(fetched)(prev)).toBe(prev);
|
|
});
|
|
|
|
it("yields the new value when anything actually changed", () => {
|
|
const prev = [{ id: 1, stage: "implement" }];
|
|
const fetched = [{ id: 1, stage: "review" }];
|
|
|
|
expect(keepIfSame(fetched)(prev)).toBe(fetched);
|
|
});
|
|
|
|
it("yields the new value out of the null a poller starts from", () => {
|
|
const fetched = { available: false };
|
|
|
|
expect(keepIfSame(fetched)(null)).toBe(fetched);
|
|
});
|
|
|
|
it("keeps null when the payload is still null", () => {
|
|
expect(keepIfSame(null)(null)).toBeNull();
|
|
});
|
|
});
|