@esaio/esa-mcp-server 0.2.0 → 0.2.2
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.
- package/README.en.md +10 -6
- package/README.md +16 -12
- package/bin/{index.js → index.mjs} +1 -1
- package/package.json +22 -3
- package/.dockerignore +0 -36
- package/.github/dependabot.yml +0 -23
- package/.github/workflows/docker-publish.yml +0 -120
- package/.github/workflows/main.yml +0 -41
- package/CLAUDE.md +0 -94
- package/Dockerfile +0 -34
- package/biome.json +0 -57
- package/src/__tests__/fixtures/mock-comment.ts +0 -90
- package/src/__tests__/fixtures/mock-post.ts +0 -79
- package/src/__tests__/index.test.ts +0 -216
- package/src/api_client/__tests__/index.test.ts +0 -149
- package/src/api_client/__tests__/middleware.test.ts +0 -120
- package/src/api_client/__tests__/with-context.test.ts +0 -98
- package/src/api_client/index.ts +0 -29
- package/src/api_client/middleware.ts +0 -21
- package/src/api_client/with-context.ts +0 -26
- package/src/config/__tests__/index.test.ts +0 -65
- package/src/config/index.ts +0 -20
- package/src/context/mcp-context.ts +0 -1
- package/src/context/stdio-context.ts +0 -6
- package/src/errors/missing-team-name-error.ts +0 -8
- package/src/formatters/__tests__/mcp-response.test.ts +0 -106
- package/src/formatters/mcp-response.ts +0 -95
- package/src/generated/api-types.ts +0 -2968
- package/src/i18n/__tests__/index.test.ts +0 -53
- package/src/i18n/index.ts +0 -39
- package/src/index.ts +0 -47
- package/src/locales/en.json +0 -13
- package/src/locales/ja.json +0 -13
- package/src/prompts/__tests__/index.test.ts +0 -48
- package/src/prompts/__tests__/summarize-post.test.ts +0 -291
- package/src/prompts/index.ts +0 -21
- package/src/prompts/summarize-post.ts +0 -94
- package/src/resources/__tests__/index.test.ts +0 -50
- package/src/resources/__tests__/recent-posts-list.test.ts +0 -92
- package/src/resources/__tests__/recent-posts.test.ts +0 -270
- package/src/resources/index.ts +0 -33
- package/src/resources/recent-posts-list.ts +0 -22
- package/src/resources/recent-posts.ts +0 -45
- package/src/schemas/team-name-schema.ts +0 -19
- package/src/tools/__tests__/attachments.test.ts +0 -460
- package/src/tools/__tests__/categories.test.ts +0 -402
- package/src/tools/__tests__/comments.test.ts +0 -970
- package/src/tools/__tests__/helps.test.ts +0 -222
- package/src/tools/__tests__/index.test.ts +0 -48
- package/src/tools/__tests__/post-actions.test.ts +0 -445
- package/src/tools/__tests__/posts.test.ts +0 -917
- package/src/tools/__tests__/search.test.ts +0 -339
- package/src/tools/__tests__/teams.test.ts +0 -615
- package/src/tools/attachments.ts +0 -167
- package/src/tools/categories.ts +0 -153
- package/src/tools/comments.ts +0 -258
- package/src/tools/helps.ts +0 -50
- package/src/tools/index.ts +0 -351
- package/src/tools/post-actions.ts +0 -132
- package/src/tools/posts.ts +0 -179
- package/src/tools/search.ts +0 -98
- package/src/tools/teams.ts +0 -157
- package/src/transformers/__tests__/category-transformer.test.ts +0 -161
- package/src/transformers/__tests__/comment-transformer.test.ts +0 -129
- package/src/transformers/__tests__/post-name-normalizer.test.ts +0 -53
- package/src/transformers/__tests__/post-transformer.test.ts +0 -70
- package/src/transformers/__tests__/query-normalizer.test.ts +0 -98
- package/src/transformers/__tests__/team-name-normalizer.test.ts +0 -21
- package/src/transformers/category-transformer.ts +0 -36
- package/src/transformers/comment-transformer.ts +0 -34
- package/src/transformers/post-name-normalizer.ts +0 -30
- package/src/transformers/post-transformer.ts +0 -38
- package/src/transformers/query-normalizer.ts +0 -36
- package/src/transformers/team-name-normalizer.ts +0 -7
- package/tsconfig.build.json +0 -4
- package/tsconfig.json +0 -30
- package/tsdown.config.ts +0 -13
- package/vitest.config.ts +0 -24
|
@@ -1,615 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
import type { createEsaClient } from "../../api_client/index.js";
|
|
3
|
-
import {
|
|
4
|
-
getTeamMembers,
|
|
5
|
-
getTeamStats,
|
|
6
|
-
getTeams,
|
|
7
|
-
getTeamTags,
|
|
8
|
-
} from "../teams.js";
|
|
9
|
-
|
|
10
|
-
describe("getTeams", () => {
|
|
11
|
-
const mockClient = {
|
|
12
|
-
GET: vi.fn(),
|
|
13
|
-
} as unknown as ReturnType<typeof createEsaClient> & {
|
|
14
|
-
GET: ReturnType<typeof vi.fn>;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
beforeEach(() => {
|
|
18
|
-
vi.clearAllMocks();
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it("should return teams successfully", async () => {
|
|
22
|
-
const mockTeams = [
|
|
23
|
-
{
|
|
24
|
-
name: "test-team",
|
|
25
|
-
description: "Test team",
|
|
26
|
-
url: "https://test-team.esa.example.com",
|
|
27
|
-
privacy: "open",
|
|
28
|
-
icon: "https://example.com/icon.png",
|
|
29
|
-
},
|
|
30
|
-
];
|
|
31
|
-
|
|
32
|
-
const mockResponse = {
|
|
33
|
-
teams: mockTeams,
|
|
34
|
-
page: 1,
|
|
35
|
-
per_page: 20,
|
|
36
|
-
total_count: 1,
|
|
37
|
-
max_per_page: 100,
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
mockClient.GET.mockResolvedValue({
|
|
41
|
-
data: mockResponse,
|
|
42
|
-
error: undefined,
|
|
43
|
-
response: {
|
|
44
|
-
ok: true,
|
|
45
|
-
status: 200,
|
|
46
|
-
} as Response,
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
const result = await getTeams(mockClient);
|
|
50
|
-
|
|
51
|
-
expect(mockClient.GET).toHaveBeenCalledWith("/v1/teams", {
|
|
52
|
-
params: {
|
|
53
|
-
query: {
|
|
54
|
-
page: undefined,
|
|
55
|
-
per_page: undefined,
|
|
56
|
-
role: undefined,
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
const expectedResponse = {
|
|
62
|
-
teams: mockTeams.map((team) => ({
|
|
63
|
-
url: team.url,
|
|
64
|
-
name: team.name,
|
|
65
|
-
description: team.description,
|
|
66
|
-
})),
|
|
67
|
-
page: 1,
|
|
68
|
-
per_page: 20,
|
|
69
|
-
total_count: 1,
|
|
70
|
-
max_per_page: 100,
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
expect(result).toEqual({
|
|
74
|
-
content: [
|
|
75
|
-
{
|
|
76
|
-
type: "text",
|
|
77
|
-
text: JSON.stringify(expectedResponse, null, 2),
|
|
78
|
-
},
|
|
79
|
-
],
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it("should return teams with query parameters", async () => {
|
|
84
|
-
const args = { page: 2, perPage: 10, role: "owner" as const };
|
|
85
|
-
|
|
86
|
-
mockClient.GET.mockResolvedValue({
|
|
87
|
-
data: { teams: [] },
|
|
88
|
-
error: undefined,
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
await getTeams(mockClient, args);
|
|
92
|
-
|
|
93
|
-
expect(mockClient.GET).toHaveBeenCalledWith("/v1/teams", {
|
|
94
|
-
params: {
|
|
95
|
-
query: {
|
|
96
|
-
page: 2,
|
|
97
|
-
per_page: 10,
|
|
98
|
-
role: "owner",
|
|
99
|
-
},
|
|
100
|
-
},
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it("should handle API errors", async () => {
|
|
105
|
-
const mockError = { error: "unauthorized", message: "Invalid token" };
|
|
106
|
-
|
|
107
|
-
mockClient.GET.mockResolvedValue({
|
|
108
|
-
data: undefined,
|
|
109
|
-
error: mockError,
|
|
110
|
-
response: {
|
|
111
|
-
ok: false,
|
|
112
|
-
status: 404,
|
|
113
|
-
} as Response,
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
const result = await getTeams(mockClient);
|
|
117
|
-
|
|
118
|
-
expect(result).toEqual({
|
|
119
|
-
content: [
|
|
120
|
-
{
|
|
121
|
-
type: "text",
|
|
122
|
-
text: `Error: ${JSON.stringify(mockError, null, 2)}`,
|
|
123
|
-
},
|
|
124
|
-
],
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it("should handle network errors", async () => {
|
|
129
|
-
const networkError = new Error("Network connection failed");
|
|
130
|
-
|
|
131
|
-
mockClient.GET.mockRejectedValue(networkError);
|
|
132
|
-
|
|
133
|
-
const result = await getTeams(mockClient);
|
|
134
|
-
|
|
135
|
-
expect(result).toEqual({
|
|
136
|
-
content: [
|
|
137
|
-
{
|
|
138
|
-
type: "text",
|
|
139
|
-
text: "Error: Network connection failed",
|
|
140
|
-
},
|
|
141
|
-
],
|
|
142
|
-
});
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it("should handle non-Error exceptions", async () => {
|
|
146
|
-
mockClient.GET.mockRejectedValue("Unexpected error");
|
|
147
|
-
|
|
148
|
-
const result = await getTeams(mockClient);
|
|
149
|
-
|
|
150
|
-
expect(result).toEqual({
|
|
151
|
-
content: [
|
|
152
|
-
{
|
|
153
|
-
type: "text",
|
|
154
|
-
text: "Error: Unexpected error",
|
|
155
|
-
},
|
|
156
|
-
],
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
describe("getTeamStats", () => {
|
|
162
|
-
const mockClient = {
|
|
163
|
-
GET: vi.fn(),
|
|
164
|
-
} as unknown as ReturnType<typeof createEsaClient> & {
|
|
165
|
-
GET: ReturnType<typeof vi.fn>;
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
beforeEach(() => {
|
|
169
|
-
vi.clearAllMocks();
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
it("should return team stats successfully", async () => {
|
|
173
|
-
const mockStats = {
|
|
174
|
-
members: 25,
|
|
175
|
-
posts: 1234,
|
|
176
|
-
posts_wip: 56,
|
|
177
|
-
posts_shipped: 1178,
|
|
178
|
-
comments: 2345,
|
|
179
|
-
stars: 567,
|
|
180
|
-
watches: 89,
|
|
181
|
-
daily_active_users: 15,
|
|
182
|
-
weekly_active_users: 20,
|
|
183
|
-
monthly_active_users: 24,
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
mockClient.GET.mockResolvedValue({
|
|
187
|
-
data: mockStats,
|
|
188
|
-
error: undefined,
|
|
189
|
-
response: {
|
|
190
|
-
ok: true,
|
|
191
|
-
status: 200,
|
|
192
|
-
} as Response,
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
const result = await getTeamStats(mockClient, { teamName: "test-team" });
|
|
196
|
-
|
|
197
|
-
expect(mockClient.GET).toHaveBeenCalledWith("/v1/teams/{team_name}/stats", {
|
|
198
|
-
params: {
|
|
199
|
-
path: { team_name: "test-team" },
|
|
200
|
-
},
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
expect(result).toEqual({
|
|
204
|
-
content: [
|
|
205
|
-
{
|
|
206
|
-
type: "text",
|
|
207
|
-
text: JSON.stringify(mockStats, null, 2),
|
|
208
|
-
},
|
|
209
|
-
],
|
|
210
|
-
});
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
it("should handle API errors", async () => {
|
|
214
|
-
const mockError = { error: "not_found", message: "Team not found" };
|
|
215
|
-
|
|
216
|
-
mockClient.GET.mockResolvedValue({
|
|
217
|
-
data: undefined,
|
|
218
|
-
error: mockError,
|
|
219
|
-
response: {
|
|
220
|
-
ok: false,
|
|
221
|
-
status: 404,
|
|
222
|
-
} as Response,
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
const result = await getTeamStats(mockClient, { teamName: "test-team" });
|
|
226
|
-
|
|
227
|
-
expect(result).toEqual({
|
|
228
|
-
content: [
|
|
229
|
-
{
|
|
230
|
-
type: "text",
|
|
231
|
-
text: `Error: ${JSON.stringify(mockError, null, 2)}`,
|
|
232
|
-
},
|
|
233
|
-
],
|
|
234
|
-
});
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
it("should handle network errors", async () => {
|
|
238
|
-
const networkError = new Error("Network connection failed");
|
|
239
|
-
|
|
240
|
-
mockClient.GET.mockRejectedValue(networkError);
|
|
241
|
-
|
|
242
|
-
const result = await getTeamStats(mockClient, { teamName: "test-team" });
|
|
243
|
-
|
|
244
|
-
expect(result).toEqual({
|
|
245
|
-
content: [
|
|
246
|
-
{
|
|
247
|
-
type: "text",
|
|
248
|
-
text: "Error: Network connection failed",
|
|
249
|
-
},
|
|
250
|
-
],
|
|
251
|
-
});
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
it("should handle non-Error exceptions", async () => {
|
|
255
|
-
mockClient.GET.mockRejectedValue("Unexpected error");
|
|
256
|
-
|
|
257
|
-
const result = await getTeamStats(mockClient, { teamName: "test-team" });
|
|
258
|
-
|
|
259
|
-
expect(result).toEqual({
|
|
260
|
-
content: [
|
|
261
|
-
{
|
|
262
|
-
type: "text",
|
|
263
|
-
text: "Error: Unexpected error",
|
|
264
|
-
},
|
|
265
|
-
],
|
|
266
|
-
});
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
it("should throw MissingTeamNameError when teamName is empty", async () => {
|
|
270
|
-
const result = await getTeamStats(mockClient, { teamName: "" });
|
|
271
|
-
|
|
272
|
-
expect(result).toEqual({
|
|
273
|
-
content: [
|
|
274
|
-
{
|
|
275
|
-
type: "text",
|
|
276
|
-
text: "Error: Missing required parameter 'teamName'. Use esa_get_teams to list available teams, then retry with teamName specified.",
|
|
277
|
-
},
|
|
278
|
-
],
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
expect(mockClient.GET).not.toHaveBeenCalled();
|
|
282
|
-
});
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
describe("getTeamTags", () => {
|
|
286
|
-
const mockClient = {
|
|
287
|
-
GET: vi.fn(),
|
|
288
|
-
} as unknown as ReturnType<typeof createEsaClient> & {
|
|
289
|
-
GET: ReturnType<typeof vi.fn>;
|
|
290
|
-
};
|
|
291
|
-
|
|
292
|
-
beforeEach(() => {
|
|
293
|
-
vi.clearAllMocks();
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
it("should return team tags successfully", async () => {
|
|
297
|
-
const mockTags = {
|
|
298
|
-
tags: [
|
|
299
|
-
{ name: "design", posts_count: 42 },
|
|
300
|
-
{ name: "engineering", posts_count: 128 },
|
|
301
|
-
{ name: "meeting", posts_count: 35 },
|
|
302
|
-
],
|
|
303
|
-
page: 1,
|
|
304
|
-
per_page: 20,
|
|
305
|
-
total_count: 3,
|
|
306
|
-
max_per_page: 100,
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
mockClient.GET.mockResolvedValue({
|
|
310
|
-
data: mockTags,
|
|
311
|
-
error: undefined,
|
|
312
|
-
response: {
|
|
313
|
-
ok: true,
|
|
314
|
-
status: 200,
|
|
315
|
-
} as Response,
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
const result = await getTeamTags(mockClient, { teamName: "test-team" });
|
|
319
|
-
|
|
320
|
-
expect(mockClient.GET).toHaveBeenCalledWith("/v1/teams/{team_name}/tags", {
|
|
321
|
-
params: {
|
|
322
|
-
path: { team_name: "test-team" },
|
|
323
|
-
query: {
|
|
324
|
-
page: undefined,
|
|
325
|
-
perPage: undefined,
|
|
326
|
-
},
|
|
327
|
-
},
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
expect(result).toEqual({
|
|
331
|
-
content: [
|
|
332
|
-
{
|
|
333
|
-
type: "text",
|
|
334
|
-
text: JSON.stringify(mockTags, null, 2),
|
|
335
|
-
},
|
|
336
|
-
],
|
|
337
|
-
});
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
it("should handle pagination parameters", async () => {
|
|
341
|
-
const mockTags = {
|
|
342
|
-
tags: [],
|
|
343
|
-
page: 2,
|
|
344
|
-
per_page: 10,
|
|
345
|
-
total_count: 50,
|
|
346
|
-
max_per_page: 100,
|
|
347
|
-
};
|
|
348
|
-
|
|
349
|
-
mockClient.GET.mockResolvedValue({
|
|
350
|
-
data: mockTags,
|
|
351
|
-
error: undefined,
|
|
352
|
-
response: {
|
|
353
|
-
ok: true,
|
|
354
|
-
status: 200,
|
|
355
|
-
} as Response,
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
const result = await getTeamTags(mockClient, {
|
|
359
|
-
teamName: "test-team",
|
|
360
|
-
page: 2,
|
|
361
|
-
perPage: 10,
|
|
362
|
-
});
|
|
363
|
-
|
|
364
|
-
expect(mockClient.GET).toHaveBeenCalledWith("/v1/teams/{team_name}/tags", {
|
|
365
|
-
params: {
|
|
366
|
-
path: { team_name: "test-team" },
|
|
367
|
-
query: {
|
|
368
|
-
page: 2,
|
|
369
|
-
per_page: 10,
|
|
370
|
-
},
|
|
371
|
-
},
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
expect(result).toEqual({
|
|
375
|
-
content: [
|
|
376
|
-
{
|
|
377
|
-
type: "text",
|
|
378
|
-
text: JSON.stringify(mockTags, null, 2),
|
|
379
|
-
},
|
|
380
|
-
],
|
|
381
|
-
});
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
it("should handle API errors", async () => {
|
|
385
|
-
const mockError = { error: "not_found", message: "Team not found" };
|
|
386
|
-
|
|
387
|
-
mockClient.GET.mockResolvedValue({
|
|
388
|
-
data: undefined,
|
|
389
|
-
error: mockError,
|
|
390
|
-
response: {
|
|
391
|
-
ok: false,
|
|
392
|
-
status: 404,
|
|
393
|
-
} as Response,
|
|
394
|
-
});
|
|
395
|
-
|
|
396
|
-
const result = await getTeamTags(mockClient, { teamName: "test-team" });
|
|
397
|
-
|
|
398
|
-
expect(result).toEqual({
|
|
399
|
-
content: [
|
|
400
|
-
{
|
|
401
|
-
type: "text",
|
|
402
|
-
text: `Error: ${JSON.stringify(mockError, null, 2)}`,
|
|
403
|
-
},
|
|
404
|
-
],
|
|
405
|
-
});
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
it("should handle network errors", async () => {
|
|
409
|
-
const networkError = new Error("Network connection failed");
|
|
410
|
-
|
|
411
|
-
mockClient.GET.mockRejectedValue(networkError);
|
|
412
|
-
|
|
413
|
-
const result = await getTeamTags(mockClient, { teamName: "test-team" });
|
|
414
|
-
|
|
415
|
-
expect(result).toEqual({
|
|
416
|
-
content: [
|
|
417
|
-
{
|
|
418
|
-
type: "text",
|
|
419
|
-
text: "Error: Network connection failed",
|
|
420
|
-
},
|
|
421
|
-
],
|
|
422
|
-
});
|
|
423
|
-
});
|
|
424
|
-
|
|
425
|
-
it("should handle non-Error exceptions", async () => {
|
|
426
|
-
mockClient.GET.mockRejectedValue("Unexpected error");
|
|
427
|
-
|
|
428
|
-
const result = await getTeamTags(mockClient, { teamName: "test-team" });
|
|
429
|
-
|
|
430
|
-
expect(result).toEqual({
|
|
431
|
-
content: [
|
|
432
|
-
{
|
|
433
|
-
type: "text",
|
|
434
|
-
text: "Error: Unexpected error",
|
|
435
|
-
},
|
|
436
|
-
],
|
|
437
|
-
});
|
|
438
|
-
});
|
|
439
|
-
|
|
440
|
-
it("should throw MissingTeamNameError when teamName is empty", async () => {
|
|
441
|
-
const result = await getTeamTags(mockClient, { teamName: "" });
|
|
442
|
-
|
|
443
|
-
expect(result).toEqual({
|
|
444
|
-
content: [
|
|
445
|
-
{
|
|
446
|
-
type: "text",
|
|
447
|
-
text: "Error: Missing required parameter 'teamName'. Use esa_get_teams to list available teams, then retry with teamName specified.",
|
|
448
|
-
},
|
|
449
|
-
],
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
expect(mockClient.GET).not.toHaveBeenCalled();
|
|
453
|
-
});
|
|
454
|
-
});
|
|
455
|
-
|
|
456
|
-
describe("getTeamMembers", () => {
|
|
457
|
-
const mockClient = {
|
|
458
|
-
GET: vi.fn(),
|
|
459
|
-
} as unknown as ReturnType<typeof createEsaClient> & {
|
|
460
|
-
GET: ReturnType<typeof vi.fn>;
|
|
461
|
-
};
|
|
462
|
-
|
|
463
|
-
beforeEach(() => {
|
|
464
|
-
vi.clearAllMocks();
|
|
465
|
-
});
|
|
466
|
-
|
|
467
|
-
it("should return team members successfully", async () => {
|
|
468
|
-
const mockMembers = {
|
|
469
|
-
members: [
|
|
470
|
-
{ name: "John Doe", screen_name: "john", role: "owner" },
|
|
471
|
-
{ name: "Jane Smith", screen_name: "jane", role: "member" },
|
|
472
|
-
],
|
|
473
|
-
total_count: 2,
|
|
474
|
-
};
|
|
475
|
-
|
|
476
|
-
mockClient.GET.mockResolvedValue({
|
|
477
|
-
data: mockMembers,
|
|
478
|
-
error: undefined,
|
|
479
|
-
response: { ok: true } as Response,
|
|
480
|
-
});
|
|
481
|
-
|
|
482
|
-
const result = await getTeamMembers(mockClient, { teamName: "test-team" });
|
|
483
|
-
|
|
484
|
-
expect(mockClient.GET).toHaveBeenCalledWith(
|
|
485
|
-
"/v1/teams/{team_name}/members",
|
|
486
|
-
{
|
|
487
|
-
params: {
|
|
488
|
-
path: { team_name: "test-team" },
|
|
489
|
-
query: {
|
|
490
|
-
page: undefined,
|
|
491
|
-
per_page: undefined,
|
|
492
|
-
sort: undefined,
|
|
493
|
-
order: undefined,
|
|
494
|
-
},
|
|
495
|
-
},
|
|
496
|
-
},
|
|
497
|
-
);
|
|
498
|
-
|
|
499
|
-
expect(result).toEqual({
|
|
500
|
-
content: [{ type: "text", text: JSON.stringify(mockMembers, null, 2) }],
|
|
501
|
-
});
|
|
502
|
-
});
|
|
503
|
-
|
|
504
|
-
it("should handle pagination parameters", async () => {
|
|
505
|
-
mockClient.GET.mockResolvedValue({
|
|
506
|
-
data: {},
|
|
507
|
-
error: undefined,
|
|
508
|
-
response: { ok: true } as Response,
|
|
509
|
-
});
|
|
510
|
-
|
|
511
|
-
await getTeamMembers(mockClient, {
|
|
512
|
-
teamName: "test-team",
|
|
513
|
-
page: 2,
|
|
514
|
-
perPage: 5,
|
|
515
|
-
});
|
|
516
|
-
|
|
517
|
-
expect(mockClient.GET).toHaveBeenCalledWith(
|
|
518
|
-
"/v1/teams/{team_name}/members",
|
|
519
|
-
{
|
|
520
|
-
params: {
|
|
521
|
-
path: { team_name: "test-team" },
|
|
522
|
-
query: {
|
|
523
|
-
page: 2,
|
|
524
|
-
per_page: 5,
|
|
525
|
-
sort: undefined,
|
|
526
|
-
order: undefined,
|
|
527
|
-
},
|
|
528
|
-
},
|
|
529
|
-
},
|
|
530
|
-
);
|
|
531
|
-
});
|
|
532
|
-
|
|
533
|
-
it("should handle sort and order parameters", async () => {
|
|
534
|
-
mockClient.GET.mockResolvedValue({
|
|
535
|
-
data: {},
|
|
536
|
-
error: undefined,
|
|
537
|
-
response: { ok: true } as Response,
|
|
538
|
-
});
|
|
539
|
-
|
|
540
|
-
await getTeamMembers(mockClient, {
|
|
541
|
-
teamName: "test-team",
|
|
542
|
-
sort: "posts_count",
|
|
543
|
-
order: "desc",
|
|
544
|
-
});
|
|
545
|
-
|
|
546
|
-
expect(mockClient.GET).toHaveBeenCalledWith(
|
|
547
|
-
"/v1/teams/{team_name}/members",
|
|
548
|
-
{
|
|
549
|
-
params: {
|
|
550
|
-
path: { team_name: "test-team" },
|
|
551
|
-
query: {
|
|
552
|
-
page: undefined,
|
|
553
|
-
per_page: undefined,
|
|
554
|
-
sort: "posts_count",
|
|
555
|
-
order: "desc",
|
|
556
|
-
},
|
|
557
|
-
},
|
|
558
|
-
},
|
|
559
|
-
);
|
|
560
|
-
});
|
|
561
|
-
|
|
562
|
-
it("should handle API errors", async () => {
|
|
563
|
-
const mockError = { error: "not_found" };
|
|
564
|
-
|
|
565
|
-
mockClient.GET.mockResolvedValue({
|
|
566
|
-
error: mockError,
|
|
567
|
-
response: { ok: false } as Response,
|
|
568
|
-
});
|
|
569
|
-
|
|
570
|
-
const result = await getTeamMembers(mockClient, { teamName: "test-team" });
|
|
571
|
-
|
|
572
|
-
expect(result).toEqual({
|
|
573
|
-
content: [
|
|
574
|
-
{ type: "text", text: `Error: ${JSON.stringify(mockError, null, 2)}` },
|
|
575
|
-
],
|
|
576
|
-
});
|
|
577
|
-
});
|
|
578
|
-
|
|
579
|
-
it("should handle network errors", async () => {
|
|
580
|
-
const networkError = new Error("Network failed");
|
|
581
|
-
|
|
582
|
-
mockClient.GET.mockRejectedValue(networkError);
|
|
583
|
-
|
|
584
|
-
const result = await getTeamMembers(mockClient, { teamName: "test-team" });
|
|
585
|
-
|
|
586
|
-
expect(result).toEqual({
|
|
587
|
-
content: [{ type: "text", text: "Error: Network failed" }],
|
|
588
|
-
});
|
|
589
|
-
});
|
|
590
|
-
|
|
591
|
-
it("should handle non-Error exceptions", async () => {
|
|
592
|
-
mockClient.GET.mockRejectedValue("Unexpected error");
|
|
593
|
-
|
|
594
|
-
const result = await getTeamMembers(mockClient, { teamName: "test-team" });
|
|
595
|
-
|
|
596
|
-
expect(result).toEqual({
|
|
597
|
-
content: [{ type: "text", text: "Error: Unexpected error" }],
|
|
598
|
-
});
|
|
599
|
-
});
|
|
600
|
-
|
|
601
|
-
it("should throw MissingTeamNameError when teamName is empty", async () => {
|
|
602
|
-
const result = await getTeamMembers(mockClient, { teamName: "" });
|
|
603
|
-
|
|
604
|
-
expect(result).toEqual({
|
|
605
|
-
content: [
|
|
606
|
-
{
|
|
607
|
-
type: "text",
|
|
608
|
-
text: "Error: Missing required parameter 'teamName'. Use esa_get_teams to list available teams, then retry with teamName specified.",
|
|
609
|
-
},
|
|
610
|
-
],
|
|
611
|
-
});
|
|
612
|
-
|
|
613
|
-
expect(mockClient.GET).not.toHaveBeenCalled();
|
|
614
|
-
});
|
|
615
|
-
});
|