@vibescope/mcp-server 0.4.4 → 0.4.6
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/CHANGELOG.md +84 -84
- package/README.md +194 -194
- package/dist/api-client/bodies-of-work.d.ts +125 -0
- package/dist/api-client/bodies-of-work.js +78 -0
- package/dist/api-client/chat.d.ts +26 -0
- package/dist/api-client/chat.js +20 -0
- package/dist/api-client/connectors.d.ts +104 -0
- package/dist/api-client/connectors.js +46 -0
- package/dist/api-client/deployment.d.ts +190 -0
- package/dist/api-client/deployment.js +113 -0
- package/dist/api-client/file-checkouts.d.ts +71 -0
- package/dist/api-client/file-checkouts.js +43 -0
- package/dist/api-client/git-issues.d.ts +55 -0
- package/dist/api-client/git-issues.js +34 -0
- package/dist/api-client/index.d.ts +619 -1
- package/dist/api-client/index.js +148 -0
- package/dist/api-client/organizations.d.ts +101 -0
- package/dist/api-client/organizations.js +86 -0
- package/dist/api-client/progress.d.ts +61 -0
- package/dist/api-client/progress.js +34 -0
- package/dist/api-client/project.d.ts +1 -0
- package/dist/api-client/requests.d.ts +28 -0
- package/dist/api-client/requests.js +28 -0
- package/dist/api-client/sprints.d.ts +153 -0
- package/dist/api-client/sprints.js +82 -0
- package/dist/api-client/subtasks.d.ts +37 -0
- package/dist/api-client/subtasks.js +23 -0
- package/dist/api-client.d.ts +23 -0
- package/dist/api-client.js +15 -0
- package/dist/cli-init.js +21 -21
- package/dist/cli.js +26 -26
- package/dist/handlers/blockers.js +4 -0
- package/dist/handlers/chat.d.ts +23 -0
- package/dist/handlers/chat.js +84 -0
- package/dist/handlers/deployment.d.ts +3 -0
- package/dist/handlers/deployment.js +23 -0
- package/dist/handlers/discovery.js +13 -0
- package/dist/handlers/index.d.ts +1 -0
- package/dist/handlers/index.js +3 -0
- package/dist/handlers/project.js +4 -2
- package/dist/handlers/session.js +7 -0
- package/dist/handlers/tasks.js +7 -0
- package/dist/handlers/tool-docs.js +1204 -1131
- package/dist/index.js +73 -73
- package/dist/templates/agent-guidelines.d.ts +1 -1
- package/dist/templates/agent-guidelines.js +205 -187
- package/dist/templates/help-content.js +1621 -1621
- package/dist/tools/bodies-of-work.js +6 -6
- package/dist/tools/chat.d.ts +1 -0
- package/dist/tools/chat.js +24 -0
- package/dist/tools/cloud-agents.js +22 -22
- package/dist/tools/deployment.js +13 -0
- package/dist/tools/features.d.ts +13 -0
- package/dist/tools/features.js +151 -0
- package/dist/tools/index.d.ts +3 -1
- package/dist/tools/index.js +4 -1
- package/dist/tools/milestones.js +2 -2
- package/dist/tools/project.js +4 -0
- package/dist/tools/requests.js +1 -1
- package/dist/tools/session.js +11 -11
- package/dist/tools/sprints.js +9 -9
- package/dist/tools/tasks.js +35 -35
- package/dist/tools/worktrees.js +14 -14
- package/dist/tools.d.ts +2 -0
- package/dist/tools.js +3602 -0
- package/dist/utils.js +11 -11
- package/docs/TOOLS.md +2663 -2545
- package/package.json +53 -53
- package/scripts/generate-docs.ts +212 -212
- package/scripts/version-bump.ts +203 -203
- package/src/api-client/blockers.ts +86 -86
- package/src/api-client/bodies-of-work.ts +194 -0
- package/src/api-client/chat.ts +50 -0
- package/src/api-client/connectors.ts +152 -0
- package/src/api-client/cost.ts +185 -185
- package/src/api-client/decisions.ts +87 -87
- package/src/api-client/deployment.ts +313 -0
- package/src/api-client/discovery.ts +81 -81
- package/src/api-client/fallback.ts +52 -52
- package/src/api-client/file-checkouts.ts +115 -0
- package/src/api-client/findings.ts +100 -100
- package/src/api-client/git-issues.ts +88 -0
- package/src/api-client/ideas.ts +112 -112
- package/src/api-client/index.ts +592 -426
- package/src/api-client/milestones.ts +83 -83
- package/src/api-client/organizations.ts +185 -0
- package/src/api-client/progress.ts +94 -0
- package/src/api-client/project.ts +180 -179
- package/src/api-client/requests.ts +54 -0
- package/src/api-client/session.ts +220 -220
- package/src/api-client/sprints.ts +227 -0
- package/src/api-client/subtasks.ts +57 -0
- package/src/api-client/tasks.ts +450 -450
- package/src/api-client/types.ts +32 -32
- package/src/api-client/validation.ts +60 -60
- package/src/api-client/worktrees.ts +53 -53
- package/src/api-client.test.ts +847 -850
- package/src/api-client.ts +2707 -2672
- package/src/cli-init.ts +557 -557
- package/src/cli.test.ts +284 -284
- package/src/cli.ts +204 -204
- package/src/handlers/__test-setup__.ts +240 -236
- package/src/handlers/__test-utils__.ts +89 -89
- package/src/handlers/blockers.test.ts +468 -468
- package/src/handlers/blockers.ts +172 -163
- package/src/handlers/bodies-of-work.test.ts +704 -704
- package/src/handlers/bodies-of-work.ts +526 -526
- package/src/handlers/chat.test.ts +185 -0
- package/src/handlers/chat.ts +101 -0
- package/src/handlers/cloud-agents.test.ts +438 -438
- package/src/handlers/cloud-agents.ts +156 -156
- package/src/handlers/connectors.test.ts +834 -834
- package/src/handlers/connectors.ts +229 -229
- package/src/handlers/cost.test.ts +462 -462
- package/src/handlers/cost.ts +285 -285
- package/src/handlers/decisions.test.ts +382 -382
- package/src/handlers/decisions.ts +153 -153
- package/src/handlers/deployment.test.ts +551 -551
- package/src/handlers/deployment.ts +570 -541
- package/src/handlers/discovery.test.ts +206 -206
- package/src/handlers/discovery.ts +427 -414
- package/src/handlers/fallback.test.ts +537 -537
- package/src/handlers/fallback.ts +194 -194
- package/src/handlers/file-checkouts.test.ts +750 -750
- package/src/handlers/file-checkouts.ts +185 -185
- package/src/handlers/findings.test.ts +633 -633
- package/src/handlers/findings.ts +239 -239
- package/src/handlers/git-issues.test.ts +631 -631
- package/src/handlers/git-issues.ts +136 -136
- package/src/handlers/ideas.test.ts +644 -644
- package/src/handlers/ideas.ts +207 -207
- package/src/handlers/index.ts +93 -90
- package/src/handlers/milestones.test.ts +475 -475
- package/src/handlers/milestones.ts +180 -180
- package/src/handlers/organizations.test.ts +826 -826
- package/src/handlers/organizations.ts +315 -315
- package/src/handlers/progress.test.ts +269 -269
- package/src/handlers/progress.ts +77 -77
- package/src/handlers/project.test.ts +546 -546
- package/src/handlers/project.ts +242 -239
- package/src/handlers/requests.test.ts +303 -303
- package/src/handlers/requests.ts +99 -99
- package/src/handlers/roles.test.ts +305 -305
- package/src/handlers/roles.ts +219 -219
- package/src/handlers/session.test.ts +998 -998
- package/src/handlers/session.ts +1105 -1093
- package/src/handlers/sprints.test.ts +732 -732
- package/src/handlers/sprints.ts +537 -537
- package/src/handlers/tasks.test.ts +931 -931
- package/src/handlers/tasks.ts +1133 -1121
- package/src/handlers/tool-categories.test.ts +66 -66
- package/src/handlers/tool-docs.test.ts +511 -511
- package/src/handlers/tool-docs.ts +1571 -1491
- package/src/handlers/types.test.ts +259 -259
- package/src/handlers/types.ts +176 -176
- package/src/handlers/validation.test.ts +582 -582
- package/src/handlers/validation.ts +164 -164
- package/src/handlers/version.ts +63 -63
- package/src/index.test.ts +674 -674
- package/src/index.ts +807 -807
- package/src/setup.test.ts +233 -233
- package/src/setup.ts +404 -404
- package/src/templates/agent-guidelines.ts +233 -215
- package/src/templates/help-content.ts +1751 -1751
- package/src/token-tracking.test.ts +463 -463
- package/src/token-tracking.ts +167 -167
- package/src/tools/blockers.ts +122 -122
- package/src/tools/bodies-of-work.ts +283 -283
- package/src/tools/chat.ts +72 -46
- package/src/tools/cloud-agents.ts +101 -101
- package/src/tools/connectors.ts +191 -191
- package/src/tools/cost.ts +111 -111
- package/src/tools/decisions.ts +111 -111
- package/src/tools/deployment.ts +455 -442
- package/src/tools/discovery.ts +76 -76
- package/src/tools/fallback.ts +111 -111
- package/src/tools/features.ts +154 -0
- package/src/tools/file-checkouts.ts +145 -145
- package/src/tools/findings.ts +101 -101
- package/src/tools/git-issues.ts +130 -130
- package/src/tools/ideas.ts +162 -162
- package/src/tools/index.ts +141 -137
- package/src/tools/milestones.ts +118 -118
- package/src/tools/organizations.ts +224 -224
- package/src/tools/progress.ts +73 -73
- package/src/tools/project.ts +206 -202
- package/src/tools/requests.ts +68 -68
- package/src/tools/roles.ts +112 -112
- package/src/tools/session.ts +181 -181
- package/src/tools/sprints.ts +298 -298
- package/src/tools/tasks.ts +550 -550
- package/src/tools/tools.test.ts +222 -222
- package/src/tools/types.ts +9 -9
- package/src/tools/validation.ts +75 -75
- package/src/tools/version.ts +34 -34
- package/src/tools/worktrees.ts +66 -66
- package/src/tools.test.ts +416 -416
- package/src/utils.test.ts +1014 -1014
- package/src/utils.ts +586 -586
- package/src/validators.test.ts +223 -223
- package/src/validators.ts +249 -249
- package/src/version.ts +109 -109
- package/tsconfig.json +16 -16
- package/vitest.config.ts +14 -14
|
@@ -1,303 +1,303 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import { getPendingRequests, acknowledgeRequest, answerQuestion } from './requests.js';
|
|
3
|
-
import { ValidationError } from '../validators.js';
|
|
4
|
-
import { createMockContext } from './__test-utils__.js';
|
|
5
|
-
import { mockApiClient } from './__test-setup__.js';
|
|
6
|
-
|
|
7
|
-
// ============================================================================
|
|
8
|
-
// getPendingRequests Tests
|
|
9
|
-
// ============================================================================
|
|
10
|
-
|
|
11
|
-
describe('getPendingRequests', () => {
|
|
12
|
-
beforeEach(() => vi.clearAllMocks());
|
|
13
|
-
|
|
14
|
-
it('should throw error for missing project_id', async () => {
|
|
15
|
-
const ctx = createMockContext();
|
|
16
|
-
|
|
17
|
-
await expect(getPendingRequests({}, ctx)).rejects.toThrow(ValidationError);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('should throw error for invalid project_id UUID', async () => {
|
|
21
|
-
const ctx = createMockContext();
|
|
22
|
-
|
|
23
|
-
await expect(
|
|
24
|
-
getPendingRequests({ project_id: 'invalid' }, ctx)
|
|
25
|
-
).rejects.toThrow(ValidationError);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('should return empty list when no requests', async () => {
|
|
29
|
-
mockApiClient.getPendingRequests.mockResolvedValue({
|
|
30
|
-
ok: true,
|
|
31
|
-
data: { requests: [], total_count: 0, has_more: false },
|
|
32
|
-
});
|
|
33
|
-
const ctx = createMockContext();
|
|
34
|
-
|
|
35
|
-
const result = await getPendingRequests(
|
|
36
|
-
{ project_id: '123e4567-e89b-12d3-a456-426614174000' },
|
|
37
|
-
ctx
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
expect(result.result).toMatchObject({
|
|
41
|
-
requests: [],
|
|
42
|
-
total_count: 0,
|
|
43
|
-
has_more: false,
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('should return pending requests with pagination info', async () => {
|
|
48
|
-
const mockRequests = [
|
|
49
|
-
{
|
|
50
|
-
id: 'r1',
|
|
51
|
-
request_type: 'task',
|
|
52
|
-
content: 'Please do this',
|
|
53
|
-
session_id: null,
|
|
54
|
-
acknowledged_at: null,
|
|
55
|
-
created_at: '2025-01-14T10:00:00Z',
|
|
56
|
-
},
|
|
57
|
-
];
|
|
58
|
-
|
|
59
|
-
mockApiClient.getPendingRequests.mockResolvedValue({
|
|
60
|
-
ok: true,
|
|
61
|
-
data: { requests: mockRequests, total_count: 5, has_more: true },
|
|
62
|
-
});
|
|
63
|
-
const ctx = createMockContext();
|
|
64
|
-
|
|
65
|
-
const result = await getPendingRequests(
|
|
66
|
-
{ project_id: '123e4567-e89b-12d3-a456-426614174000' },
|
|
67
|
-
ctx
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
expect(result.result).toMatchObject({
|
|
71
|
-
requests: mockRequests,
|
|
72
|
-
total_count: 5,
|
|
73
|
-
has_more: true,
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('should call API client with project_id and session_id', async () => {
|
|
78
|
-
mockApiClient.getPendingRequests.mockResolvedValue({
|
|
79
|
-
ok: true,
|
|
80
|
-
data: { requests: [], total_count: 0, has_more: false },
|
|
81
|
-
});
|
|
82
|
-
const ctx = createMockContext({ sessionId: 'my-session' });
|
|
83
|
-
|
|
84
|
-
await getPendingRequests(
|
|
85
|
-
{ project_id: '123e4567-e89b-12d3-a456-426614174000' },
|
|
86
|
-
ctx
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
expect(mockApiClient.getPendingRequests).toHaveBeenCalledWith(
|
|
90
|
-
'123e4567-e89b-12d3-a456-426614174000',
|
|
91
|
-
'my-session',
|
|
92
|
-
50,
|
|
93
|
-
0
|
|
94
|
-
);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('should pass limit and offset to API client', async () => {
|
|
98
|
-
mockApiClient.getPendingRequests.mockResolvedValue({
|
|
99
|
-
ok: true,
|
|
100
|
-
data: { requests: [], total_count: 100, has_more: true },
|
|
101
|
-
});
|
|
102
|
-
const ctx = createMockContext({ sessionId: 'my-session' });
|
|
103
|
-
|
|
104
|
-
await getPendingRequests(
|
|
105
|
-
{
|
|
106
|
-
project_id: '123e4567-e89b-12d3-a456-426614174000',
|
|
107
|
-
limit: 10,
|
|
108
|
-
offset: 20,
|
|
109
|
-
},
|
|
110
|
-
ctx
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
expect(mockApiClient.getPendingRequests).toHaveBeenCalledWith(
|
|
114
|
-
'123e4567-e89b-12d3-a456-426614174000',
|
|
115
|
-
'my-session',
|
|
116
|
-
10,
|
|
117
|
-
20
|
|
118
|
-
);
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
it('should return error when API call fails', async () => {
|
|
122
|
-
mockApiClient.getPendingRequests.mockResolvedValue({
|
|
123
|
-
ok: false,
|
|
124
|
-
error: 'Query failed',
|
|
125
|
-
});
|
|
126
|
-
const ctx = createMockContext();
|
|
127
|
-
|
|
128
|
-
const result = await getPendingRequests(
|
|
129
|
-
{ project_id: '123e4567-e89b-12d3-a456-426614174000' },
|
|
130
|
-
ctx
|
|
131
|
-
);
|
|
132
|
-
|
|
133
|
-
expect(result.isError).toBe(true);
|
|
134
|
-
expect(result.result).toMatchObject({
|
|
135
|
-
error: 'Query failed',
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
// ============================================================================
|
|
141
|
-
// acknowledgeRequest Tests
|
|
142
|
-
// ============================================================================
|
|
143
|
-
|
|
144
|
-
describe('acknowledgeRequest', () => {
|
|
145
|
-
beforeEach(() => vi.clearAllMocks());
|
|
146
|
-
|
|
147
|
-
it('should throw error for missing request_id', async () => {
|
|
148
|
-
const ctx = createMockContext();
|
|
149
|
-
|
|
150
|
-
await expect(acknowledgeRequest({}, ctx)).rejects.toThrow(ValidationError);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it('should throw error for invalid request_id UUID', async () => {
|
|
154
|
-
const ctx = createMockContext();
|
|
155
|
-
|
|
156
|
-
await expect(
|
|
157
|
-
acknowledgeRequest({ request_id: 'invalid' }, ctx)
|
|
158
|
-
).rejects.toThrow(ValidationError);
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it('should acknowledge request successfully', async () => {
|
|
162
|
-
mockApiClient.acknowledgeRequest.mockResolvedValue({
|
|
163
|
-
ok: true,
|
|
164
|
-
data: { success: true },
|
|
165
|
-
});
|
|
166
|
-
const ctx = createMockContext();
|
|
167
|
-
|
|
168
|
-
const result = await acknowledgeRequest(
|
|
169
|
-
{ request_id: '123e4567-e89b-12d3-a456-426614174000' },
|
|
170
|
-
ctx
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
expect(result.result).toMatchObject({
|
|
174
|
-
success: true,
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
it('should call API client with request_id and session_id', async () => {
|
|
179
|
-
mockApiClient.acknowledgeRequest.mockResolvedValue({
|
|
180
|
-
ok: true,
|
|
181
|
-
data: { success: true },
|
|
182
|
-
});
|
|
183
|
-
const ctx = createMockContext({ sessionId: 'my-session' });
|
|
184
|
-
|
|
185
|
-
await acknowledgeRequest(
|
|
186
|
-
{ request_id: '123e4567-e89b-12d3-a456-426614174000' },
|
|
187
|
-
ctx
|
|
188
|
-
);
|
|
189
|
-
|
|
190
|
-
expect(mockApiClient.acknowledgeRequest).toHaveBeenCalledWith(
|
|
191
|
-
'123e4567-e89b-12d3-a456-426614174000',
|
|
192
|
-
'my-session'
|
|
193
|
-
);
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
it('should return error when API call fails', async () => {
|
|
197
|
-
mockApiClient.acknowledgeRequest.mockResolvedValue({
|
|
198
|
-
ok: false,
|
|
199
|
-
error: 'Update failed',
|
|
200
|
-
});
|
|
201
|
-
const ctx = createMockContext();
|
|
202
|
-
|
|
203
|
-
const result = await acknowledgeRequest({ request_id: '123e4567-e89b-12d3-a456-426614174000' }, ctx);
|
|
204
|
-
|
|
205
|
-
expect(result.isError).toBe(true);
|
|
206
|
-
expect(result.result).toMatchObject({
|
|
207
|
-
error: 'Update failed',
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
// ============================================================================
|
|
213
|
-
// answerQuestion Tests
|
|
214
|
-
// ============================================================================
|
|
215
|
-
|
|
216
|
-
describe('answerQuestion', () => {
|
|
217
|
-
beforeEach(() => vi.clearAllMocks());
|
|
218
|
-
|
|
219
|
-
it('should throw error for missing request_id', async () => {
|
|
220
|
-
const ctx = createMockContext();
|
|
221
|
-
|
|
222
|
-
await expect(
|
|
223
|
-
answerQuestion({ answer: 'The answer' }, ctx)
|
|
224
|
-
).rejects.toThrow(ValidationError);
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
it('should throw error for missing answer', async () => {
|
|
228
|
-
const ctx = createMockContext();
|
|
229
|
-
|
|
230
|
-
await expect(
|
|
231
|
-
answerQuestion({ request_id: '123e4567-e89b-12d3-a456-426614174000' }, ctx)
|
|
232
|
-
).rejects.toThrow(ValidationError);
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
it('should throw error for invalid request_id UUID', async () => {
|
|
236
|
-
const ctx = createMockContext();
|
|
237
|
-
|
|
238
|
-
await expect(
|
|
239
|
-
answerQuestion({ request_id: 'invalid', answer: 'The answer' }, ctx)
|
|
240
|
-
).rejects.toThrow(ValidationError);
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
it('should answer question successfully', async () => {
|
|
244
|
-
mockApiClient.answerQuestion.mockResolvedValue({
|
|
245
|
-
ok: true,
|
|
246
|
-
data: { success: true },
|
|
247
|
-
});
|
|
248
|
-
const ctx = createMockContext();
|
|
249
|
-
|
|
250
|
-
const result = await answerQuestion(
|
|
251
|
-
{
|
|
252
|
-
request_id: '123e4567-e89b-12d3-a456-426614174000',
|
|
253
|
-
answer: 'This is the answer',
|
|
254
|
-
},
|
|
255
|
-
ctx
|
|
256
|
-
);
|
|
257
|
-
|
|
258
|
-
expect(result.result).toMatchObject({
|
|
259
|
-
success: true,
|
|
260
|
-
message: 'Question answered successfully',
|
|
261
|
-
});
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
it('should call API client with request_id, answer, and session_id', async () => {
|
|
265
|
-
mockApiClient.answerQuestion.mockResolvedValue({
|
|
266
|
-
ok: true,
|
|
267
|
-
data: { success: true },
|
|
268
|
-
});
|
|
269
|
-
const ctx = createMockContext({ sessionId: 'my-session' });
|
|
270
|
-
|
|
271
|
-
await answerQuestion(
|
|
272
|
-
{
|
|
273
|
-
request_id: '123e4567-e89b-12d3-a456-426614174000',
|
|
274
|
-
answer: 'The answer to the question',
|
|
275
|
-
},
|
|
276
|
-
ctx
|
|
277
|
-
);
|
|
278
|
-
|
|
279
|
-
expect(mockApiClient.answerQuestion).toHaveBeenCalledWith(
|
|
280
|
-
'123e4567-e89b-12d3-a456-426614174000',
|
|
281
|
-
'The answer to the question',
|
|
282
|
-
'my-session'
|
|
283
|
-
);
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
it('should return error when API call fails', async () => {
|
|
287
|
-
mockApiClient.answerQuestion.mockResolvedValue({
|
|
288
|
-
ok: false,
|
|
289
|
-
error: 'Update failed',
|
|
290
|
-
});
|
|
291
|
-
const ctx = createMockContext();
|
|
292
|
-
|
|
293
|
-
const result = await answerQuestion({
|
|
294
|
-
request_id: '123e4567-e89b-12d3-a456-426614174000',
|
|
295
|
-
answer: 'Answer',
|
|
296
|
-
}, ctx);
|
|
297
|
-
|
|
298
|
-
expect(result.isError).toBe(true);
|
|
299
|
-
expect(result.result).toMatchObject({
|
|
300
|
-
error: 'Update failed',
|
|
301
|
-
});
|
|
302
|
-
});
|
|
303
|
-
});
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { getPendingRequests, acknowledgeRequest, answerQuestion } from './requests.js';
|
|
3
|
+
import { ValidationError } from '../validators.js';
|
|
4
|
+
import { createMockContext } from './__test-utils__.js';
|
|
5
|
+
import { mockApiClient } from './__test-setup__.js';
|
|
6
|
+
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// getPendingRequests Tests
|
|
9
|
+
// ============================================================================
|
|
10
|
+
|
|
11
|
+
describe('getPendingRequests', () => {
|
|
12
|
+
beforeEach(() => vi.clearAllMocks());
|
|
13
|
+
|
|
14
|
+
it('should throw error for missing project_id', async () => {
|
|
15
|
+
const ctx = createMockContext();
|
|
16
|
+
|
|
17
|
+
await expect(getPendingRequests({}, ctx)).rejects.toThrow(ValidationError);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should throw error for invalid project_id UUID', async () => {
|
|
21
|
+
const ctx = createMockContext();
|
|
22
|
+
|
|
23
|
+
await expect(
|
|
24
|
+
getPendingRequests({ project_id: 'invalid' }, ctx)
|
|
25
|
+
).rejects.toThrow(ValidationError);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should return empty list when no requests', async () => {
|
|
29
|
+
mockApiClient.getPendingRequests.mockResolvedValue({
|
|
30
|
+
ok: true,
|
|
31
|
+
data: { requests: [], total_count: 0, has_more: false },
|
|
32
|
+
});
|
|
33
|
+
const ctx = createMockContext();
|
|
34
|
+
|
|
35
|
+
const result = await getPendingRequests(
|
|
36
|
+
{ project_id: '123e4567-e89b-12d3-a456-426614174000' },
|
|
37
|
+
ctx
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
expect(result.result).toMatchObject({
|
|
41
|
+
requests: [],
|
|
42
|
+
total_count: 0,
|
|
43
|
+
has_more: false,
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should return pending requests with pagination info', async () => {
|
|
48
|
+
const mockRequests = [
|
|
49
|
+
{
|
|
50
|
+
id: 'r1',
|
|
51
|
+
request_type: 'task',
|
|
52
|
+
content: 'Please do this',
|
|
53
|
+
session_id: null,
|
|
54
|
+
acknowledged_at: null,
|
|
55
|
+
created_at: '2025-01-14T10:00:00Z',
|
|
56
|
+
},
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
mockApiClient.getPendingRequests.mockResolvedValue({
|
|
60
|
+
ok: true,
|
|
61
|
+
data: { requests: mockRequests, total_count: 5, has_more: true },
|
|
62
|
+
});
|
|
63
|
+
const ctx = createMockContext();
|
|
64
|
+
|
|
65
|
+
const result = await getPendingRequests(
|
|
66
|
+
{ project_id: '123e4567-e89b-12d3-a456-426614174000' },
|
|
67
|
+
ctx
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
expect(result.result).toMatchObject({
|
|
71
|
+
requests: mockRequests,
|
|
72
|
+
total_count: 5,
|
|
73
|
+
has_more: true,
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('should call API client with project_id and session_id', async () => {
|
|
78
|
+
mockApiClient.getPendingRequests.mockResolvedValue({
|
|
79
|
+
ok: true,
|
|
80
|
+
data: { requests: [], total_count: 0, has_more: false },
|
|
81
|
+
});
|
|
82
|
+
const ctx = createMockContext({ sessionId: 'my-session' });
|
|
83
|
+
|
|
84
|
+
await getPendingRequests(
|
|
85
|
+
{ project_id: '123e4567-e89b-12d3-a456-426614174000' },
|
|
86
|
+
ctx
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
expect(mockApiClient.getPendingRequests).toHaveBeenCalledWith(
|
|
90
|
+
'123e4567-e89b-12d3-a456-426614174000',
|
|
91
|
+
'my-session',
|
|
92
|
+
50,
|
|
93
|
+
0
|
|
94
|
+
);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should pass limit and offset to API client', async () => {
|
|
98
|
+
mockApiClient.getPendingRequests.mockResolvedValue({
|
|
99
|
+
ok: true,
|
|
100
|
+
data: { requests: [], total_count: 100, has_more: true },
|
|
101
|
+
});
|
|
102
|
+
const ctx = createMockContext({ sessionId: 'my-session' });
|
|
103
|
+
|
|
104
|
+
await getPendingRequests(
|
|
105
|
+
{
|
|
106
|
+
project_id: '123e4567-e89b-12d3-a456-426614174000',
|
|
107
|
+
limit: 10,
|
|
108
|
+
offset: 20,
|
|
109
|
+
},
|
|
110
|
+
ctx
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
expect(mockApiClient.getPendingRequests).toHaveBeenCalledWith(
|
|
114
|
+
'123e4567-e89b-12d3-a456-426614174000',
|
|
115
|
+
'my-session',
|
|
116
|
+
10,
|
|
117
|
+
20
|
|
118
|
+
);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('should return error when API call fails', async () => {
|
|
122
|
+
mockApiClient.getPendingRequests.mockResolvedValue({
|
|
123
|
+
ok: false,
|
|
124
|
+
error: 'Query failed',
|
|
125
|
+
});
|
|
126
|
+
const ctx = createMockContext();
|
|
127
|
+
|
|
128
|
+
const result = await getPendingRequests(
|
|
129
|
+
{ project_id: '123e4567-e89b-12d3-a456-426614174000' },
|
|
130
|
+
ctx
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
expect(result.isError).toBe(true);
|
|
134
|
+
expect(result.result).toMatchObject({
|
|
135
|
+
error: 'Query failed',
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// ============================================================================
|
|
141
|
+
// acknowledgeRequest Tests
|
|
142
|
+
// ============================================================================
|
|
143
|
+
|
|
144
|
+
describe('acknowledgeRequest', () => {
|
|
145
|
+
beforeEach(() => vi.clearAllMocks());
|
|
146
|
+
|
|
147
|
+
it('should throw error for missing request_id', async () => {
|
|
148
|
+
const ctx = createMockContext();
|
|
149
|
+
|
|
150
|
+
await expect(acknowledgeRequest({}, ctx)).rejects.toThrow(ValidationError);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('should throw error for invalid request_id UUID', async () => {
|
|
154
|
+
const ctx = createMockContext();
|
|
155
|
+
|
|
156
|
+
await expect(
|
|
157
|
+
acknowledgeRequest({ request_id: 'invalid' }, ctx)
|
|
158
|
+
).rejects.toThrow(ValidationError);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('should acknowledge request successfully', async () => {
|
|
162
|
+
mockApiClient.acknowledgeRequest.mockResolvedValue({
|
|
163
|
+
ok: true,
|
|
164
|
+
data: { success: true },
|
|
165
|
+
});
|
|
166
|
+
const ctx = createMockContext();
|
|
167
|
+
|
|
168
|
+
const result = await acknowledgeRequest(
|
|
169
|
+
{ request_id: '123e4567-e89b-12d3-a456-426614174000' },
|
|
170
|
+
ctx
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
expect(result.result).toMatchObject({
|
|
174
|
+
success: true,
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('should call API client with request_id and session_id', async () => {
|
|
179
|
+
mockApiClient.acknowledgeRequest.mockResolvedValue({
|
|
180
|
+
ok: true,
|
|
181
|
+
data: { success: true },
|
|
182
|
+
});
|
|
183
|
+
const ctx = createMockContext({ sessionId: 'my-session' });
|
|
184
|
+
|
|
185
|
+
await acknowledgeRequest(
|
|
186
|
+
{ request_id: '123e4567-e89b-12d3-a456-426614174000' },
|
|
187
|
+
ctx
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
expect(mockApiClient.acknowledgeRequest).toHaveBeenCalledWith(
|
|
191
|
+
'123e4567-e89b-12d3-a456-426614174000',
|
|
192
|
+
'my-session'
|
|
193
|
+
);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it('should return error when API call fails', async () => {
|
|
197
|
+
mockApiClient.acknowledgeRequest.mockResolvedValue({
|
|
198
|
+
ok: false,
|
|
199
|
+
error: 'Update failed',
|
|
200
|
+
});
|
|
201
|
+
const ctx = createMockContext();
|
|
202
|
+
|
|
203
|
+
const result = await acknowledgeRequest({ request_id: '123e4567-e89b-12d3-a456-426614174000' }, ctx);
|
|
204
|
+
|
|
205
|
+
expect(result.isError).toBe(true);
|
|
206
|
+
expect(result.result).toMatchObject({
|
|
207
|
+
error: 'Update failed',
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
// ============================================================================
|
|
213
|
+
// answerQuestion Tests
|
|
214
|
+
// ============================================================================
|
|
215
|
+
|
|
216
|
+
describe('answerQuestion', () => {
|
|
217
|
+
beforeEach(() => vi.clearAllMocks());
|
|
218
|
+
|
|
219
|
+
it('should throw error for missing request_id', async () => {
|
|
220
|
+
const ctx = createMockContext();
|
|
221
|
+
|
|
222
|
+
await expect(
|
|
223
|
+
answerQuestion({ answer: 'The answer' }, ctx)
|
|
224
|
+
).rejects.toThrow(ValidationError);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('should throw error for missing answer', async () => {
|
|
228
|
+
const ctx = createMockContext();
|
|
229
|
+
|
|
230
|
+
await expect(
|
|
231
|
+
answerQuestion({ request_id: '123e4567-e89b-12d3-a456-426614174000' }, ctx)
|
|
232
|
+
).rejects.toThrow(ValidationError);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it('should throw error for invalid request_id UUID', async () => {
|
|
236
|
+
const ctx = createMockContext();
|
|
237
|
+
|
|
238
|
+
await expect(
|
|
239
|
+
answerQuestion({ request_id: 'invalid', answer: 'The answer' }, ctx)
|
|
240
|
+
).rejects.toThrow(ValidationError);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it('should answer question successfully', async () => {
|
|
244
|
+
mockApiClient.answerQuestion.mockResolvedValue({
|
|
245
|
+
ok: true,
|
|
246
|
+
data: { success: true },
|
|
247
|
+
});
|
|
248
|
+
const ctx = createMockContext();
|
|
249
|
+
|
|
250
|
+
const result = await answerQuestion(
|
|
251
|
+
{
|
|
252
|
+
request_id: '123e4567-e89b-12d3-a456-426614174000',
|
|
253
|
+
answer: 'This is the answer',
|
|
254
|
+
},
|
|
255
|
+
ctx
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
expect(result.result).toMatchObject({
|
|
259
|
+
success: true,
|
|
260
|
+
message: 'Question answered successfully',
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it('should call API client with request_id, answer, and session_id', async () => {
|
|
265
|
+
mockApiClient.answerQuestion.mockResolvedValue({
|
|
266
|
+
ok: true,
|
|
267
|
+
data: { success: true },
|
|
268
|
+
});
|
|
269
|
+
const ctx = createMockContext({ sessionId: 'my-session' });
|
|
270
|
+
|
|
271
|
+
await answerQuestion(
|
|
272
|
+
{
|
|
273
|
+
request_id: '123e4567-e89b-12d3-a456-426614174000',
|
|
274
|
+
answer: 'The answer to the question',
|
|
275
|
+
},
|
|
276
|
+
ctx
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
expect(mockApiClient.answerQuestion).toHaveBeenCalledWith(
|
|
280
|
+
'123e4567-e89b-12d3-a456-426614174000',
|
|
281
|
+
'The answer to the question',
|
|
282
|
+
'my-session'
|
|
283
|
+
);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('should return error when API call fails', async () => {
|
|
287
|
+
mockApiClient.answerQuestion.mockResolvedValue({
|
|
288
|
+
ok: false,
|
|
289
|
+
error: 'Update failed',
|
|
290
|
+
});
|
|
291
|
+
const ctx = createMockContext();
|
|
292
|
+
|
|
293
|
+
const result = await answerQuestion({
|
|
294
|
+
request_id: '123e4567-e89b-12d3-a456-426614174000',
|
|
295
|
+
answer: 'Answer',
|
|
296
|
+
}, ctx);
|
|
297
|
+
|
|
298
|
+
expect(result.isError).toBe(true);
|
|
299
|
+
expect(result.result).toMatchObject({
|
|
300
|
+
error: 'Update failed',
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
});
|