@prmichaelsen/reddit-mcp 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/.claude/settings.local.json +4 -1
  2. package/README.md +253 -27
  3. package/agent/progress.yaml +29 -30
  4. package/dist/factory.js +1206 -0
  5. package/dist/factory.js.map +4 -4
  6. package/dist/index.js +1206 -0
  7. package/dist/index.js.map +4 -4
  8. package/dist/server.d.ts.map +1 -1
  9. package/dist/server.js +1206 -0
  10. package/dist/server.js.map +4 -4
  11. package/dist/tools/account.d.ts +4 -0
  12. package/dist/tools/account.d.ts.map +1 -0
  13. package/dist/tools/comments.d.ts +4 -0
  14. package/dist/tools/comments.d.ts.map +1 -0
  15. package/dist/tools/flair.d.ts +4 -0
  16. package/dist/tools/flair.d.ts.map +1 -0
  17. package/dist/tools/messages.d.ts +4 -0
  18. package/dist/tools/messages.d.ts.map +1 -0
  19. package/dist/tools/moderation.d.ts +4 -0
  20. package/dist/tools/moderation.d.ts.map +1 -0
  21. package/dist/tools/multireddits.d.ts +4 -0
  22. package/dist/tools/multireddits.d.ts.map +1 -0
  23. package/dist/tools/posts.d.ts +4 -0
  24. package/dist/tools/posts.d.ts.map +1 -0
  25. package/dist/tools/subreddits.d.ts +4 -0
  26. package/dist/tools/subreddits.d.ts.map +1 -0
  27. package/dist/tools/users.d.ts +4 -0
  28. package/dist/tools/users.d.ts.map +1 -0
  29. package/dist/tools/voting.d.ts +4 -0
  30. package/dist/tools/voting.d.ts.map +1 -0
  31. package/dist/tools/wiki.d.ts +4 -0
  32. package/dist/tools/wiki.d.ts.map +1 -0
  33. package/package.json +1 -1
  34. package/src/server.ts +22 -0
  35. package/src/tools/account.ts +84 -0
  36. package/src/tools/comments.ts +73 -0
  37. package/src/tools/flair.ts +79 -0
  38. package/src/tools/messages.ts +126 -0
  39. package/src/tools/moderation.ts +292 -0
  40. package/src/tools/multireddits.ts +152 -0
  41. package/src/tools/posts.ts +177 -0
  42. package/src/tools/subreddits.ts +137 -0
  43. package/src/tools/users.ts +181 -0
  44. package/src/tools/voting.ts +90 -0
  45. package/src/tools/wiki.ts +118 -0
  46. package/tests/fixtures/reddit-responses.ts +159 -0
  47. package/tests/unit/account.test.ts +95 -0
  48. package/tests/unit/comments.test.ts +92 -0
  49. package/tests/unit/flair.test.ts +101 -0
  50. package/tests/unit/messages.test.ts +106 -0
  51. package/tests/unit/moderation.test.ts +243 -0
  52. package/tests/unit/multireddits.test.ts +136 -0
  53. package/tests/unit/posts.test.ts +155 -0
  54. package/tests/unit/subreddits.test.ts +125 -0
  55. package/tests/unit/transport.test.ts +13 -0
  56. package/tests/unit/users.test.ts +124 -0
  57. package/tests/unit/voting.test.ts +110 -0
  58. package/tests/unit/wiki.test.ts +116 -0
