import { beforeEach, describe, expect, it } from "vitest"; import { InMemoryProjectStore } from "./in-memory-project-store.js"; describe("InMemoryProjectStore", () => { let store: InMemoryProjectStore; beforeEach(() => { store = new InMemoryProjectStore(); }); describe("create", () => { it("creates a project and returns it with generated id", async () => { const result = await store.create({ name: "Test Project" }); expect(result.success).toBe(true); if (result.success) { expect(result.value.id).toBeDefined(); expect(result.value.name).toBe("Test Project"); expect(result.value.description).toBeNull(); expect(result.value.isGlobal).toBe(false); expect(result.value.folders).toEqual([]); expect(result.value.createdAt).toBeInstanceOf(Date); expect(result.value.updatedAt).toBeInstanceOf(Date); } }); it("creates a project with optional fields", async () => { const result = await store.create({ name: "Test Project", description: "A test project", isGlobal: true, }); expect(result.success).toBe(true); if (result.success) { expect(result.value.description).toBe("A test project"); expect(result.value.isGlobal).toBe(true); } }); }); describe("get", () => { it("returns a project by id", async () => { const createResult = await store.create({ name: "Test Project" }); if (!createResult.success) { throw new Error("Failed to create project"); } const result = await store.get(createResult.value.id); expect(result.success).toBe(true); if (result.success) { expect(result.value).toEqual(createResult.value); } }); it("returns failure when project does not exist", async () => { const result = await store.get("non-existent-id"); expect(result.success).toBe(false); if (!result.success) { expect(result.error.type).toBe("PROJECT_NOT_FOUND"); expect(result.error.projectId).toBe("non-existent-id"); } }); }); describe("update", () => { it("updates a project and returns the updated version", async () => { const createResult = await store.create({ name: "Original Name" }); if (!createResult.success) { throw new Error("Failed to create project"); } const result = await store.update(createResult.value.id, { name: "Updated Name", }); expect(result.success).toBe(true); if (result.success) { expect(result.value.name).toBe("Updated Name"); expect(result.value.updatedAt.getTime()).toBeGreaterThanOrEqual( createResult.value.updatedAt.getTime(), ); } }); it("updates only specified fields", async () => { const createResult = await store.create({ name: "Test Project", description: "Original description", isGlobal: false, }); if (!createResult.success) { throw new Error("Failed to create project"); } const result = await store.update(createResult.value.id, { name: "Updated Name", }); expect(result.success).toBe(true); if (result.success) { expect(result.value.name).toBe("Updated Name"); expect(result.value.description).toBe("Original description"); expect(result.value.isGlobal).toBe(false); } }); it("allows setting description to null", async () => { const createResult = await store.create({ name: "Test Project", description: "Original description", }); if (!createResult.success) { throw new Error("Failed to create project"); } const result = await store.update(createResult.value.id, { description: null, }); expect(result.success).toBe(true); if (result.success) { expect(result.value.description).toBeNull(); } }); it("returns failure when project does not exist", async () => { const result = await store.update("non-existent-id", { name: "Updated Name", }); expect(result.success).toBe(false); if (!result.success) { expect(result.error.type).toBe("PROJECT_NOT_FOUND"); expect(result.error.projectId).toBe("non-existent-id"); } }); }); describe("delete", () => { it("deletes a project", async () => { const createResult = await store.create({ name: "Test Project" }); if (!createResult.success) { throw new Error("Failed to create project"); } const deleteResult = await store.delete(createResult.value.id); expect(deleteResult.success).toBe(true); const getResult = await store.get(createResult.value.id); expect(getResult.success).toBe(false); }); it("returns failure when project does not exist", async () => { const result = await store.delete("non-existent-id"); expect(result.success).toBe(false); if (!result.success) { expect(result.error.type).toBe("PROJECT_NOT_FOUND"); expect(result.error.projectId).toBe("non-existent-id"); } }); }); describe("list", () => { it("returns empty array when no projects exist", async () => { const result = await store.list(); expect(result.success).toBe(true); if (result.success) { expect(result.value).toEqual([]); } }); it("returns all projects", async () => { const createResult1 = await store.create({ name: "Project 1" }); const createResult2 = await store.create({ name: "Project 2" }); if (!createResult1.success || !createResult2.success) { throw new Error("Failed to create projects"); } const result = await store.list(); expect(result.success).toBe(true); if (result.success) { expect(result.value).toHaveLength(2); expect(result.value).toContainEqual(createResult1.value); expect(result.value).toContainEqual(createResult2.value); } }); }); describe("addFolder", () => { it("adds a folder to a project", async () => { const createResult = await store.create({ name: "Test Project" }); if (!createResult.success) { throw new Error("Failed to create project"); } const result = await store.addFolder(createResult.value.id, { name: "Test Folder", }); expect(result.success).toBe(true); if (result.success) { expect(result.value.id).toBeDefined(); expect(result.value.name).toBe("Test Folder"); expect(result.value.description).toBeNull(); expect(result.value.projectId).toBe(createResult.value.id); expect(result.value.createdAt).toBeInstanceOf(Date); expect(result.value.updatedAt).toBeInstanceOf(Date); } }); it("adds a folder with description", async () => { const createResult = await store.create({ name: "Test Project" }); if (!createResult.success) { throw new Error("Failed to create project"); } const result = await store.addFolder(createResult.value.id, { name: "Test Folder", description: "A test folder", }); expect(result.success).toBe(true); if (result.success) { expect(result.value.description).toBe("A test folder"); } }); it("returns failure when project does not exist", async () => { const result = await store.addFolder("non-existent-id", { name: "Test Folder", }); expect(result.success).toBe(false); if (!result.success) { expect(result.error.type).toBe("PROJECT_NOT_FOUND"); expect(result.error.projectId).toBe("non-existent-id"); } }); }); describe("updateFolder", () => { it("updates a folder and returns the updated version", async () => { const createResult = await store.create({ name: "Test Project" }); if (!createResult.success) { throw new Error("Failed to create project"); } const folderResult = await store.addFolder(createResult.value.id, { name: "Original Name", }); if (!folderResult.success) { throw new Error("Failed to create folder"); } const result = await store.updateFolder( createResult.value.id, folderResult.value.id, { name: "Updated Name" }, ); expect(result.success).toBe(true); if (result.success) { expect(result.value.name).toBe("Updated Name"); expect(result.value.updatedAt.getTime()).toBeGreaterThanOrEqual( folderResult.value.updatedAt.getTime(), ); } }); it("allows setting description to null", async () => { const createResult = await store.create({ name: "Test Project" }); if (!createResult.success) { throw new Error("Failed to create project"); } const folderResult = await store.addFolder(createResult.value.id, { name: "Test Folder", description: "Original description", }); if (!folderResult.success) { throw new Error("Failed to create folder"); } const result = await store.updateFolder( createResult.value.id, folderResult.value.id, { description: null }, ); expect(result.success).toBe(true); if (result.success) { expect(result.value.description).toBeNull(); } }); it("returns failure when project does not exist", async () => { const result = await store.updateFolder("non-existent-id", "folder-id", { name: "Updated Name", }); expect(result.success).toBe(false); if (!result.success) { expect(result.error.type).toBe("PROJECT_NOT_FOUND"); } }); it("returns failure when folder does not exist", async () => { const createResult = await store.create({ name: "Test Project" }); if (!createResult.success) { throw new Error("Failed to create project"); } const result = await store.updateFolder( createResult.value.id, "non-existent-folder-id", { name: "Updated Name" }, ); expect(result.success).toBe(false); if (!result.success) { expect(result.error.type).toBe("FOLDER_NOT_FOUND"); if (result.error.type === "FOLDER_NOT_FOUND") { expect(result.error.folderId).toBe("non-existent-folder-id"); } } }); }); describe("removeFolder", () => { it("removes a folder from a project", async () => { const createResult = await store.create({ name: "Test Project" }); if (!createResult.success) { throw new Error("Failed to create project"); } const folderResult = await store.addFolder(createResult.value.id, { name: "Test Folder", }); if (!folderResult.success) { throw new Error("Failed to create folder"); } const removeResult = await store.removeFolder( createResult.value.id, folderResult.value.id, ); expect(removeResult.success).toBe(true); const listResult = await store.listFolders(createResult.value.id); if (listResult.success) { expect(listResult.value).toHaveLength(0); } }); it("returns failure when project does not exist", async () => { const result = await store.removeFolder("non-existent-id", "folder-id"); expect(result.success).toBe(false); if (!result.success) { expect(result.error.type).toBe("PROJECT_NOT_FOUND"); } }); it("returns failure when folder does not exist", async () => { const createResult = await store.create({ name: "Test Project" }); if (!createResult.success) { throw new Error("Failed to create project"); } const result = await store.removeFolder( createResult.value.id, "non-existent-folder-id", ); expect(result.success).toBe(false); if (!result.success) { expect(result.error.type).toBe("FOLDER_NOT_FOUND"); if (result.error.type === "FOLDER_NOT_FOUND") { expect(result.error.folderId).toBe("non-existent-folder-id"); } } }); }); describe("listFolders", () => { it("returns empty array when project has no folders", async () => { const createResult = await store.create({ name: "Test Project" }); if (!createResult.success) { throw new Error("Failed to create project"); } const result = await store.listFolders(createResult.value.id); expect(result.success).toBe(true); if (result.success) { expect(result.value).toEqual([]); } }); it("returns all folders for a project", async () => { const createResult = await store.create({ name: "Test Project" }); if (!createResult.success) { throw new Error("Failed to create project"); } const folder1Result = await store.addFolder(createResult.value.id, { name: "Folder 1", }); const folder2Result = await store.addFolder(createResult.value.id, { name: "Folder 2", }); if (!folder1Result.success || !folder2Result.success) { throw new Error("Failed to create folders"); } const result = await store.listFolders(createResult.value.id); expect(result.success).toBe(true); if (result.success) { expect(result.value).toHaveLength(2); expect(result.value).toContainEqual(folder1Result.value); expect(result.value).toContainEqual(folder2Result.value); } }); it("returns failure when project does not exist", async () => { const result = await store.listFolders("non-existent-id"); expect(result.success).toBe(false); if (!result.success) { expect(result.error.type).toBe("PROJECT_NOT_FOUND"); expect(result.error.projectId).toBe("non-existent-id"); } }); }); });