All checks were successful
🏗️ Build and Test JellyTau / Run Tests (push) Successful in 4m32s
Traceability Validation / Check Requirement Traces (push) Successful in 22s
Build & Release / Run Tests (push) Successful in 5m21s
🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 4m25s
Build & Release / Build Linux (push) Successful in 17m31s
Build & Release / Build Android (push) Successful in 22m5s
Build & Release / Create Release (push) Successful in 16s
131 lines
4.2 KiB
TypeScript
131 lines
4.2 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
import { render, screen, fireEvent } from "@testing-library/svelte";
|
|
|
|
// Controllable stores for the offline "server only" branch. Declared via
|
|
// vi.hoisted so they exist when the hoisted vi.mock factories run. A tiny
|
|
// writable shim avoids importing svelte inside the hoisted block.
|
|
const h = vi.hoisted(() => {
|
|
function shim<T>(initial: T) {
|
|
let value = initial;
|
|
const subs = new Set<(v: T) => void>();
|
|
return {
|
|
set(v: T) {
|
|
value = v;
|
|
subs.forEach((fn) => fn(value));
|
|
},
|
|
subscribe(fn: (v: T) => void) {
|
|
subs.add(fn);
|
|
fn(value);
|
|
return () => subs.delete(fn);
|
|
},
|
|
};
|
|
}
|
|
return {
|
|
isConnectedStore: shim(true),
|
|
showServerCatalogStore: shim(false),
|
|
downloadsStore: shim({ downloads: {} as Record<string, any> }),
|
|
downloadItem: vi.fn(async () => 1),
|
|
getUserId: vi.fn(() => "user-1"),
|
|
};
|
|
});
|
|
|
|
const { isConnectedStore, showServerCatalogStore, downloadsStore, downloadItem, getUserId } = h;
|
|
|
|
vi.mock("$lib/stores/connectivity", () => ({
|
|
isConnected: { subscribe: h.isConnectedStore.subscribe },
|
|
}));
|
|
|
|
vi.mock("$lib/services/offlineCatalog", () => ({
|
|
showServerCatalog: { subscribe: h.showServerCatalogStore.subscribe },
|
|
}));
|
|
|
|
vi.mock("$lib/stores/downloads", () => ({
|
|
downloads: { subscribe: h.downloadsStore.subscribe, downloadItem: h.downloadItem },
|
|
}));
|
|
|
|
vi.mock("$lib/stores/auth", () => ({
|
|
auth: { getUserId: h.getUserId },
|
|
}));
|
|
|
|
// CachedImage does async repo/image work irrelevant to these tests.
|
|
vi.mock("$lib/components/common/CachedImage.svelte", async () => ({
|
|
default: (await import("./__mocks__/StubImage.svelte")).default,
|
|
}));
|
|
|
|
import MediaCard from "./MediaCard.svelte";
|
|
|
|
const track = {
|
|
id: "track-1",
|
|
name: "Some Song",
|
|
type: "Audio" as const,
|
|
serverId: "server-1",
|
|
artists: ["Artist A"],
|
|
albumName: "Album X",
|
|
};
|
|
|
|
describe("MediaCard server-only (offline browse & queue)", () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
isConnectedStore.set(true);
|
|
showServerCatalogStore.set(false);
|
|
downloadsStore.set({ downloads: {} });
|
|
});
|
|
|
|
it("shows no queue button while online", () => {
|
|
render(MediaCard, { props: { item: track } });
|
|
expect(screen.queryByLabelText(/Queue download/i)).toBeNull();
|
|
});
|
|
|
|
it("shows no queue button when offline but the reveal toggle is off", () => {
|
|
isConnectedStore.set(false);
|
|
render(MediaCard, { props: { item: track } });
|
|
expect(screen.queryByLabelText(/Queue download/i)).toBeNull();
|
|
});
|
|
|
|
it("reveals a queue button when offline and the reveal toggle is on", () => {
|
|
isConnectedStore.set(false);
|
|
showServerCatalogStore.set(true);
|
|
render(MediaCard, { props: { item: track } });
|
|
expect(screen.getByLabelText(/Queue download for Some Song/i)).toBeTruthy();
|
|
});
|
|
|
|
it("queues the item for download with its metadata on click", async () => {
|
|
isConnectedStore.set(false);
|
|
showServerCatalogStore.set(true);
|
|
render(MediaCard, { props: { item: track } });
|
|
|
|
await fireEvent.click(screen.getByLabelText(/Queue download for Some Song/i));
|
|
|
|
expect(downloadItem).toHaveBeenCalledTimes(1);
|
|
const args = downloadItem.mock.calls[0] as unknown as any[];
|
|
expect(args[0]).toBe("track-1"); // itemId
|
|
expect(args[1]).toBe("user-1"); // userId
|
|
expect(args[5]).toBe("Some Song"); // itemName
|
|
expect(args[6]).toBe("Artist A"); // artistName
|
|
expect(args[7]).toBe("Album X"); // albumName
|
|
});
|
|
|
|
it("shows a Queued badge (not the button) for a pending download", () => {
|
|
isConnectedStore.set(false);
|
|
showServerCatalogStore.set(true);
|
|
downloadsStore.set({
|
|
downloads: { "track-1": { itemId: "track-1", status: "pending", progress: 0 } },
|
|
});
|
|
render(MediaCard, { props: { item: track } });
|
|
|
|
expect(screen.getByText(/Queued/i)).toBeTruthy();
|
|
expect(screen.queryByLabelText(/Queue download/i)).toBeNull();
|
|
});
|
|
|
|
it("does not grey out a completed download", () => {
|
|
isConnectedStore.set(false);
|
|
showServerCatalogStore.set(true);
|
|
downloadsStore.set({
|
|
downloads: { "track-1": { itemId: "track-1", status: "completed", progress: 1 } },
|
|
});
|
|
render(MediaCard, { props: { item: track } });
|
|
|
|
expect(screen.queryByLabelText(/Queue download/i)).toBeNull();
|
|
});
|
|
});
|