fix(playlists): an Undo puts a row back after its old neighbour, not at a stale index
A raw index recorded at removal drifted once anything changed before the Undo. Both lists now read the list fresh and re-insert each row after the row that preceded it (lib/reinsert). A failed watched toggle in a Plex playlist also puts the row's state back: its local copy was never re-seeded.
This commit is contained in:
@@ -152,14 +152,22 @@ describe("PlexPlaylistView · a row's menu", () => {
|
||||
it("removes a title with no confirm, and the toast's Undo puts it back at its index", async () => {
|
||||
mount([movie("1"), movie("2"), movie("3")]);
|
||||
await screen.findByText("Movie 2");
|
||||
vi.spyOn(api, "plexPlaylistRemoveItem").mockResolvedValue({} as never);
|
||||
vi.spyOn(api, "plexPlaylistRemoveItem").mockImplementation(async () => {
|
||||
// The server's side of it: the Undo reads the list fresh, and the row is gone from it.
|
||||
vi.mocked(api.plexPlaylist).mockResolvedValue({
|
||||
id: 5,
|
||||
title: "Films",
|
||||
items: [movie("1"), movie("3")],
|
||||
} as never);
|
||||
return {} as never;
|
||||
});
|
||||
const add = vi.spyOn(api, "plexPlaylistAddBulk").mockResolvedValue({} as never);
|
||||
await pick(() => fireEvent.contextMenu(rowOf("Movie 2")), "plex.playlist.removeFromPlaylist");
|
||||
await waitFor(() => expect(api.plexPlaylistRemoveItem).toHaveBeenCalledWith(5, "2"));
|
||||
expect(h.confirm).not.toHaveBeenCalled();
|
||||
await waitFor(() => expect(toast()?.message).toBe("plex.playlist.removedToast:Movie 2"));
|
||||
act(() => toast()!.action!.onClick());
|
||||
expect(add).toHaveBeenCalledWith(5, ["2"], [1]);
|
||||
await waitFor(() => expect(add).toHaveBeenCalledWith(5, ["2"], [1]));
|
||||
});
|
||||
|
||||
it("plays and removes a whole show from its group's menu", async () => {
|
||||
@@ -313,3 +321,24 @@ describe("PlexPlaylistView · the header's '…'", () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// E28 review E2: the watched toggle flips the view's LOCAL copy of the rows. On a failure the
|
||||
// resync refetches an identical list, react-query keeps the same `data`, and the copy was never
|
||||
// re-seeded — the row stayed "watched" on screen while Plex still had it unwatched.
|
||||
describe("PlexPlaylistView · a failed watched toggle", () => {
|
||||
it("puts the row's watched state back", async () => {
|
||||
mount([movie("1"), movie("2")]);
|
||||
await screen.findByText("Movie 2");
|
||||
vi.spyOn(api, "plexSetState").mockRejectedValue(new Error("offline"));
|
||||
await pick(() => fireEvent.contextMenu(rowOf("Movie 2")), "plex.markWatched");
|
||||
await waitFor(() =>
|
||||
expect(h.notify).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ level: "error", title: "plex.watchedFailed" }),
|
||||
),
|
||||
);
|
||||
await act(async () => {});
|
||||
fireEvent.keyDown(document.activeElement ?? document.body, { key: "Escape" });
|
||||
await openMenu(() => fireEvent.contextMenu(rowOf("Movie 2")));
|
||||
expect(menuRows()).toContain("plex.markWatched");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user