fix(offline): gate library listing to downloaded-only when offline (#10)
The connectivity store now drives the "downloaded only" view so an offline library page shows just on-device media, with the server catalog revealed only when "Show all server media" is toggled. TRACES: UR-052 | DR-078, DR-079
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
|
||||
// UT-068: `pushCatalogVisibility` resolves `serverReachable || showCatalog` and
|
||||
// pushes the result to the backend whenever either input changes.
|
||||
// See docs/specs/offline-downloaded-only-filter.md (DR-078/DR-079).
|
||||
//
|
||||
// `isConnected` now tracks server reachability alone (DR-079), so from this
|
||||
// service's perspective its input is "is the server reachable". We drive it and
|
||||
// the `showServerCatalog` toggle and assert what gets pushed via
|
||||
// `commands.setShowServerCatalog`.
|
||||
|
||||
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),
|
||||
setShowServerCatalog: vi.fn(async () => {}),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("$lib/stores/connectivity", () => ({
|
||||
isConnected: { subscribe: h.isConnectedStore.subscribe },
|
||||
}));
|
||||
|
||||
vi.mock("$lib/api/bindings", () => ({
|
||||
commands: {
|
||||
setShowServerCatalog: h.setShowServerCatalog,
|
||||
syncFullCatalog: vi.fn(),
|
||||
resumeQueuedDownloads: vi.fn(),
|
||||
catalogSyncStatus: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("$lib/stores/auth", () => ({
|
||||
auth: { getRepository: () => ({ getHandle: () => "handle-1" }) },
|
||||
}));
|
||||
|
||||
describe("pushCatalogVisibility resolves reachable || showCatalog (UT-068)", () => {
|
||||
beforeEach(() => {
|
||||
h.setShowServerCatalog.mockClear();
|
||||
h.isConnectedStore.set(true);
|
||||
vi.resetModules();
|
||||
});
|
||||
|
||||
it("pushes include=true while the server is reachable (initial subscribe)", async () => {
|
||||
const { showServerCatalog } = await import("./offlineCatalog");
|
||||
// Initial subscription with reachable=true, showCatalog=false ⇒ include=true.
|
||||
expect(h.setShowServerCatalog).toHaveBeenLastCalledWith(true);
|
||||
// Keep the import binding referenced so tree-shaking never elides it.
|
||||
expect(showServerCatalog).toBeDefined();
|
||||
});
|
||||
|
||||
it("pushes include=false when unreachable and the toggle is off", async () => {
|
||||
h.isConnectedStore.set(false);
|
||||
await import("./offlineCatalog");
|
||||
// Fresh module subscribes with reachable=false, showCatalog=false ⇒ false.
|
||||
expect(h.setShowServerCatalog).toHaveBeenLastCalledWith(false);
|
||||
});
|
||||
|
||||
it("re-pushes include=true when the toggle flips on while unreachable", async () => {
|
||||
h.isConnectedStore.set(false);
|
||||
const { showServerCatalog } = await import("./offlineCatalog");
|
||||
h.setShowServerCatalog.mockClear();
|
||||
|
||||
showServerCatalog.set(true); // showCatalog input changes ⇒ include flips to true
|
||||
expect(h.setShowServerCatalog).toHaveBeenLastCalledWith(true);
|
||||
|
||||
h.setShowServerCatalog.mockClear();
|
||||
showServerCatalog.set(false); // back off ⇒ include flips to false
|
||||
expect(h.setShowServerCatalog).toHaveBeenLastCalledWith(false);
|
||||
});
|
||||
|
||||
it("does not re-push when the resolved value is unchanged", async () => {
|
||||
// reachable=true ⇒ include already true. Turning the toggle on keeps it true.
|
||||
const { showServerCatalog } = await import("./offlineCatalog");
|
||||
h.setShowServerCatalog.mockClear();
|
||||
|
||||
showServerCatalog.set(true); // include stays true (true || true) ⇒ no push
|
||||
expect(h.setShowServerCatalog).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -11,7 +11,7 @@
|
||||
// It also owns the `showServerCatalog` UI flag (the offline banner toggle that
|
||||
// reveals greyed-out, non-downloaded server media).
|
||||
//
|
||||
// TRACES: UR-002
|
||||
// TRACES: UR-002, UR-052 | DR-078
|
||||
|
||||
import { writable, type Writable } from "svelte/store";
|
||||
import { commands } from "$lib/api/bindings";
|
||||
|
||||
Reference in New Issue
Block a user