@@ -0,0 +1,95 @@
1
+ import { describe, it, expect, beforeEach } from "@jest/globals";
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { registerAccountTools } from "../../src/tools/account.js";
4
+ import { createMockClient } from "../helpers/mock-client.js";
5
+ import {
6
+ mockMeResponse,
7
+ mockKarmaResponse,
8
+ mockPrefsResponse,
9
+ mockTrophiesResponse,
10
+ mockFriendsResponse,
11
+ mockBlockedResponse,
12
+ } from "../fixtures/reddit-responses.js";
13
+
14
+ describe("Account Tools", () => {
15
+ let server: McpServer;
16
+ let mockClient: ReturnType<typeof createMockClient>;
17
+
18
+ beforeEach(() => {
19
+ server = new McpServer({ name: "test", version: "0.0.1" });
20
+ mockClient = createMockClient(
21
+ new Map([
22
+ ["/api/v1/me", mockMeResponse],
23
+ ["/api/v1/me/karma", mockKarmaResponse],
24
+ ["/api/v1/me/prefs", mockPrefsResponse],
25
+ ["/api/v1/me/trophies", mockTrophiesResponse],
26
+ ["/prefs/friends", mockFriendsResponse],
27
+ ["/prefs/blocked", mockBlockedResponse],
28
+ ]),
29
+ );
30
+ registerAccountTools(server, mockClient);
31
+ });
32
+
33
+ it("registers account tools", () => {
34
+ expect(server).toBeDefined();
35
+ });
36
+
37
+ describe("reddit_me", () => {
38
+ it("calls GET /api/v1/me", async () => {
39
+ const result = await mockClient.get("/api/v1/me");
40
+ expect(mockClient.mockGet).toHaveBeenCalledWith("/api/v1/me");
41
+ expect(result).toEqual(mockMeResponse);
42
+ });
43
+ });
44
+
45
+ describe("reddit_me_karma", () => {
46
+ it("calls GET /api/v1/me/karma", async () => {
47
+ const result = await mockClient.get("/api/v1/me/karma");
48
+ expect(mockClient.mockGet).toHaveBeenCalledWith("/api/v1/me/karma");
49
+ expect(result).toEqual(mockKarmaResponse);
50
+ });
51
+ });
52
+
53
+ describe("reddit_me_prefs", () => {
54
+ it("calls GET /api/v1/me/prefs", async () => {
55
+ const result = await mockClient.get("/api/v1/me/prefs");
56
+ expect(mockClient.mockGet).toHaveBeenCalledWith("/api/v1/me/prefs");
57
+ expect(result).toEqual(mockPrefsResponse);
58
+ });
59
+ });
60
+
61
+ describe("reddit_me_prefs_update", () => {
62
+ it("calls PATCH /api/v1/me/prefs with prefs object", async () => {
63
+ const prefs = { over_18: true, hide_downs: true };
64
+ await mockClient.patch("/api/v1/me/prefs", prefs);
65
+ expect(mockClient.patch).toHaveBeenCalledWith(
66
+ "/api/v1/me/prefs",
67
+ prefs,
68
+ );
69
+ });
70
+ });
71
+
72
+ describe("reddit_me_trophies", () => {
73
+ it("calls GET /api/v1/me/trophies", async () => {
74
+ const result = await mockClient.get("/api/v1/me/trophies");
75
+ expect(mockClient.mockGet).toHaveBeenCalledWith("/api/v1/me/trophies");
76
+ expect(result).toEqual(mockTrophiesResponse);
77
+ });
78
+ });
79
+
80
+ describe("reddit_me_friends", () => {
81
+ it("calls GET /prefs/friends", async () => {
82
+ const result = await mockClient.get("/prefs/friends");
83
+ expect(mockClient.mockGet).toHaveBeenCalledWith("/prefs/friends");
84
+ expect(result).toEqual(mockFriendsResponse);
85
+ });
86
+ });
87
+
88
+ describe("reddit_me_blocked", () => {
89
+ it("calls GET /prefs/blocked", async () => {
90
+ const result = await mockClient.get("/prefs/blocked");
91
+ expect(mockClient.mockGet).toHaveBeenCalledWith("/prefs/blocked");
92
+ expect(result).toEqual(mockBlockedResponse);
93
+ });
94
+ });
95
+ });
@@ -0,0 +1,92 @@
1
+ import { describe, it, expect, beforeEach } from "@jest/globals";
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { registerCommentTools } from "../../src/tools/comments.js";
4
+ import { createMockClient } from "../helpers/mock-client.js";
5
+ import {
6
+ mockCommentResponse,
7
+ mockMoreChildrenResponse,
8
+ } from "../fixtures/reddit-responses.js";
9
+
10
+ describe("Comment Tools", () => {
11
+ let server: McpServer;
12
+ let mockClient: ReturnType<typeof createMockClient>;
13
+
14
+ beforeEach(() => {
15
+ server = new McpServer({ name: "test", version: "0.0.1" });
16
+ mockClient = createMockClient(
17
+ new Map([
18
+ ["/api/comment", mockCommentResponse],
19
+ ["/api/morechildren", mockMoreChildrenResponse],
20
+ ]),
21
+ );
22
+ registerCommentTools(server, mockClient);
23
+ });
24
+
25
+ it("registers comment tools", () => {
26
+ expect(server).toBeDefined();
27
+ });
28
+
29
+ describe("reddit_comment", () => {
30
+ it("calls POST /api/comment for top-level comment", async () => {
31
+ await mockClient.post("/api/comment", {
32
+ parent: "t3_abc123",
33
+ text: "Great post!",
34
+ api_type: "json",
35
+ });
36
+ expect(mockClient.mockPost).toHaveBeenCalledWith(
37
+ "/api/comment",
38
+ expect.objectContaining({
39
+ parent: "t3_abc123",
40
+ text: "Great post!",
41
+ }),
42
+ );
43
+ });
44
+
45
+ it("calls POST /api/comment for reply", async () => {
46
+ await mockClient.post("/api/comment", {
47
+ parent: "t1_xyz789",
48
+ text: "I agree!",
49
+ api_type: "json",
50
+ });
51
+ expect(mockClient.mockPost).toHaveBeenCalledWith(
52
+ "/api/comment",
53
+ expect.objectContaining({
54
+ parent: "t1_xyz789",
55
+ text: "I agree!",
56
+ }),
57
+ );
58
+ });
59
+ });
60
+
61
+ describe("reddit_more_children", () => {
62
+ it("calls GET /api/morechildren", async () => {
63
+ await mockClient.get("/api/morechildren", {
64
+ link_id: "t3_abc123",
65
+ children: "comment1,comment2,comment3",
66
+ api_type: "json",
67
+ });
68
+ expect(mockClient.mockGet).toHaveBeenCalledWith(
69
+ "/api/morechildren",
70
+ expect.objectContaining({
71
+ link_id: "t3_abc123",
72
+ children: "comment1,comment2,comment3",
73
+ }),
74
+ );
75
+ });
76
+
77
+ it("supports sort parameter", async () => {
78
+ await mockClient.get("/api/morechildren", {
79
+ link_id: "t3_abc123",
80
+ children: "c1",
81
+ sort: "top",
82
+ api_type: "json",
83
+ });
84
+ expect(mockClient.mockGet).toHaveBeenCalledWith(
85
+ "/api/morechildren",
86
+ expect.objectContaining({
87
+ sort: "top",
88
+ }),
89
+ );
90
+ });
91
+ });
92
+ });
@@ -0,0 +1,101 @@
1
+ import { describe, it, expect, beforeEach } from "@jest/globals";
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { registerFlairTools } from "../../src/tools/flair.js";
4
+ import { createMockClient } from "../helpers/mock-client.js";
5
+ import { mockEmptyResponse } from "../fixtures/reddit-responses.js";
6
+
7
+ const mockFlairTemplates = [
8
+ {
9
+ type: "richtext",
10
+ text_editable: false,
11
+ allowable_content: "all",
12
+ text: "Discussion",
13
+ id: "flair_abc123",
14
+ css_class: "discussion",
15
+ text_color: "dark",
16
+ background_color: "#edeff1",
17
+ },
18
+ {
19
+ type: "richtext",
20
+ text_editable: true,
21
+ allowable_content: "all",
22
+ text: "Question",
23
+ id: "flair_xyz789",
24
+ css_class: "question",
25
+ text_color: "light",
26
+ background_color: "#0079d3",
27
+ },
28
+ ];
29
+
30
+ describe("Flair Tools", () => {
31
+ let server: McpServer;
32
+ let mockClient: ReturnType<typeof createMockClient>;
33
+
34
+ beforeEach(() => {
35
+ server = new McpServer({ name: "test", version: "0.0.1" });
36
+ mockClient = createMockClient(
37
+ new Map([
38
+ ["/r/test/api/link_flair_v2", mockFlairTemplates],
39
+ ["/r/test/api/user_flair_v2", mockFlairTemplates],
40
+ ["/r/test/api/selectflair", mockEmptyResponse],
41
+ ]),
42
+ );
43
+ registerFlairTools(server, mockClient);
44
+ });
45
+
46
+ it("registers flair tools", () => {
47
+ expect(server).toBeDefined();
48
+ });
49
+
50
+ describe("reddit_link_flair", () => {
51
+ it("calls GET /r/{subreddit}/api/link_flair_v2", async () => {
52
+ const result = await mockClient.get("/r/test/api/link_flair_v2");
53
+ expect(mockClient.mockGet).toHaveBeenCalledWith(
54
+ "/r/test/api/link_flair_v2",
55
+ );
56
+ expect(result).toEqual(mockFlairTemplates);
57
+ });
58
+ });
59
+
60
+ describe("reddit_user_flair", () => {
61
+ it("calls GET /r/{subreddit}/api/user_flair_v2", async () => {
62
+ const result = await mockClient.get("/r/test/api/user_flair_v2");
63
+ expect(mockClient.mockGet).toHaveBeenCalledWith(
64
+ "/r/test/api/user_flair_v2",
65
+ );
66
+ expect(result).toEqual(mockFlairTemplates);
67
+ });
68
+ });
69
+
70
+ describe("reddit_select_flair", () => {
71
+ it("calls POST /r/{subreddit}/api/selectflair for link flair", async () => {
72
+ await mockClient.post("/r/test/api/selectflair", {
73
+ flair_template_id: "flair_abc123",
74
+ link: "t3_abc123",
75
+ });
76
+ expect(mockClient.mockPost).toHaveBeenCalledWith(
77
+ "/r/test/api/selectflair",
78
+ expect.objectContaining({
79
+ flair_template_id: "flair_abc123",
80
+ link: "t3_abc123",
81
+ }),
82
+ );
83
+ });
84
+
85
+ it("calls POST /r/{subreddit}/api/selectflair for user flair", async () => {
86
+ await mockClient.post("/r/test/api/selectflair", {
87
+ flair_template_id: "flair_xyz789",
88
+ name: "testuser",
89
+ text: "Custom Text",
90
+ });
91
+ expect(mockClient.mockPost).toHaveBeenCalledWith(
92
+ "/r/test/api/selectflair",
93
+ expect.objectContaining({
94
+ flair_template_id: "flair_xyz789",
95
+ name: "testuser",
96
+ text: "Custom Text",
97
+ }),
98
+ );
99
+ });
100
+ });
101
+ });
@@ -0,0 +1,106 @@
1
+ import { describe, it, expect, beforeEach } from "@jest/globals";
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { registerMessageTools } from "../../src/tools/messages.js";
4
+ import { createMockClient } from "../helpers/mock-client.js";
5
+ import {
6
+ mockMessageListing,
7
+ mockComposeResponse,
8
+ mockEmptyResponse,
9
+ } from "../fixtures/reddit-responses.js";
10
+
11
+ describe("Private Message Tools", () => {
12
+ let server: McpServer;
13
+ let mockClient: ReturnType<typeof createMockClient>;
14
+
15
+ beforeEach(() => {
16
+ server = new McpServer({ name: "test", version: "0.0.1" });
17
+ mockClient = createMockClient(
18
+ new Map([
19
+ ["/message/inbox", mockMessageListing],
20
+ ["/message/unread", mockMessageListing],
21
+ ["/message/sent", mockMessageListing],
22
+ ["/api/compose", mockComposeResponse],
23
+ ["/api/read_message", mockEmptyResponse],
24
+ ["/api/unread_message", mockEmptyResponse],
25
+ ["/api/del_msg", mockEmptyResponse],
26
+ ]),
27
+ );
28
+ registerMessageTools(server, mockClient);
29
+ });
30
+
31
+ it("registers message tools", () => {
32
+ expect(server).toBeDefined();
33
+ });
34
+
35
+ describe("reddit_inbox", () => {
36
+ it("calls GET /message/inbox", async () => {
37
+ const result = await mockClient.get("/message/inbox", { limit: "10" });
38
+ expect(mockClient.mockGet).toHaveBeenCalledWith("/message/inbox", {
39
+ limit: "10",
40
+ });
41
+ expect(result).toEqual(mockMessageListing);
42
+ });
43
+ });
44
+
45
+ describe("reddit_unread", () => {
46
+ it("calls GET /message/unread", async () => {
47
+ const result = await mockClient.get("/message/unread");
48
+ expect(mockClient.mockGet).toHaveBeenCalledWith("/message/unread");
49
+ expect(result).toEqual(mockMessageListing);
50
+ });
51
+ });
52
+
53
+ describe("reddit_sent", () => {
54
+ it("calls GET /message/sent", async () => {
55
+ await mockClient.get("/message/sent");
56
+ expect(mockClient.mockGet).toHaveBeenCalledWith("/message/sent");
57
+ });
58
+ });
59
+
60
+ describe("reddit_compose", () => {
61
+ it("calls POST /api/compose", async () => {
62
+ await mockClient.post("/api/compose", {
63
+ to: "otheruser",
64
+ subject: "Hello",
65
+ text: "Hi there!",
66
+ api_type: "json",
67
+ });
68
+ expect(mockClient.mockPost).toHaveBeenCalledWith(
69
+ "/api/compose",
70
+ expect.objectContaining({
71
+ to: "otheruser",
72
+ subject: "Hello",
73
+ text: "Hi there!",
74
+ }),
75
+ );
76
+ });
77
+ });
78
+
79
+ describe("reddit_read_message", () => {
80
+ it("calls POST /api/read_message", async () => {
81
+ await mockClient.post("/api/read_message", { id: "t4_msg1" });
82
+ expect(mockClient.mockPost).toHaveBeenCalledWith("/api/read_message", {
83
+ id: "t4_msg1",
84
+ });
85
+ });
86
+ });
87
+
88
+ describe("reddit_unread_message", () => {
89
+ it("calls POST /api/unread_message", async () => {
90
+ await mockClient.post("/api/unread_message", { id: "t4_msg1" });
91
+ expect(mockClient.mockPost).toHaveBeenCalledWith(
92
+ "/api/unread_message",
93
+ { id: "t4_msg1" },
94
+ );
95
+ });
96
+ });
97
+
98
+ describe("reddit_del_msg", () => {
99
+ it("calls POST /api/del_msg", async () => {
100
+ await mockClient.post("/api/del_msg", { id: "t4_msg1" });
101
+ expect(mockClient.mockPost).toHaveBeenCalledWith("/api/del_msg", {
102
+ id: "t4_msg1",
103
+ });
104
+ });
105
+ });
106
+ });
@@ -0,0 +1,243 @@
1
+ import { describe, it, expect, beforeEach } from "@jest/globals";
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { registerModerationTools } from "../../src/tools/moderation.js";
4
+ import { createMockClient } from "../helpers/mock-client.js";
5
+ import { mockListing, mockEmptyResponse } from "../fixtures/reddit-responses.js";
6
+
7
+ const mockUserList = {
8
+ kind: "UserList",
9
+ data: {
10
+ children: [
11
+ { name: "mod1", date: 1700000000, id: "t2_mod1" },
12
+ ],
13
+ },
14
+ };
15
+
16
+ const mockModlogResponse = {
17
+ kind: "Listing",
18
+ data: {
19
+ after: null,
20
+ children: [
21
+ {
22
+ kind: "modaction",
23
+ data: {
24
+ id: "ModAction_abc",
25
+ mod: "mod1",
26
+ action: "removelink",
27
+ target_fullname: "t3_abc123",
28
+ created_utc: 1710000000,
29
+ },
30
+ },
31
+ ],
32
+ },
33
+ };
34
+
35
+ describe("Moderation Tools", () => {
36
+ let server: McpServer;
37
+ let mockClient: ReturnType<typeof createMockClient>;
38
+
39
+ beforeEach(() => {
40
+ server = new McpServer({ name: "test", version: "0.0.1" });
41
+ mockClient = createMockClient(
42
+ new Map([
43
+ ["/api/approve", mockEmptyResponse],
44
+ ["/api/remove", mockEmptyResponse],
45
+ ["/api/distinguish", mockEmptyResponse],
46
+ ["/api/ignore_reports", mockEmptyResponse],
47
+ ["/api/unignore_reports", mockEmptyResponse],
48
+ ["/api/lock", mockEmptyResponse],
49
+ ["/api/unlock", mockEmptyResponse],
50
+ ["/r/test/about/modqueue", mockListing],
51
+ ["/r/test/about/reports", mockListing],
52
+ ["/r/test/about/spam", mockListing],
53
+ ["/r/test/about/edited", mockListing],
54
+ ["/r/test/about/log", mockModlogResponse],
55
+ ["/r/test/about/moderators", mockUserList],
56
+ ["/r/test/about/contributors", mockUserList],
57
+ ["/r/test/about/banned", mockUserList],
58
+ ["/r/test/about/muted", mockUserList],
59
+ ]),
60
+ );
61
+ registerModerationTools(server, mockClient);
62
+ });
63
+
64
+ it("registers moderation tools", () => {
65
+ expect(server).toBeDefined();
66
+ });
67
+
68
+ // === Mod Action Tools ===
69
+
70
+ describe("reddit_approve", () => {
71
+ it("calls POST /api/approve", async () => {
72
+ await mockClient.post("/api/approve", { id: "t3_abc123" });
73
+ expect(mockClient.mockPost).toHaveBeenCalledWith("/api/approve", {
74
+ id: "t3_abc123",
75
+ });
76
+ });
77
+ });
78
+
79
+ describe("reddit_remove", () => {
80
+ it("calls POST /api/remove", async () => {
81
+ await mockClient.post("/api/remove", { id: "t3_abc123" });
82
+ expect(mockClient.mockPost).toHaveBeenCalledWith("/api/remove", {
83
+ id: "t3_abc123",
84
+ });
85
+ });
86
+
87
+ it("supports spam flag", async () => {
88
+ await mockClient.post("/api/remove", { id: "t3_abc123", spam: "true" });
89
+ expect(mockClient.mockPost).toHaveBeenCalledWith("/api/remove", {
90
+ id: "t3_abc123",
91
+ spam: "true",
92
+ });
93
+ });
94
+ });
95
+
96
+ describe("reddit_distinguish", () => {
97
+ it("calls POST /api/distinguish", async () => {
98
+ await mockClient.post("/api/distinguish", {
99
+ id: "t1_xyz789",
100
+ how: "yes",
101
+ });
102
+ expect(mockClient.mockPost).toHaveBeenCalledWith("/api/distinguish", {
103
+ id: "t1_xyz789",
104
+ how: "yes",
105
+ });
106
+ });
107
+ });
108
+
109
+ describe("reddit_ignore_reports", () => {
110
+ it("calls POST /api/ignore_reports", async () => {
111
+ await mockClient.post("/api/ignore_reports", { id: "t3_abc123" });
112
+ expect(mockClient.mockPost).toHaveBeenCalledWith("/api/ignore_reports", {
113
+ id: "t3_abc123",
114
+ });
115
+ });
116
+ });
117
+
118
+ describe("reddit_unignore_reports", () => {
119
+ it("calls POST /api/unignore_reports", async () => {
120
+ await mockClient.post("/api/unignore_reports", { id: "t3_abc123" });
121
+ expect(mockClient.mockPost).toHaveBeenCalledWith(
122
+ "/api/unignore_reports",
123
+ { id: "t3_abc123" },
124
+ );
125
+ });
126
+ });
127
+
128
+ describe("reddit_lock", () => {
129
+ it("calls POST /api/lock", async () => {
130
+ await mockClient.post("/api/lock", { id: "t3_abc123" });
131
+ expect(mockClient.mockPost).toHaveBeenCalledWith("/api/lock", {
132
+ id: "t3_abc123",
133
+ });
134
+ });
135
+ });
136
+
137
+ describe("reddit_unlock", () => {
138
+ it("calls POST /api/unlock", async () => {
139
+ await mockClient.post("/api/unlock", { id: "t3_abc123" });
140
+ expect(mockClient.mockPost).toHaveBeenCalledWith("/api/unlock", {
141
+ id: "t3_abc123",
142
+ });
143
+ });
144
+ });
145
+
146
+ // === Mod Listing Tools ===
147
+
148
+ describe("reddit_modqueue", () => {
149
+ it("calls GET /r/{subreddit}/about/modqueue", async () => {
150
+ await mockClient.get("/r/test/about/modqueue", { limit: "10" });
151
+ expect(mockClient.mockGet).toHaveBeenCalledWith(
152
+ "/r/test/about/modqueue",
153
+ { limit: "10" },
154
+ );
155
+ });
156
+ });
157
+
158
+ describe("reddit_reports", () => {
159
+ it("calls GET /r/{subreddit}/about/reports", async () => {
160
+ await mockClient.get("/r/test/about/reports", {});
161
+ expect(mockClient.mockGet).toHaveBeenCalledWith(
162
+ "/r/test/about/reports",
163
+ {},
164
+ );
165
+ });
166
+ });
167
+
168
+ describe("reddit_spam", () => {
169
+ it("calls GET /r/{subreddit}/about/spam", async () => {
170
+ await mockClient.get("/r/test/about/spam", {});
171
+ expect(mockClient.mockGet).toHaveBeenCalledWith(
172
+ "/r/test/about/spam",
173
+ {},
174
+ );
175
+ });
176
+ });
177
+
178
+ describe("reddit_edited", () => {
179
+ it("calls GET /r/{subreddit}/about/edited", async () => {
180
+ await mockClient.get("/r/test/about/edited", {});
181
+ expect(mockClient.mockGet).toHaveBeenCalledWith(
182
+ "/r/test/about/edited",
183
+ {},
184
+ );
185
+ });
186
+ });
187
+
188
+ describe("reddit_modlog", () => {
189
+ it("calls GET /r/{subreddit}/about/log", async () => {
190
+ const result = await mockClient.get("/r/test/about/log", {
191
+ type: "removelink",
192
+ mod: "mod1",
193
+ });
194
+ expect(mockClient.mockGet).toHaveBeenCalledWith("/r/test/about/log", {
195
+ type: "removelink",
196
+ mod: "mod1",
197
+ });
198
+ expect(result).toEqual(mockModlogResponse);
199
+ });
200
+ });
201
+
202
+ // === Mod Management Tools ===
203
+
204
+ describe("reddit_moderators", () => {
205
+ it("calls GET /r/{subreddit}/about/moderators", async () => {
206
+ const result = await mockClient.get("/r/test/about/moderators");
207
+ expect(mockClient.mockGet).toHaveBeenCalledWith(
208
+ "/r/test/about/moderators",
209
+ );
210
+ expect(result).toEqual(mockUserList);
211
+ });
212
+ });
213
+
214
+ describe("reddit_contributors", () => {
215
+ it("calls GET /r/{subreddit}/about/contributors", async () => {
216
+ await mockClient.get("/r/test/about/contributors", { limit: "25" });
217
+ expect(mockClient.mockGet).toHaveBeenCalledWith(
218
+ "/r/test/about/contributors",
219
+ { limit: "25" },
220
+ );
221
+ });
222
+ });
223
+
224
+ describe("reddit_banned", () => {
225
+ it("calls GET /r/{subreddit}/about/banned", async () => {
226
+ await mockClient.get("/r/test/about/banned", {});
227
+ expect(mockClient.mockGet).toHaveBeenCalledWith(
228
+ "/r/test/about/banned",
229
+ {},
230
+ );
231
+ });
232
+ });
233
+
234
+ describe("reddit_muted", () => {
235
+ it("calls GET /r/{subreddit}/about/muted", async () => {
236
+ await mockClient.get("/r/test/about/muted", {});
237
+ expect(mockClient.mockGet).toHaveBeenCalledWith(
238
+ "/r/test/about/muted",
239
+ {},
240
+ );
241
+ });
242
+ });
243
+ });