Files
jellytau/src/lib/stores/libraryListingOrder.test.ts
T
dtourolle 231ffae626 fix(library): podcasts list newest episode first
A Jellypod podcast listed its episodes alphabetically. The store pinned
SortBy=SortName onto every drill-down, which overrode the order the
channel plugin returns — and since Jellypod prefixes played episodes with
"[Played]", the name sort also clumped every heard episode at the top.

Which order a container's children take is domain knowledge, so it moves
to Rust: the caller names the container (GetItemsOptions.parentKind) and
default_listing_sort answers with the sort. A channel folder is
PremiereDate descending, every other container keeps SortName ascending,
and a caller naming no container still gets no SortBy, so the paths that
rely on the server's own order keep it. An explicit sort always wins.

ChannelFolderItem with is_folder now maps to MediaKind::ChannelFolder
instead of collapsing into Folder — while both were Folder there was
nothing to key the rule on. The offline leg of the cache/server race
applies the same order, so the cached list no longer flashes in name
order before the server's arrives.

TRACES: UR-007 | DR-257 | UT-229, UT-230, UT-231
2026-08-23 18:38:24 +02:00

54 lines
1.7 KiB
TypeScript

/**
* What order a container's children come back in.
*
* The store used to pin `sortBy: "SortName"` onto every drill-down, which is
* where the podcast bug came from: a Jellypod channel folder lists its episodes
* newest-first, and an alphabetical sort not only lost that order but clumped
* every "[Played] …" title at the top. The store now says *what the container
* is* and lets Rust say how it orders — the same division as `SearchScope`.
*
* TRACES: UR-007 | DR-257 | UT-231
*/
import { describe, it, expect, beforeEach, vi } from "vitest";
const getItemsMock = vi.fn();
vi.mock("@tauri-apps/api/event", () => ({
listen: vi.fn(async () => () => {}),
}));
vi.mock("./auth", () => ({
auth: {
getRepository: () => ({ getItems: getItemsMock }),
},
}));
import { library } from "./library";
describe("library.loadItems ordering", () => {
beforeEach(() => {
getItemsMock.mockReset();
getItemsMock.mockResolvedValue({ items: [], totalRecordCount: 0 });
});
it("names the container rather than a sort field", async () => {
await library.loadItems("podcast-1", { parentKind: "channelFolder" });
const options = getItemsMock.mock.calls[0][1];
expect(options.parentKind).toBe("channelFolder");
// Naming a sort field here would put the ordering rule back in the
// presentation layer, which is the leak this fix removes.
expect(options.sortBy).toBeUndefined();
expect(options.sortOrder).toBeUndefined();
});
it("falls back to a plain folder when the caller names no container", async () => {
await library.loadItems("library-1");
const options = getItemsMock.mock.calls[0][1];
expect(options.parentKind).toBe("folder");
expect(options.sortBy).toBeUndefined();
});
});