aboutsummaryrefslogtreecommitdiffstats
path: root/packages/e2e_tests/tests/api/rss.test.ts
blob: 3c87f88a789c574dccd74dad2e6e9e0cabe61d4c (plain) (blame)
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);
  });
});