Files
jellytau/src/lib/services/favorites.test.ts
T

160 lines
4.9 KiB
TypeScript

/**
* Favorites service tests
*
* TRACES: UR-017 | DR-021
*/
import { describe, it, expect, beforeEach, vi } from "vitest";
import { toggleFavorite } from "./favorites";
vi.mock("@tauri-apps/api/core", () => ({
invoke: vi.fn(async (command: string) => {
if (command === "storage_toggle_favorite") {
return undefined;
}
if (command === "storage_mark_synced") {
return undefined;
}
return null;
}),
}));
vi.mock("$lib/stores/auth", () => ({
auth: {
getUserId: vi.fn(() => "user-123"),
getRepository: vi.fn(() => ({
markFavorite: vi.fn(async () => undefined),
unmarkFavorite: vi.fn(async () => undefined),
})),
},
}));
describe("favorites service", () => {
beforeEach(() => {
vi.clearAllMocks();
});
describe("toggleFavorite", () => {
it("should toggle favorite to true", async () => {
const result = await toggleFavorite("item-123", false);
expect(result).toBe(true);
});
it("should toggle favorite to false", async () => {
const result = await toggleFavorite("item-123", true);
expect(result).toBe(false);
});
it("should update local database", async () => {
const { invoke } = await import("@tauri-apps/api/core");
const invokeSpy = vi.mocked(invoke);
await toggleFavorite("item-123", false);
const call = invokeSpy.mock.calls.find(
(c) => c[0] === "storage_toggle_favorite"
);
expect(call).toBeDefined();
expect(call![1]).toHaveProperty("itemId", "item-123");
expect(call![1]).toHaveProperty("isFavorite", true);
});
it("should include userId in storage call", async () => {
const { invoke } = await import("@tauri-apps/api/core");
const invokeSpy = vi.mocked(invoke);
await toggleFavorite("item-123", false);
const call = invokeSpy.mock.calls.find(
(c) => c[0] === "storage_toggle_favorite"
);
expect(call![1]).toHaveProperty("userId", "user-123");
});
it("should sync to server when marking as favorite", async () => {
const { auth } = await import("$lib/stores/auth");
const authModule = vi.mocked(auth);
const mockRepo = {
markFavorite: vi.fn(async () => undefined),
unmarkFavorite: vi.fn(async () => undefined),
};
authModule.getRepository = vi.fn(() => mockRepo as any);
await toggleFavorite("item-123", false);
expect(mockRepo.markFavorite).toHaveBeenCalledWith("item-123");
});
it("should sync to server when unmarking as favorite", async () => {
const { auth } = await import("$lib/stores/auth");
const authModule = vi.mocked(auth);
const mockRepo = {
markFavorite: vi.fn(async () => undefined),
unmarkFavorite: vi.fn(async () => undefined),
};
authModule.getRepository = vi.fn(() => mockRepo as any);
await toggleFavorite("item-123", true);
expect(mockRepo.unmarkFavorite).toHaveBeenCalledWith("item-123");
});
it("should mark as synced after successful server update", async () => {
const { invoke } = await import("@tauri-apps/api/core");
const invokeSpy = vi.mocked(invoke);
await toggleFavorite("item-123", false);
const markSyncedCall = invokeSpy.mock.calls.find(
(c) => c[0] === "storage_mark_synced"
);
expect(markSyncedCall).toBeDefined();
expect(markSyncedCall![1]).toHaveProperty("itemId", "item-123");
});
it("should throw error if not authenticated", async () => {
const { auth } = await import("$lib/stores/auth");
const authModule = vi.mocked(auth);
authModule.getUserId = vi.fn(() => null);
await expect(toggleFavorite("item-123", false)).rejects.toThrow(
"Not authenticated"
);
});
it("should handle server sync failure gracefully", async () => {
const { auth } = await import("$lib/stores/auth");
const authModule = vi.mocked(auth);
const mockRepo = {
markFavorite: vi.fn(async () => {
throw new Error("Server error");
}),
unmarkFavorite: vi.fn(async () => undefined),
};
authModule.getRepository = vi.fn(() => mockRepo as any);
// Ensure getUserId returns a value for this test
authModule.getUserId = vi.fn(() => "user-123");
// Should not throw, but return the new favorite state
const result = await toggleFavorite("item-123", false);
expect(result).toBe(true);
});
it("should handle multiple toggles", async () => {
const { auth } = await import("$lib/stores/auth");
const authModule = vi.mocked(auth);
authModule.getUserId = vi.fn(() => "user-123");
let result = await toggleFavorite("item-123", false);
expect(result).toBe(true);
result = await toggleFavorite("item-123", true);
expect(result).toBe(false);
result = await toggleFavorite("item-123", false);
expect(result).toBe(true);
});
});
});