@access-mcp/announcements 0.1.0

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.
@@ -0,0 +1,367 @@
1
+ import { describe, it, expect, beforeEach, vi } from "vitest";
2
+ import { AnnouncementsServer } from "./server.js";
3
+
4
+ describe("AnnouncementsServer", () => {
5
+ let server: AnnouncementsServer;
6
+ let mockHttpClient: any;
7
+
8
+ beforeEach(() => {
9
+ server = new AnnouncementsServer();
10
+
11
+ // Mock the httpClient
12
+ mockHttpClient = {
13
+ get: vi.fn(),
14
+ };
15
+
16
+ // Override the httpClient getter
17
+ Object.defineProperty(server, "httpClient", {
18
+ get: () => mockHttpClient,
19
+ configurable: true,
20
+ });
21
+ });
22
+
23
+ describe("Tool Methods", () => {
24
+ describe("get_announcements", () => {
25
+ it("should fetch announcements with filters", async () => {
26
+ const mockResponse = {
27
+ status: 200,
28
+ data: [
29
+ {
30
+ title: "Scheduled Maintenance",
31
+ body: "System will be down for maintenance",
32
+ field_published_date: "2024-03-15",
33
+ author: "ACCESS Support",
34
+ custom_announcement_tags: "maintenance, scheduled",
35
+ custom_announcement_ag: "123,456",
36
+ },
37
+ {
38
+ title: "New GPU Nodes Available",
39
+ body: "Additional GPU resources added",
40
+ field_published_date: "2024-03-10",
41
+ author: "Resource Team",
42
+ custom_announcement_tags: "gpu, hardware",
43
+ custom_announcement_ag: "789",
44
+ },
45
+ ],
46
+ };
47
+
48
+ mockHttpClient.get.mockResolvedValue(mockResponse);
49
+
50
+ const result = await server["handleToolCall"]({
51
+ params: {
52
+ name: "get_announcements",
53
+ arguments: {
54
+ tags: "maintenance",
55
+ limit: 10,
56
+ },
57
+ },
58
+ } as any);
59
+
60
+ expect(mockHttpClient.get).toHaveBeenCalled();
61
+ const url = mockHttpClient.get.mock.calls[0][0];
62
+ expect(url).toContain("/api/2.1/announcements");
63
+ expect(url).toContain("tags=maintenance");
64
+
65
+ const responseData = JSON.parse(result.content[0].text);
66
+ expect(responseData.total_announcements).toBe(2);
67
+ expect(responseData.announcements).toHaveLength(2);
68
+ expect(responseData.announcements[0].tags).toEqual(["maintenance", "scheduled"]);
69
+ });
70
+
71
+ it("should handle empty results", async () => {
72
+ mockHttpClient.get.mockResolvedValue({
73
+ status: 200,
74
+ data: [],
75
+ });
76
+
77
+ const result = await server["handleToolCall"]({
78
+ params: {
79
+ name: "get_announcements",
80
+ arguments: {
81
+ tags: "nonexistent",
82
+ },
83
+ },
84
+ } as any);
85
+
86
+ const responseData = JSON.parse(result.content[0].text);
87
+ expect(responseData.total_announcements).toBe(0);
88
+ expect(responseData.announcements).toEqual([]);
89
+ });
90
+
91
+ it("should handle API errors", async () => {
92
+ mockHttpClient.get.mockResolvedValue({
93
+ status: 500,
94
+ statusText: "Internal Server Error",
95
+ });
96
+
97
+ const result = await server["handleToolCall"]({
98
+ params: {
99
+ name: "get_announcements",
100
+ arguments: {},
101
+ },
102
+ } as any);
103
+
104
+ // Server handles errors and returns them in content, not as isError
105
+ expect(result.content[0].text).toContain("500");
106
+ });
107
+ });
108
+
109
+ describe("get_announcements_by_tags", () => {
110
+ it("should fetch announcements by specific tags", async () => {
111
+ const mockResponse = {
112
+ status: 200,
113
+ data: [
114
+ {
115
+ title: "GPU Maintenance",
116
+ body: "GPU nodes maintenance",
117
+ field_published_date: "2024-03-15",
118
+ author: "Support",
119
+ custom_announcement_tags: "gpu, maintenance",
120
+ custom_announcement_ag: "",
121
+ },
122
+ ],
123
+ };
124
+
125
+ mockHttpClient.get.mockResolvedValue(mockResponse);
126
+
127
+ const result = await server["handleToolCall"]({
128
+ params: {
129
+ name: "get_announcements_by_tags",
130
+ arguments: {
131
+ tags: "gpu,maintenance",
132
+ limit: 20,
133
+ },
134
+ },
135
+ } as any);
136
+
137
+ const url = mockHttpClient.get.mock.calls[0][0];
138
+ expect(url).toContain("tags=gpu%2Cmaintenance");
139
+ // Note: exact_match is not implemented in the server
140
+
141
+ const responseData = JSON.parse(result.content[0].text);
142
+ expect(responseData.announcements[0].tags).toContain("gpu");
143
+ expect(responseData.announcements[0].tags).toContain("maintenance");
144
+ });
145
+ });
146
+
147
+ describe("get_announcements_by_affinity_group", () => {
148
+ it("should fetch announcements for affinity group", async () => {
149
+ const mockResponse = {
150
+ status: 200,
151
+ data: [
152
+ {
153
+ title: "AI/ML Community Update",
154
+ body: "New resources for AI/ML",
155
+ field_published_date: "2024-03-14",
156
+ author: "Community Team",
157
+ custom_announcement_tags: "ai, ml, community",
158
+ custom_announcement_ag: "ai-ml-123",
159
+ },
160
+ ],
161
+ };
162
+
163
+ mockHttpClient.get.mockResolvedValue(mockResponse);
164
+
165
+ const result = await server["handleToolCall"]({
166
+ params: {
167
+ name: "get_announcements_by_affinity_group",
168
+ arguments: {
169
+ ag: "ai-ml-123",
170
+ limit: 5,
171
+ },
172
+ },
173
+ } as any);
174
+
175
+ const url = mockHttpClient.get.mock.calls[0][0];
176
+ expect(url).toContain("ag=ai-ml-123");
177
+ // Note: limit is handled in JavaScript, not in URL
178
+
179
+ const responseData = JSON.parse(result.content[0].text);
180
+ expect(responseData.announcements).toHaveLength(1);
181
+ expect(responseData.announcements[0].affinity_groups).toContain("ai-ml-123");
182
+ });
183
+ });
184
+
185
+ describe("get_recent_announcements", () => {
186
+ it("should fetch recent announcements", async () => {
187
+ const mockResponse = {
188
+ status: 200,
189
+ data: [
190
+ {
191
+ title: "Today's Update",
192
+ body: "Important update",
193
+ date: new Date().toISOString(),
194
+ author: "Admin",
195
+ custom_support_tags: "urgent",
196
+ custom_affinity_groups: "",
197
+ },
198
+ ],
199
+ };
200
+
201
+ mockHttpClient.get.mockResolvedValue(mockResponse);
202
+
203
+ const result = await server["handleToolCall"]({
204
+ params: {
205
+ name: "get_recent_announcements",
206
+ arguments: {
207
+ period: "1 week",
208
+ },
209
+ },
210
+ } as any);
211
+
212
+ const url = mockHttpClient.get.mock.calls[0][0];
213
+ expect(url).toContain("relative_start_date=-1+week");
214
+
215
+ const responseData = JSON.parse(result.content[0].text);
216
+ expect(responseData.announcements).toHaveLength(1);
217
+ });
218
+
219
+ it("should default to past week if no time period specified", async () => {
220
+ mockHttpClient.get.mockResolvedValue({
221
+ status: 200,
222
+ data: [],
223
+ });
224
+
225
+ await server["handleToolCall"]({
226
+ params: {
227
+ name: "get_recent_announcements",
228
+ arguments: {},
229
+ },
230
+ } as any);
231
+
232
+ const url = mockHttpClient.get.mock.calls[0][0];
233
+ expect(url).toContain("relative_start_date=-1+month");
234
+ });
235
+ });
236
+ });
237
+
238
+ describe("URL Building", () => {
239
+ it("should build URLs with multiple filters", async () => {
240
+ mockHttpClient.get.mockResolvedValue({
241
+ status: 200,
242
+ data: [],
243
+ });
244
+
245
+ await server["handleToolCall"]({
246
+ params: {
247
+ name: "get_announcements",
248
+ arguments: {
249
+ tags: "gpu,maintenance",
250
+ ag: "123,456",
251
+ start_date: "2024-01-01",
252
+ end_date: "2024-12-31",
253
+ limit: 20,
254
+ },
255
+ },
256
+ } as any);
257
+
258
+ const url = mockHttpClient.get.mock.calls[0][0];
259
+ expect(url).toContain("tags=gpu%2Cmaintenance");
260
+ expect(url).toContain("ag=123%2C456");
261
+ expect(url).toContain("start_date=2024-01-01");
262
+ expect(url).toContain("end_date=2024-12-31");
263
+ // Note: exact_match and limit are not URL parameters
264
+ });
265
+
266
+ it("should handle relative date filters", async () => {
267
+ mockHttpClient.get.mockResolvedValue({
268
+ status: 200,
269
+ data: [],
270
+ });
271
+
272
+ await server["handleToolCall"]({
273
+ params: {
274
+ name: "get_announcements",
275
+ arguments: {
276
+ relative_start_date: "today",
277
+ relative_end_date: "+1month",
278
+ },
279
+ },
280
+ } as any);
281
+
282
+ const url = mockHttpClient.get.mock.calls[0][0];
283
+ expect(url).toContain("relative_start_date=today");
284
+ expect(url).toContain("relative_end_date=%2B1month");
285
+ });
286
+ });
287
+
288
+ describe("Data Enhancement", () => {
289
+ it("should parse tags correctly", async () => {
290
+ const mockResponse = {
291
+ status: 200,
292
+ data: [
293
+ {
294
+ title: "Test",
295
+ field_published_date: "2024-03-15",
296
+ custom_announcement_tags: "tag1, tag2, tag3 ",
297
+ custom_announcement_ag: "",
298
+ },
299
+ ],
300
+ };
301
+
302
+ mockHttpClient.get.mockResolvedValue(mockResponse);
303
+
304
+ const result = await server["handleToolCall"]({
305
+ params: {
306
+ name: "get_announcements",
307
+ arguments: {},
308
+ },
309
+ } as any);
310
+
311
+ const responseData = JSON.parse(result.content[0].text);
312
+ expect(responseData.announcements[0].tags).toEqual(["tag1", "tag2", "tag3"]);
313
+ });
314
+
315
+ it("should extract popular tags", async () => {
316
+ const mockResponse = {
317
+ status: 200,
318
+ data: [
319
+ { title: "1", field_published_date: "2024-03-15", custom_announcement_tags: "gpu, maintenance", custom_announcement_ag: "" },
320
+ { title: "2", field_published_date: "2024-03-14", custom_announcement_tags: "gpu, network", custom_announcement_ag: "" },
321
+ { title: "3", field_published_date: "2024-03-13", custom_announcement_tags: "gpu, storage", custom_announcement_ag: "" },
322
+ { title: "4", field_published_date: "2024-03-12", custom_announcement_tags: "maintenance", custom_announcement_ag: "" },
323
+ ],
324
+ };
325
+
326
+ mockHttpClient.get.mockResolvedValue(mockResponse);
327
+
328
+ const result = await server["handleToolCall"]({
329
+ params: {
330
+ name: "get_announcements",
331
+ arguments: {},
332
+ },
333
+ } as any);
334
+
335
+ const responseData = JSON.parse(result.content[0].text);
336
+ expect(responseData.popular_tags).toContain("gpu");
337
+ expect(responseData.popular_tags).toContain("maintenance");
338
+ });
339
+
340
+ it("should format dates correctly", async () => {
341
+ const mockResponse = {
342
+ status: 200,
343
+ data: [
344
+ {
345
+ title: "Test",
346
+ field_published_date: "2024-03-15",
347
+ custom_announcement_tags: "",
348
+ custom_announcement_ag: "",
349
+ },
350
+ ],
351
+ };
352
+
353
+ mockHttpClient.get.mockResolvedValue(mockResponse);
354
+
355
+ const result = await server["handleToolCall"]({
356
+ params: {
357
+ name: "get_announcements",
358
+ arguments: {},
359
+ },
360
+ } as any);
361
+
362
+ const responseData = JSON.parse(result.content[0].text);
363
+ expect(responseData.announcements[0].formatted_date).toBeDefined();
364
+ expect(responseData.announcements[0].formatted_date).toContain("March");
365
+ });
366
+ });
367
+ });