fix(home): a shelf move acts on the order shown, one write at a time
- During a budget switch the rail shows the previous budget's payload (keepPreviousData) while the new key is empty; the move read that empty cache, found no tile and silently did nothing. It now acts on the order the rail rendered. - A refused move was undone only by a re-read; when that read failed too, the shelf kept showing the order the user had just been told was not saved. Moves are now written one at a time (the move rows wait, with a "saving" note), which makes restoring the shown order correct — the overlapping-moves problem that ruled a rollback out cannot occur.
This commit is contained in:
@@ -210,10 +210,7 @@ describe("Home — the comfort shelf's context menu", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("re-asks the server when a move fails instead of restoring a snapshot", async () => {
|
||||
// Writing a captured `before` back was wrong twice: two overlapping moves each reverted to their
|
||||
// own snapshot and the shelf settled on an order neither side held, and `before` is the WHOLE
|
||||
// payload, so the rollback also discarded any rail refresh that landed mid-flight.
|
||||
it("re-asks the server when a move fails", async () => {
|
||||
reorderComfortPins.mockRejectedValue(new Error("nope"));
|
||||
mount();
|
||||
await screen.findByText("Comfort A");
|
||||
@@ -223,6 +220,51 @@ describe("Home — the comfort shelf's context menu", () => {
|
||||
await waitFor(() => expect(discover).toHaveBeenCalledTimes(2));
|
||||
});
|
||||
|
||||
it("puts the shown order back when a move is refused, even if the re-read fails too", async () => {
|
||||
// Only a re-read used to undo a refused move — and when that read failed for the same reason the
|
||||
// write did, react-query kept the last data: the shelf showed the order the user had just been
|
||||
// told was not saved. With one write at a time, the order shown before it IS the server's.
|
||||
reorderComfortPins.mockRejectedValue(new Error("nope"));
|
||||
mount();
|
||||
await screen.findByText("Comfort A");
|
||||
discover.mockRejectedValue(new Error("still down"));
|
||||
fireEvent.contextMenu(screen.getByText("Comfort A"));
|
||||
fireEvent.click(item("home.shelf.moveRight"));
|
||||
await waitFor(() => expect(discover).toHaveBeenCalledTimes(2));
|
||||
await waitFor(() =>
|
||||
expect(screen.getAllByText(/^Comfort [ABC]$/).map((e) => e.textContent)).toEqual([
|
||||
"Comfort A",
|
||||
"Comfort B",
|
||||
"Comfort C",
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it("writes one move at a time: the rows wait, and say so, while one is being saved", async () => {
|
||||
reorderComfortPins.mockReturnValue(new Promise(() => {}));
|
||||
discover.mockResolvedValueOnce(payload()).mockReturnValue(new Promise(() => {}));
|
||||
mount();
|
||||
fireEvent.contextMenu(await screen.findByText("Comfort A"));
|
||||
fireEvent.click(item("home.shelf.moveRight"));
|
||||
await waitFor(() => expect(reorderComfortPins).toHaveBeenCalledTimes(1));
|
||||
fireEvent.contextMenu(screen.getByText("Comfort C"));
|
||||
// The first row carries the note, so its text is its label followed by the note.
|
||||
expect(item("home.shelf.moveFirst" + "home.shelf.moveSaving").disabled).toBe(true);
|
||||
expect(item("home.shelf.moveLeft").disabled).toBe(true);
|
||||
});
|
||||
|
||||
it("moves what the rail SHOWS while a new budget is still loading", async () => {
|
||||
// Under keepPreviousData the rail keeps the previous budget's payload on screen while the new
|
||||
// key holds nothing yet; the move read that empty cache, found no tile and did nothing.
|
||||
mount();
|
||||
await screen.findByText("Comfort A");
|
||||
discover.mockReturnValue(new Promise(() => {})); // the new budget never arrives
|
||||
fireEvent.click(screen.getByText("home.budget.short"));
|
||||
fireEvent.contextMenu(screen.getByText("Comfort A"));
|
||||
fireEvent.click(item("home.shelf.moveRight"));
|
||||
await waitFor(() => expect(reorderComfortPins).toHaveBeenCalledWith([7, 3, 9]));
|
||||
});
|
||||
|
||||
it("unpins with the pin id the shelf card carries", async () => {
|
||||
mount();
|
||||
fireEvent.contextMenu(await screen.findByText("Comfort C"));
|
||||
|
||||
Reference in New Issue
Block a user