import { describe, it, expect } from "vitest"; import type { Library } from "$lib/api/types"; import { buildLibraryMosaic, assumedLibraryRatio } from "./libraryMosaic"; function lib( id: string, name: string, collectionType: string, favoritesScope?: Library["favoritesScope"], ): Library { return { id, name, collectionType, favoritesScope } as Library; } const MOVIES = lib("1", "Movies", "movies", "movies"); const SHOWS = lib("2", "Shows", "tvshows", "tv"); const MUSIC = lib("3", "Music", "music", "music"); const LIVETV = lib("4", "Live TV", "livetv"); describe("buildLibraryMosaic", () => { it("leads with the cross-library favourites entry", () => { const entries = buildLibraryMosaic([MOVIES]); expect(entries[0]).toMatchObject({ kind: "favorites", scope: "all", label: "Favourites", href: "/library/favorites", }); }); it("puts each library's own favourites tile right after it", () => { const entries = buildLibraryMosaic([MOVIES, MUSIC]); expect(entries.map((e) => e.label)).toEqual([ "Favourites", "Movies", "Favourite Movies", "Music", "Favourite Music", ]); }); it("links a category tile to that category's favourites tab", () => { const entries = buildLibraryMosaic([SHOWS]); const tile = entries.find((e) => e.label === "Favourite Shows"); expect(tile).toMatchObject({ kind: "favorites", scope: "tv", href: "/library/favorites?scope=tv", }); }); it("offers a category's favourites once, however many libraries share it", () => { const entries = buildLibraryMosaic([MOVIES, lib("5", "Kids Films", "movies", "movies")]); expect(entries.filter((e) => e.kind === "favorites" && e.scope === "movies")).toHaveLength(1); expect(entries.map((e) => e.label)).toEqual([ "Favourites", "Movies", "Favourite Movies", "Kids Films", ]); }); it("gives no favourites tile to a library kind favourites do not carve up", () => { const entries = buildLibraryMosaic([LIVETV]); expect(entries.map((e) => e.label)).toEqual(["Favourites", "Live TV"]); }); it("ignores a scope the favourites page does not offer as a tab", () => { const odd = lib("6", "Books", "books", "books" as Library["favoritesScope"]); const entries = buildLibraryMosaic([odd]); expect(entries.map((e) => e.label)).toEqual(["Favourites", "Books"]); }); it("keeps every library, and keys tiles uniquely", () => { const entries = buildLibraryMosaic([MOVIES, SHOWS, MUSIC, LIVETV]); expect(entries.filter((e) => e.kind === "library")).toHaveLength(4); expect(new Set(entries.map((e) => e.key)).size).toBe(entries.length); }); it("has nothing but the favourites entry when there are no libraries", () => { expect(buildLibraryMosaic([]).map((e) => e.key)).toEqual(["favorites:all"]); }); it("gives a category tile the shape of the library it follows", () => { const entries = buildLibraryMosaic([MUSIC, MOVIES]); const musicFavorites = entries.find((e) => e.label === "Favourite Music")!; const movieFavorites = entries.find((e) => e.label === "Favourite Movies")!; expect(musicFavorites.ratio).toBe(assumedLibraryRatio(MUSIC)); expect(movieFavorites.ratio).toBe(assumedLibraryRatio(MOVIES)); }); }); describe("assumedLibraryRatio", () => { it("assumes a square cover for music and a wide backdrop otherwise", () => { expect(assumedLibraryRatio(MUSIC)).toBe(1); expect(assumedLibraryRatio(MOVIES)).toBeCloseTo(16 / 9); expect(assumedLibraryRatio(LIVETV)).toBeCloseTo(16 / 9); }); });