@vibescope/mcp-server 0.0.1 → 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.
- package/README.md +113 -98
- package/dist/api-client.d.ts +1114 -0
- package/dist/api-client.js +698 -0
- package/dist/cli.d.ts +1 -6
- package/dist/cli.js +39 -240
- package/dist/config/tool-categories.d.ts +31 -0
- package/dist/config/tool-categories.js +253 -0
- package/dist/handlers/blockers.js +57 -58
- package/dist/handlers/bodies-of-work.d.ts +2 -0
- package/dist/handlers/bodies-of-work.js +106 -476
- package/dist/handlers/cost.d.ts +1 -0
- package/dist/handlers/cost.js +35 -113
- package/dist/handlers/decisions.d.ts +2 -0
- package/dist/handlers/decisions.js +28 -27
- package/dist/handlers/deployment.js +112 -828
- package/dist/handlers/discovery.js +31 -0
- package/dist/handlers/fallback.d.ts +2 -0
- package/dist/handlers/fallback.js +39 -134
- package/dist/handlers/findings.js +43 -67
- package/dist/handlers/git-issues.d.ts +9 -13
- package/dist/handlers/git-issues.js +80 -225
- package/dist/handlers/ideas.d.ts +3 -0
- package/dist/handlers/ideas.js +53 -134
- package/dist/handlers/index.d.ts +2 -0
- package/dist/handlers/index.js +6 -0
- package/dist/handlers/milestones.d.ts +2 -0
- package/dist/handlers/milestones.js +51 -98
- package/dist/handlers/organizations.js +79 -275
- package/dist/handlers/progress.d.ts +2 -0
- package/dist/handlers/progress.js +25 -123
- package/dist/handlers/project.js +42 -221
- package/dist/handlers/requests.d.ts +2 -0
- package/dist/handlers/requests.js +23 -83
- package/dist/handlers/session.js +99 -585
- package/dist/handlers/sprints.d.ts +32 -0
- package/dist/handlers/sprints.js +274 -0
- package/dist/handlers/tasks.d.ts +7 -10
- package/dist/handlers/tasks.js +230 -900
- package/dist/handlers/tool-docs.d.ts +8 -0
- package/dist/handlers/tool-docs.js +657 -0
- package/dist/handlers/types.d.ts +11 -3
- package/dist/handlers/validation.d.ts +1 -1
- package/dist/handlers/validation.js +26 -153
- package/dist/index.js +473 -160
- package/dist/knowledge.js +106 -9
- package/dist/tools.js +4 -0
- package/dist/validators.d.ts +21 -0
- package/dist/validators.js +91 -0
- package/package.json +2 -3
- package/src/api-client.ts +1752 -0
- package/src/cli.test.ts +128 -302
- package/src/cli.ts +41 -285
- package/src/handlers/__test-setup__.ts +210 -0
- package/src/handlers/__test-utils__.ts +4 -134
- package/src/handlers/blockers.test.ts +114 -124
- package/src/handlers/blockers.ts +68 -70
- package/src/handlers/bodies-of-work.test.ts +236 -831
- package/src/handlers/bodies-of-work.ts +194 -525
- package/src/handlers/cost.test.ts +149 -113
- package/src/handlers/cost.ts +44 -132
- package/src/handlers/decisions.test.ts +111 -209
- package/src/handlers/decisions.ts +35 -27
- package/src/handlers/deployment.test.ts +193 -239
- package/src/handlers/deployment.ts +140 -895
- package/src/handlers/discovery.test.ts +20 -67
- package/src/handlers/discovery.ts +32 -0
- package/src/handlers/fallback.test.ts +128 -361
- package/src/handlers/fallback.ts +62 -148
- package/src/handlers/findings.test.ts +127 -345
- package/src/handlers/findings.ts +49 -66
- package/src/handlers/git-issues.test.ts +623 -0
- package/src/handlers/git-issues.ts +174 -0
- package/src/handlers/ideas.test.ts +229 -343
- package/src/handlers/ideas.ts +69 -143
- package/src/handlers/index.ts +6 -0
- package/src/handlers/milestones.test.ts +167 -281
- package/src/handlers/milestones.ts +54 -93
- package/src/handlers/organizations.test.ts +275 -467
- package/src/handlers/organizations.ts +84 -294
- package/src/handlers/progress.test.ts +112 -218
- package/src/handlers/progress.ts +29 -142
- package/src/handlers/project.test.ts +203 -226
- package/src/handlers/project.ts +48 -238
- package/src/handlers/requests.test.ts +74 -342
- package/src/handlers/requests.ts +25 -83
- package/src/handlers/session.test.ts +241 -206
- package/src/handlers/session.ts +110 -657
- package/src/handlers/sprints.test.ts +711 -0
- package/src/handlers/sprints.ts +497 -0
- package/src/handlers/tasks.test.ts +608 -353
- package/src/handlers/tasks.ts +248 -1025
- package/src/handlers/types.ts +12 -4
- package/src/handlers/validation.test.ts +189 -572
- package/src/handlers/validation.ts +29 -166
- package/src/index.ts +473 -184
- package/src/knowledge.ts +107 -9
- package/src/tools.ts +2506 -0
- package/src/validators.test.ts +223 -223
- package/src/validators.ts +127 -0
- package/tsconfig.json +1 -1
- package/vitest.config.ts +14 -13
- package/dist/cli.test.d.ts +0 -1
- package/dist/cli.test.js +0 -367
- package/dist/handlers/__test-utils__.d.ts +0 -72
- package/dist/handlers/__test-utils__.js +0 -176
- package/dist/handlers/checkouts.d.ts +0 -37
- package/dist/handlers/checkouts.js +0 -377
- package/dist/handlers/knowledge-query.d.ts +0 -22
- package/dist/handlers/knowledge-query.js +0 -253
- package/dist/handlers/knowledge.d.ts +0 -12
- package/dist/handlers/knowledge.js +0 -108
- package/dist/handlers/roles.d.ts +0 -30
- package/dist/handlers/roles.js +0 -281
- package/dist/handlers/tasks.test.d.ts +0 -1
- package/dist/handlers/tasks.test.js +0 -431
- package/dist/utils.test.d.ts +0 -1
- package/dist/utils.test.js +0 -532
- package/dist/validators.test.d.ts +0 -1
- package/dist/validators.test.js +0 -176
- package/src/tmpclaude-0078-cwd +0 -1
- package/src/tmpclaude-0ee1-cwd +0 -1
- package/src/tmpclaude-2dd5-cwd +0 -1
- package/src/tmpclaude-344c-cwd +0 -1
- package/src/tmpclaude-3860-cwd +0 -1
- package/src/tmpclaude-4b63-cwd +0 -1
- package/src/tmpclaude-5c73-cwd +0 -1
- package/src/tmpclaude-5ee3-cwd +0 -1
- package/src/tmpclaude-6795-cwd +0 -1
- package/src/tmpclaude-709e-cwd +0 -1
- package/src/tmpclaude-9839-cwd +0 -1
- package/src/tmpclaude-d829-cwd +0 -1
- package/src/tmpclaude-e072-cwd +0 -1
- package/src/tmpclaude-f6ee-cwd +0 -1
- package/tmpclaude-0439-cwd +0 -1
- package/tmpclaude-132f-cwd +0 -1
- package/tmpclaude-15bb-cwd +0 -1
- package/tmpclaude-165a-cwd +0 -1
- package/tmpclaude-1ba9-cwd +0 -1
- package/tmpclaude-21a3-cwd +0 -1
- package/tmpclaude-2a38-cwd +0 -1
- package/tmpclaude-2adf-cwd +0 -1
- package/tmpclaude-2f56-cwd +0 -1
- package/tmpclaude-3626-cwd +0 -1
- package/tmpclaude-3727-cwd +0 -1
- package/tmpclaude-40bc-cwd +0 -1
- package/tmpclaude-436f-cwd +0 -1
- package/tmpclaude-4783-cwd +0 -1
- package/tmpclaude-4b6d-cwd +0 -1
- package/tmpclaude-4ba4-cwd +0 -1
- package/tmpclaude-51e6-cwd +0 -1
- package/tmpclaude-5ecf-cwd +0 -1
- package/tmpclaude-6f97-cwd +0 -1
- package/tmpclaude-7fb2-cwd +0 -1
- package/tmpclaude-825c-cwd +0 -1
- package/tmpclaude-8baf-cwd +0 -1
- package/tmpclaude-8d9f-cwd +0 -1
- package/tmpclaude-975c-cwd +0 -1
- package/tmpclaude-9983-cwd +0 -1
- package/tmpclaude-a045-cwd +0 -1
- package/tmpclaude-ac4a-cwd +0 -1
- package/tmpclaude-b593-cwd +0 -1
- package/tmpclaude-b891-cwd +0 -1
- package/tmpclaude-c032-cwd +0 -1
- package/tmpclaude-cf43-cwd +0 -1
- package/tmpclaude-d040-cwd +0 -1
- package/tmpclaude-dcdd-cwd +0 -1
- package/tmpclaude-dcee-cwd +0 -1
- package/tmpclaude-e16b-cwd +0 -1
- package/tmpclaude-ecd2-cwd +0 -1
- package/tmpclaude-f48d-cwd +0 -1
|
@@ -11,7 +11,10 @@ import {
|
|
|
11
11
|
deleteCostAlert,
|
|
12
12
|
getTaskCosts,
|
|
13
13
|
} from './cost.js';
|
|
14
|
-
import {
|
|
14
|
+
import { createMockContext } from './__test-utils__.js';
|
|
15
|
+
import { mockApiClient } from './__test-setup__.js';
|
|
16
|
+
|
|
17
|
+
const VALID_UUID = '123e4567-e89b-12d3-a456-426614174000';
|
|
15
18
|
|
|
16
19
|
describe('Cost Handlers', () => {
|
|
17
20
|
beforeEach(() => {
|
|
@@ -24,8 +27,7 @@ describe('Cost Handlers', () => {
|
|
|
24
27
|
|
|
25
28
|
describe('getCostSummary', () => {
|
|
26
29
|
it('should return error when project_id is missing', async () => {
|
|
27
|
-
const
|
|
28
|
-
const ctx = createMockContext(supabase);
|
|
30
|
+
const ctx = createMockContext();
|
|
29
31
|
|
|
30
32
|
const result = await getCostSummary({}, ctx);
|
|
31
33
|
|
|
@@ -50,13 +52,22 @@ describe('Cost Handlers', () => {
|
|
|
50
52
|
estimated_cost_usd: '0.30',
|
|
51
53
|
},
|
|
52
54
|
];
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
mockApiClient.getCostSummary.mockResolvedValue({
|
|
56
|
+
ok: true,
|
|
57
|
+
data: {
|
|
58
|
+
period: 'daily',
|
|
59
|
+
summary: mockData,
|
|
60
|
+
totals: {
|
|
61
|
+
sessions: 8,
|
|
62
|
+
tokens: 16000,
|
|
63
|
+
calls: 80,
|
|
64
|
+
cost: 0.8,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
56
67
|
});
|
|
57
|
-
const ctx = createMockContext(
|
|
68
|
+
const ctx = createMockContext();
|
|
58
69
|
|
|
59
|
-
const result = await getCostSummary({ project_id:
|
|
70
|
+
const result = await getCostSummary({ project_id: VALID_UUID }, ctx);
|
|
60
71
|
|
|
61
72
|
expect(result.isError).toBeUndefined();
|
|
62
73
|
expect(result.result.period).toBe('daily');
|
|
@@ -70,45 +81,54 @@ describe('Cost Handlers', () => {
|
|
|
70
81
|
});
|
|
71
82
|
|
|
72
83
|
it('should handle weekly period', async () => {
|
|
73
|
-
|
|
74
|
-
|
|
84
|
+
mockApiClient.getCostSummary.mockResolvedValue({
|
|
85
|
+
ok: true,
|
|
86
|
+
data: { period: 'weekly', summary: [], totals: { sessions: 0, tokens: 0, calls: 0, cost: 0 } },
|
|
75
87
|
});
|
|
76
|
-
const ctx = createMockContext(
|
|
88
|
+
const ctx = createMockContext();
|
|
77
89
|
|
|
78
90
|
const result = await getCostSummary(
|
|
79
|
-
{ project_id:
|
|
91
|
+
{ project_id: VALID_UUID, period: 'weekly' },
|
|
80
92
|
ctx
|
|
81
93
|
);
|
|
82
94
|
|
|
83
95
|
expect(result.result.period).toBe('weekly');
|
|
84
|
-
expect(
|
|
96
|
+
expect(mockApiClient.getCostSummary).toHaveBeenCalledWith(
|
|
97
|
+
VALID_UUID,
|
|
98
|
+
expect.objectContaining({ period: 'weekly' })
|
|
99
|
+
);
|
|
85
100
|
});
|
|
86
101
|
|
|
87
102
|
it('should handle monthly period', async () => {
|
|
88
|
-
|
|
89
|
-
|
|
103
|
+
mockApiClient.getCostSummary.mockResolvedValue({
|
|
104
|
+
ok: true,
|
|
105
|
+
data: { period: 'monthly', summary: [], totals: { sessions: 0, tokens: 0, calls: 0, cost: 0 } },
|
|
90
106
|
});
|
|
91
|
-
const ctx = createMockContext(
|
|
107
|
+
const ctx = createMockContext();
|
|
92
108
|
|
|
93
109
|
const result = await getCostSummary(
|
|
94
|
-
{ project_id:
|
|
110
|
+
{ project_id: VALID_UUID, period: 'monthly' },
|
|
95
111
|
ctx
|
|
96
112
|
);
|
|
97
113
|
|
|
98
114
|
expect(result.result.period).toBe('monthly');
|
|
99
|
-
expect(
|
|
115
|
+
expect(mockApiClient.getCostSummary).toHaveBeenCalledWith(
|
|
116
|
+
VALID_UUID,
|
|
117
|
+
expect.objectContaining({ period: 'monthly' })
|
|
118
|
+
);
|
|
100
119
|
});
|
|
101
120
|
|
|
102
|
-
it('should return error on
|
|
103
|
-
|
|
104
|
-
|
|
121
|
+
it('should return error on API failure', async () => {
|
|
122
|
+
mockApiClient.getCostSummary.mockResolvedValue({
|
|
123
|
+
ok: false,
|
|
124
|
+
error: 'Database error',
|
|
105
125
|
});
|
|
106
|
-
const ctx = createMockContext(
|
|
126
|
+
const ctx = createMockContext();
|
|
107
127
|
|
|
108
|
-
const result = await getCostSummary({ project_id:
|
|
128
|
+
const result = await getCostSummary({ project_id: VALID_UUID }, ctx);
|
|
109
129
|
|
|
110
130
|
expect(result.isError).toBe(true);
|
|
111
|
-
expect(result.result.error).
|
|
131
|
+
expect(result.result.error).toBe('Database error');
|
|
112
132
|
});
|
|
113
133
|
});
|
|
114
134
|
|
|
@@ -122,11 +142,11 @@ describe('Cost Handlers', () => {
|
|
|
122
142
|
{ id: 'alert-1', threshold_amount: 10, threshold_period: 'daily' },
|
|
123
143
|
{ id: 'alert-2', threshold_amount: 50, threshold_period: 'weekly' },
|
|
124
144
|
];
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
145
|
+
mockApiClient.getCostAlerts.mockResolvedValue({
|
|
146
|
+
ok: true,
|
|
147
|
+
data: { alerts: mockAlerts, count: 2 },
|
|
128
148
|
});
|
|
129
|
-
const ctx = createMockContext(
|
|
149
|
+
const ctx = createMockContext();
|
|
130
150
|
|
|
131
151
|
const result = await getCostAlerts({}, ctx);
|
|
132
152
|
|
|
@@ -134,27 +154,29 @@ describe('Cost Handlers', () => {
|
|
|
134
154
|
expect(result.result.count).toBe(2);
|
|
135
155
|
});
|
|
136
156
|
|
|
137
|
-
it('should
|
|
138
|
-
|
|
139
|
-
|
|
157
|
+
it('should call getCostAlerts with no args (project filtering done server-side)', async () => {
|
|
158
|
+
mockApiClient.getCostAlerts.mockResolvedValue({
|
|
159
|
+
ok: true,
|
|
160
|
+
data: { alerts: [], count: 0 },
|
|
140
161
|
});
|
|
141
|
-
const ctx = createMockContext(
|
|
162
|
+
const ctx = createMockContext();
|
|
142
163
|
|
|
143
|
-
await getCostAlerts({ project_id:
|
|
164
|
+
await getCostAlerts({ project_id: VALID_UUID }, ctx);
|
|
144
165
|
|
|
145
|
-
expect(
|
|
166
|
+
expect(mockApiClient.getCostAlerts).toHaveBeenCalledWith();
|
|
146
167
|
});
|
|
147
168
|
|
|
148
|
-
it('should return error on
|
|
149
|
-
|
|
150
|
-
|
|
169
|
+
it('should return error on API failure', async () => {
|
|
170
|
+
mockApiClient.getCostAlerts.mockResolvedValue({
|
|
171
|
+
ok: false,
|
|
172
|
+
error: 'Query failed',
|
|
151
173
|
});
|
|
152
|
-
const ctx = createMockContext(
|
|
174
|
+
const ctx = createMockContext();
|
|
153
175
|
|
|
154
176
|
const result = await getCostAlerts({}, ctx);
|
|
155
177
|
|
|
156
178
|
expect(result.isError).toBe(true);
|
|
157
|
-
expect(result.result.error).
|
|
179
|
+
expect(result.result.error).toBe('Query failed');
|
|
158
180
|
});
|
|
159
181
|
});
|
|
160
182
|
|
|
@@ -164,8 +186,7 @@ describe('Cost Handlers', () => {
|
|
|
164
186
|
|
|
165
187
|
describe('addCostAlert', () => {
|
|
166
188
|
it('should return error when threshold_amount is missing', async () => {
|
|
167
|
-
const
|
|
168
|
-
const ctx = createMockContext(supabase);
|
|
189
|
+
const ctx = createMockContext();
|
|
169
190
|
|
|
170
191
|
const result = await addCostAlert(
|
|
171
192
|
{ threshold_period: 'daily' },
|
|
@@ -177,8 +198,7 @@ describe('Cost Handlers', () => {
|
|
|
177
198
|
});
|
|
178
199
|
|
|
179
200
|
it('should return error when threshold_amount is not positive', async () => {
|
|
180
|
-
const
|
|
181
|
-
const ctx = createMockContext(supabase);
|
|
201
|
+
const ctx = createMockContext();
|
|
182
202
|
|
|
183
203
|
const result = await addCostAlert(
|
|
184
204
|
{ threshold_amount: -5, threshold_period: 'daily' },
|
|
@@ -190,8 +210,7 @@ describe('Cost Handlers', () => {
|
|
|
190
210
|
});
|
|
191
211
|
|
|
192
212
|
it('should return error when threshold_period is invalid', async () => {
|
|
193
|
-
const
|
|
194
|
-
const ctx = createMockContext(supabase);
|
|
213
|
+
const ctx = createMockContext();
|
|
195
214
|
|
|
196
215
|
const result = await addCostAlert(
|
|
197
216
|
{ threshold_amount: 10, threshold_period: 'yearly' },
|
|
@@ -209,11 +228,11 @@ describe('Cost Handlers', () => {
|
|
|
209
228
|
threshold_period: 'daily',
|
|
210
229
|
alert_type: 'warning',
|
|
211
230
|
};
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
231
|
+
mockApiClient.addCostAlert.mockResolvedValue({
|
|
232
|
+
ok: true,
|
|
233
|
+
data: { success: true, alert: mockAlert, message: 'Alert created' },
|
|
215
234
|
});
|
|
216
|
-
const ctx = createMockContext(
|
|
235
|
+
const ctx = createMockContext();
|
|
217
236
|
|
|
218
237
|
const result = await addCostAlert(
|
|
219
238
|
{ threshold_amount: 10, threshold_period: 'daily' },
|
|
@@ -226,32 +245,36 @@ describe('Cost Handlers', () => {
|
|
|
226
245
|
});
|
|
227
246
|
|
|
228
247
|
it('should create alert with project_id', async () => {
|
|
229
|
-
|
|
230
|
-
|
|
248
|
+
mockApiClient.addCostAlert.mockResolvedValue({
|
|
249
|
+
ok: true,
|
|
250
|
+
data: { success: true, alert: { id: 'new-alert' } },
|
|
231
251
|
});
|
|
232
|
-
const ctx = createMockContext(
|
|
252
|
+
const ctx = createMockContext();
|
|
233
253
|
|
|
234
254
|
await addCostAlert(
|
|
235
255
|
{
|
|
236
|
-
project_id:
|
|
256
|
+
project_id: VALID_UUID,
|
|
237
257
|
threshold_amount: 10,
|
|
238
258
|
threshold_period: 'daily',
|
|
239
259
|
},
|
|
240
260
|
ctx
|
|
241
261
|
);
|
|
242
262
|
|
|
243
|
-
expect(
|
|
263
|
+
expect(mockApiClient.addCostAlert).toHaveBeenCalledWith(
|
|
244
264
|
expect.objectContaining({
|
|
245
|
-
project_id:
|
|
265
|
+
project_id: VALID_UUID,
|
|
266
|
+
threshold_amount: 10,
|
|
267
|
+
threshold_period: 'daily',
|
|
246
268
|
})
|
|
247
269
|
);
|
|
248
270
|
});
|
|
249
271
|
|
|
250
|
-
it('should return error on
|
|
251
|
-
|
|
252
|
-
|
|
272
|
+
it('should return error on API failure', async () => {
|
|
273
|
+
mockApiClient.addCostAlert.mockResolvedValue({
|
|
274
|
+
ok: false,
|
|
275
|
+
error: 'Insert failed',
|
|
253
276
|
});
|
|
254
|
-
const ctx = createMockContext(
|
|
277
|
+
const ctx = createMockContext();
|
|
255
278
|
|
|
256
279
|
const result = await addCostAlert(
|
|
257
280
|
{ threshold_amount: 10, threshold_period: 'daily' },
|
|
@@ -259,7 +282,7 @@ describe('Cost Handlers', () => {
|
|
|
259
282
|
);
|
|
260
283
|
|
|
261
284
|
expect(result.isError).toBe(true);
|
|
262
|
-
expect(result.result.error).
|
|
285
|
+
expect(result.result.error).toBe('Insert failed');
|
|
263
286
|
});
|
|
264
287
|
});
|
|
265
288
|
|
|
@@ -269,8 +292,7 @@ describe('Cost Handlers', () => {
|
|
|
269
292
|
|
|
270
293
|
describe('updateCostAlert', () => {
|
|
271
294
|
it('should return error when alert_id is missing', async () => {
|
|
272
|
-
const
|
|
273
|
-
const ctx = createMockContext(supabase);
|
|
295
|
+
const ctx = createMockContext();
|
|
274
296
|
|
|
275
297
|
const result = await updateCostAlert({}, ctx);
|
|
276
298
|
|
|
@@ -279,10 +301,9 @@ describe('Cost Handlers', () => {
|
|
|
279
301
|
});
|
|
280
302
|
|
|
281
303
|
it('should return error when no updates provided', async () => {
|
|
282
|
-
const
|
|
283
|
-
const ctx = createMockContext(supabase);
|
|
304
|
+
const ctx = createMockContext();
|
|
284
305
|
|
|
285
|
-
const result = await updateCostAlert({ alert_id:
|
|
306
|
+
const result = await updateCostAlert({ alert_id: VALID_UUID }, ctx);
|
|
286
307
|
|
|
287
308
|
expect(result.isError).toBe(true);
|
|
288
309
|
expect(result.result.error).toBe('No updates provided');
|
|
@@ -290,18 +311,18 @@ describe('Cost Handlers', () => {
|
|
|
290
311
|
|
|
291
312
|
it('should update alert successfully', async () => {
|
|
292
313
|
const mockUpdatedAlert = {
|
|
293
|
-
id:
|
|
314
|
+
id: VALID_UUID,
|
|
294
315
|
threshold_amount: 20,
|
|
295
316
|
threshold_period: 'weekly',
|
|
296
317
|
};
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
318
|
+
mockApiClient.updateCostAlert.mockResolvedValue({
|
|
319
|
+
ok: true,
|
|
320
|
+
data: { success: true, alert: mockUpdatedAlert },
|
|
300
321
|
});
|
|
301
|
-
const ctx = createMockContext(
|
|
322
|
+
const ctx = createMockContext();
|
|
302
323
|
|
|
303
324
|
const result = await updateCostAlert(
|
|
304
|
-
{ alert_id:
|
|
325
|
+
{ alert_id: VALID_UUID, threshold_amount: 20 },
|
|
305
326
|
ctx
|
|
306
327
|
);
|
|
307
328
|
|
|
@@ -310,29 +331,34 @@ describe('Cost Handlers', () => {
|
|
|
310
331
|
});
|
|
311
332
|
|
|
312
333
|
it('should update enabled status', async () => {
|
|
313
|
-
|
|
314
|
-
|
|
334
|
+
mockApiClient.updateCostAlert.mockResolvedValue({
|
|
335
|
+
ok: true,
|
|
336
|
+
data: { success: true, alert: { id: VALID_UUID, enabled: false } },
|
|
315
337
|
});
|
|
316
|
-
const ctx = createMockContext(
|
|
338
|
+
const ctx = createMockContext();
|
|
317
339
|
|
|
318
|
-
await updateCostAlert({ alert_id:
|
|
340
|
+
await updateCostAlert({ alert_id: VALID_UUID, enabled: false }, ctx);
|
|
319
341
|
|
|
320
|
-
expect(
|
|
342
|
+
expect(mockApiClient.updateCostAlert).toHaveBeenCalledWith(
|
|
343
|
+
VALID_UUID,
|
|
344
|
+
expect.objectContaining({ enabled: false })
|
|
345
|
+
);
|
|
321
346
|
});
|
|
322
347
|
|
|
323
|
-
it('should return error on
|
|
324
|
-
|
|
325
|
-
|
|
348
|
+
it('should return error on API failure', async () => {
|
|
349
|
+
mockApiClient.updateCostAlert.mockResolvedValue({
|
|
350
|
+
ok: false,
|
|
351
|
+
error: 'Update failed',
|
|
326
352
|
});
|
|
327
|
-
const ctx = createMockContext(
|
|
353
|
+
const ctx = createMockContext();
|
|
328
354
|
|
|
329
355
|
const result = await updateCostAlert(
|
|
330
|
-
{ alert_id:
|
|
356
|
+
{ alert_id: VALID_UUID, threshold_amount: 20 },
|
|
331
357
|
ctx
|
|
332
358
|
);
|
|
333
359
|
|
|
334
360
|
expect(result.isError).toBe(true);
|
|
335
|
-
expect(result.result.error).
|
|
361
|
+
expect(result.result.error).toBe('Update failed');
|
|
336
362
|
});
|
|
337
363
|
});
|
|
338
364
|
|
|
@@ -342,8 +368,7 @@ describe('Cost Handlers', () => {
|
|
|
342
368
|
|
|
343
369
|
describe('deleteCostAlert', () => {
|
|
344
370
|
it('should return error when alert_id is missing', async () => {
|
|
345
|
-
const
|
|
346
|
-
const ctx = createMockContext(supabase);
|
|
371
|
+
const ctx = createMockContext();
|
|
347
372
|
|
|
348
373
|
const result = await deleteCostAlert({}, ctx);
|
|
349
374
|
|
|
@@ -352,27 +377,29 @@ describe('Cost Handlers', () => {
|
|
|
352
377
|
});
|
|
353
378
|
|
|
354
379
|
it('should delete alert successfully', async () => {
|
|
355
|
-
|
|
356
|
-
|
|
380
|
+
mockApiClient.deleteCostAlert.mockResolvedValue({
|
|
381
|
+
ok: true,
|
|
382
|
+
data: { success: true, deleted_alert_id: VALID_UUID },
|
|
357
383
|
});
|
|
358
|
-
const ctx = createMockContext(
|
|
384
|
+
const ctx = createMockContext();
|
|
359
385
|
|
|
360
|
-
const result = await deleteCostAlert({ alert_id:
|
|
386
|
+
const result = await deleteCostAlert({ alert_id: VALID_UUID }, ctx);
|
|
361
387
|
|
|
362
388
|
expect(result.result.success).toBe(true);
|
|
363
|
-
expect(result.result.deleted_alert_id).toBe(
|
|
389
|
+
expect(result.result.deleted_alert_id).toBe(VALID_UUID);
|
|
364
390
|
});
|
|
365
391
|
|
|
366
|
-
it('should return error on
|
|
367
|
-
|
|
368
|
-
|
|
392
|
+
it('should return error on API failure', async () => {
|
|
393
|
+
mockApiClient.deleteCostAlert.mockResolvedValue({
|
|
394
|
+
ok: false,
|
|
395
|
+
error: 'Delete failed',
|
|
369
396
|
});
|
|
370
|
-
const ctx = createMockContext(
|
|
397
|
+
const ctx = createMockContext();
|
|
371
398
|
|
|
372
|
-
const result = await deleteCostAlert({ alert_id:
|
|
399
|
+
const result = await deleteCostAlert({ alert_id: VALID_UUID }, ctx);
|
|
373
400
|
|
|
374
401
|
expect(result.isError).toBe(true);
|
|
375
|
-
expect(result.result.error).
|
|
402
|
+
expect(result.result.error).toBe('Delete failed');
|
|
376
403
|
});
|
|
377
404
|
});
|
|
378
405
|
|
|
@@ -382,8 +409,7 @@ describe('Cost Handlers', () => {
|
|
|
382
409
|
|
|
383
410
|
describe('getTaskCosts', () => {
|
|
384
411
|
it('should return error when project_id is missing', async () => {
|
|
385
|
-
const
|
|
386
|
-
const ctx = createMockContext(supabase);
|
|
412
|
+
const ctx = createMockContext();
|
|
387
413
|
|
|
388
414
|
const result = await getTaskCosts({}, ctx);
|
|
389
415
|
|
|
@@ -396,41 +422,51 @@ describe('Cost Handlers', () => {
|
|
|
396
422
|
{ id: 'task-1', title: 'Task 1', estimated_cost_usd: '0.50' },
|
|
397
423
|
{ id: 'task-2', title: 'Task 2', estimated_cost_usd: '0.30' },
|
|
398
424
|
];
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
425
|
+
mockApiClient.getTaskCosts.mockResolvedValue({
|
|
426
|
+
ok: true,
|
|
427
|
+
data: {
|
|
428
|
+
project_id: VALID_UUID,
|
|
429
|
+
tasks: mockTasks,
|
|
430
|
+
total_cost_usd: 0.8,
|
|
431
|
+
},
|
|
402
432
|
});
|
|
403
|
-
const ctx = createMockContext(
|
|
433
|
+
const ctx = createMockContext();
|
|
404
434
|
|
|
405
|
-
const result = await getTaskCosts({ project_id:
|
|
435
|
+
const result = await getTaskCosts({ project_id: VALID_UUID }, ctx);
|
|
406
436
|
|
|
407
|
-
expect(result.result.project_id).toBe(
|
|
437
|
+
expect(result.result.project_id).toBe(VALID_UUID);
|
|
408
438
|
expect(result.result.tasks).toEqual(mockTasks);
|
|
409
439
|
expect(result.result.total_cost_usd).toBe(0.8);
|
|
410
440
|
});
|
|
411
441
|
|
|
412
442
|
it('should handle empty task list', async () => {
|
|
413
|
-
|
|
414
|
-
|
|
443
|
+
mockApiClient.getTaskCosts.mockResolvedValue({
|
|
444
|
+
ok: true,
|
|
445
|
+
data: {
|
|
446
|
+
project_id: VALID_UUID,
|
|
447
|
+
tasks: [],
|
|
448
|
+
total_cost_usd: 0,
|
|
449
|
+
},
|
|
415
450
|
});
|
|
416
|
-
const ctx = createMockContext(
|
|
451
|
+
const ctx = createMockContext();
|
|
417
452
|
|
|
418
|
-
const result = await getTaskCosts({ project_id:
|
|
453
|
+
const result = await getTaskCosts({ project_id: VALID_UUID }, ctx);
|
|
419
454
|
|
|
420
455
|
expect(result.result.tasks).toEqual([]);
|
|
421
456
|
expect(result.result.total_cost_usd).toBe(0);
|
|
422
457
|
});
|
|
423
458
|
|
|
424
|
-
it('should return error on
|
|
425
|
-
|
|
426
|
-
|
|
459
|
+
it('should return error on API failure', async () => {
|
|
460
|
+
mockApiClient.getTaskCosts.mockResolvedValue({
|
|
461
|
+
ok: false,
|
|
462
|
+
error: 'Query failed',
|
|
427
463
|
});
|
|
428
|
-
const ctx = createMockContext(
|
|
464
|
+
const ctx = createMockContext();
|
|
429
465
|
|
|
430
|
-
const result = await getTaskCosts({ project_id:
|
|
466
|
+
const result = await getTaskCosts({ project_id: VALID_UUID }, ctx);
|
|
431
467
|
|
|
432
468
|
expect(result.isError).toBe(true);
|
|
433
|
-
expect(result.result.error).
|
|
469
|
+
expect(result.result.error).toBe('Query failed');
|
|
434
470
|
});
|
|
435
471
|
});
|
|
436
472
|
});
|