1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
import { beforeEach, describe, expect, inject, it } from "vitest";
import { BookmarkTypes } from "@karakeep/shared/types/bookmarks";
import { createTestUser } from "../../utils/api";
import { getTrpcClient } from "../../utils/trpc";
describe("RSS Feed API", () => {
const port = inject("karakeepPort");
if (!port) {
throw new Error("Missing required environment variables");
}
async function fetchRssFeed(listId: string, token: string) {
return await fetch(
`http://localhost:${port}/api/v1/rss/lists/${listId}?token=${token}`,
);
}
async function seedDatabase() {
const trpcClient = getTrpcClient(apiKey);
// Create two lists
const manualList = await trpcClient.lists.create.mutate({
name: "Test List #1",
icon: "🚀",
type: "manual",
});
const smartList = await trpcClient.lists.create.mutate({
name: "Test List #2",
icon: "🚀",
type: "smart",
query: "is:fav",
});
// Create two bookmarks
const createBookmark1 = await trpcClient.bookmarks.createBookmark.mutate({
title: "Test Bookmark #1",
url: "https://example.com",
type: BookmarkTypes.LINK,
});
const createBookmark2 = await trpcClient.bookmarks.createBookmark.mutate({
title: "Test Bookmark #2",
url: "https://example.com/2",
type: BookmarkTypes.LINK,
favourited: true,
});
await trpcClient.lists.addToList.mutate({
listId: manualList.id,
bookmarkId: createBookmark1.id,
});
return { manualList, smartList, createBookmark1, createBookmark2 };
}
let apiKey: string;
beforeEach(async () => {
apiKey = await createTestUser();
});
it("should generate rss feed for manual lists", async () => {
const { manualList } = await seedDatabase();
const trpcClient = getTrpcClient(apiKey);
// Enable rss feed
const token = await trpcClient.lists.regenRssToken.mutate({
listId: manualList.id,
});
const res = await fetchRssFeed(manualList.id, token.token);
expect(res.status).toBe(200);
expect(res.headers.get("Content-Type")).toBe("application/rss+xml");
const text = await res.text();
expect(text).toContain("Test Bookmark #1");
expect(text).not.toContain("Test Bookmark #2");
});
it("should generate rss feed for smart lists", async () => {
const { smartList } = await seedDatabase();
const trpcClient = getTrpcClient(apiKey);
// Enable rss feed
const token = await trpcClient.lists.regenRssToken.mutate({
listId: smartList.id,
});
const res = await fetchRssFeed(smartList.id, token.token);
expect(res.status).toBe(200);
expect(res.headers.get("Content-Type")).toBe("application/rss+xml");
const text = await res.text();
expect(text).not.toContain("Test Bookmark #1");
expect(text).toContain("Test Bookmark #2");
});
it("should fail when the token is invalid", async () => {
const { smartList } = await seedDatabase();
const trpcClient = getTrpcClient(apiKey);
// Enable rss feed
const token = await trpcClient.lists.regenRssToken.mutate({
listId: smartList.id,
});
let res = await fetchRssFeed(smartList.id, token.token);
expect(res.status).toBe(200);
// Invalidate the token
await trpcClient.lists.regenRssToken.mutate({
listId: smartList.id,
});
res = await fetchRssFeed(smartList.id, token.token);
expect(res.status).toBe(404);
});
it("should fail when rss gets disabled", async () => {
const { smartList } = await seedDatabase();
const trpcClient = getTrpcClient(apiKey);
// Enable rss feed
const token = await trpcClient.lists.regenRssToken.mutate({
listId: smartList.id,
});
const res = await fetchRssFeed(smartList.id, token.token);
expect(res.status).toBe(200);
// Disable rss feed
await trpcClient.lists.clearRssToken.mutate({
listId: smartList.id,
});
const res2 = await fetchRssFeed(smartList.id, token.token);
expect(res2.status).toBe(404);
});
it("should fail when no token is provided", async () => {
const { smartList } = await seedDatabase();
const trpcClient = getTrpcClient(apiKey);
// Enable rss feed
await trpcClient.lists.regenRssToken.mutate({
listId: smartList.id,
});
const res2 = await fetchRssFeed(smartList.id, "");
expect(res2.status).toBe(400);
});
});
|