diff options
Diffstat (limited to 'packages/trpc/routers/bookmarks.test.ts')
| -rw-r--r-- | packages/trpc/routers/bookmarks.test.ts | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/packages/trpc/routers/bookmarks.test.ts b/packages/trpc/routers/bookmarks.test.ts index c272e015..aaee5447 100644 --- a/packages/trpc/routers/bookmarks.test.ts +++ b/packages/trpc/routers/bookmarks.test.ts @@ -331,6 +331,198 @@ describe("Bookmark Routes", () => { ).rejects.toThrow(/You must provide either a tagId or a tagName/); }); + test<CustomTestContext>("update tags - comprehensive edge cases", async ({ + apiCallers, + }) => { + const api = apiCallers[0].bookmarks; + + // Create two bookmarks + const bookmark1 = await api.createBookmark({ + url: "https://bookmark1.com", + type: BookmarkTypes.LINK, + }); + const bookmark2 = await api.createBookmark({ + url: "https://bookmark2.com", + type: BookmarkTypes.LINK, + }); + + // Test 1: Attach tags by name to bookmark1 (creates new tags) + await api.updateTags({ + bookmarkId: bookmark1.id, + attach: [{ tagName: "existing-tag" }, { tagName: "shared-tag" }], + detach: [], + }); + + let b1 = await api.getBookmark({ bookmarkId: bookmark1.id }); + expect(b1.tags.map((t) => t.name).sort()).toEqual([ + "existing-tag", + "shared-tag", + ]); + + const existingTagId = b1.tags.find((t) => t.name === "existing-tag")!.id; + const sharedTagId = b1.tags.find((t) => t.name === "shared-tag")!.id; + + // Test 2: Attach existing tag by ID to bookmark2 (tag already exists in DB from bookmark1) + await api.updateTags({ + bookmarkId: bookmark2.id, + attach: [{ tagId: existingTagId }], + detach: [], + }); + + let b2 = await api.getBookmark({ bookmarkId: bookmark2.id }); + expect(b2.tags.map((t) => t.name)).toEqual(["existing-tag"]); + + // Test 3: Attach existing tag by NAME to bookmark2 (tag already exists in DB) + await api.updateTags({ + bookmarkId: bookmark2.id, + attach: [{ tagName: "shared-tag" }], + detach: [], + }); + + b2 = await api.getBookmark({ bookmarkId: bookmark2.id }); + expect(b2.tags.map((t) => t.name).sort()).toEqual([ + "existing-tag", + "shared-tag", + ]); + + // Test 4: Re-attaching the same tag (idempotency) - should be no-op + await api.updateTags({ + bookmarkId: bookmark2.id, + attach: [{ tagId: existingTagId }], + detach: [], + }); + + b2 = await api.getBookmark({ bookmarkId: bookmark2.id }); + expect(b2.tags.map((t) => t.name).sort()).toEqual([ + "existing-tag", + "shared-tag", + ]); + + // Test 5: Detach non-existent tag by name (should be no-op) + await api.updateTags({ + bookmarkId: bookmark2.id, + attach: [], + detach: [{ tagName: "non-existent-tag" }], + }); + + b2 = await api.getBookmark({ bookmarkId: bookmark2.id }); + expect(b2.tags.map((t) => t.name).sort()).toEqual([ + "existing-tag", + "shared-tag", + ]); + + // Test 6: Mixed attach/detach with pre-existing tags + await api.updateTags({ + bookmarkId: bookmark2.id, + attach: [{ tagName: "new-tag" }, { tagId: sharedTagId }], // sharedTagId already attached + detach: [{ tagName: "existing-tag" }], + }); + + b2 = await api.getBookmark({ bookmarkId: bookmark2.id }); + expect(b2.tags.map((t) => t.name).sort()).toEqual([ + "new-tag", + "shared-tag", + ]); + + // Test 7: Detach by ID and re-attach by name in same operation + await api.updateTags({ + bookmarkId: bookmark2.id, + attach: [{ tagName: "new-tag" }], // Already exists, should be idempotent + detach: [{ tagId: sharedTagId }], + }); + + b2 = await api.getBookmark({ bookmarkId: bookmark2.id }); + expect(b2.tags.map((t) => t.name).sort()).toEqual(["new-tag"]); + + // Verify bookmark1 still has its original tags (operations on bookmark2 didn't affect it) + b1 = await api.getBookmark({ bookmarkId: bookmark1.id }); + expect(b1.tags.map((t) => t.name).sort()).toEqual([ + "existing-tag", + "shared-tag", + ]); + + // Test 8: Attach same tag multiple times in one operation (deduplication) + await api.updateTags({ + bookmarkId: bookmark1.id, + attach: [{ tagName: "duplicate-test" }, { tagName: "duplicate-test" }], + detach: [], + }); + + b1 = await api.getBookmark({ bookmarkId: bookmark1.id }); + const duplicateTagCount = b1.tags.filter( + (t) => t.name === "duplicate-test", + ).length; + expect(duplicateTagCount).toEqual(1); // Should only be attached once + }); + + test<CustomTestContext>("updateTags with attachedBy field", async ({ + apiCallers, + }) => { + const api = apiCallers[0].bookmarks; + const bookmark = await api.createBookmark({ + url: "https://bookmark.com", + type: BookmarkTypes.LINK, + }); + + // Test 1: Attach tags with different attachedBy values + await api.updateTags({ + bookmarkId: bookmark.id, + attach: [ + { tagName: "ai-tag", attachedBy: "ai" }, + { tagName: "human-tag", attachedBy: "human" }, + { tagName: "default-tag" }, // Should default to "human" + ], + detach: [], + }); + + let b = await api.getBookmark({ bookmarkId: bookmark.id }); + expect(b.tags.length).toEqual(3); + + const aiTag = b.tags.find((t) => t.name === "ai-tag"); + const humanTag = b.tags.find((t) => t.name === "human-tag"); + const defaultTag = b.tags.find((t) => t.name === "default-tag"); + + expect(aiTag?.attachedBy).toEqual("ai"); + expect(humanTag?.attachedBy).toEqual("human"); + expect(defaultTag?.attachedBy).toEqual("human"); + + // Test 2: Attach existing tag by ID with different attachedBy + // First detach the ai-tag + await api.updateTags({ + bookmarkId: bookmark.id, + attach: [], + detach: [{ tagId: aiTag!.id }], + }); + + // Re-attach the same tag but as human + await api.updateTags({ + bookmarkId: bookmark.id, + attach: [{ tagId: aiTag!.id, attachedBy: "human" }], + detach: [], + }); + + b = await api.getBookmark({ bookmarkId: bookmark.id }); + const reAttachedTag = b.tags.find((t) => t.id === aiTag!.id); + expect(reAttachedTag?.attachedBy).toEqual("human"); + + // Test 3: Attach existing tag by name with AI attachedBy + const bookmark2 = await api.createBookmark({ + url: "https://bookmark2.com", + type: BookmarkTypes.LINK, + }); + + await api.updateTags({ + bookmarkId: bookmark2.id, + attach: [{ tagName: "ai-tag", attachedBy: "ai" }], + detach: [], + }); + + const b2 = await api.getBookmark({ bookmarkId: bookmark2.id }); + const aiTagOnB2 = b2.tags.find((t) => t.name === "ai-tag"); + expect(aiTagOnB2?.attachedBy).toEqual("ai"); + expect(aiTagOnB2?.id).toEqual(aiTag!.id); // Should be the same tag + }); + test<CustomTestContext>("update bookmark text", async ({ apiCallers }) => { const api = apiCallers[0].bookmarks; const createdBookmark = await api.createBookmark({ |
