@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.
Files changed (170) hide show
  1. package/README.md +113 -98
  2. package/dist/api-client.d.ts +1114 -0
  3. package/dist/api-client.js +698 -0
  4. package/dist/cli.d.ts +1 -6
  5. package/dist/cli.js +39 -240
  6. package/dist/config/tool-categories.d.ts +31 -0
  7. package/dist/config/tool-categories.js +253 -0
  8. package/dist/handlers/blockers.js +57 -58
  9. package/dist/handlers/bodies-of-work.d.ts +2 -0
  10. package/dist/handlers/bodies-of-work.js +106 -476
  11. package/dist/handlers/cost.d.ts +1 -0
  12. package/dist/handlers/cost.js +35 -113
  13. package/dist/handlers/decisions.d.ts +2 -0
  14. package/dist/handlers/decisions.js +28 -27
  15. package/dist/handlers/deployment.js +112 -828
  16. package/dist/handlers/discovery.js +31 -0
  17. package/dist/handlers/fallback.d.ts +2 -0
  18. package/dist/handlers/fallback.js +39 -134
  19. package/dist/handlers/findings.js +43 -67
  20. package/dist/handlers/git-issues.d.ts +9 -13
  21. package/dist/handlers/git-issues.js +80 -225
  22. package/dist/handlers/ideas.d.ts +3 -0
  23. package/dist/handlers/ideas.js +53 -134
  24. package/dist/handlers/index.d.ts +2 -0
  25. package/dist/handlers/index.js +6 -0
  26. package/dist/handlers/milestones.d.ts +2 -0
  27. package/dist/handlers/milestones.js +51 -98
  28. package/dist/handlers/organizations.js +79 -275
  29. package/dist/handlers/progress.d.ts +2 -0
  30. package/dist/handlers/progress.js +25 -123
  31. package/dist/handlers/project.js +42 -221
  32. package/dist/handlers/requests.d.ts +2 -0
  33. package/dist/handlers/requests.js +23 -83
  34. package/dist/handlers/session.js +99 -585
  35. package/dist/handlers/sprints.d.ts +32 -0
  36. package/dist/handlers/sprints.js +274 -0
  37. package/dist/handlers/tasks.d.ts +7 -10
  38. package/dist/handlers/tasks.js +230 -900
  39. package/dist/handlers/tool-docs.d.ts +8 -0
  40. package/dist/handlers/tool-docs.js +657 -0
  41. package/dist/handlers/types.d.ts +11 -3
  42. package/dist/handlers/validation.d.ts +1 -1
  43. package/dist/handlers/validation.js +26 -153
  44. package/dist/index.js +473 -160
  45. package/dist/knowledge.js +106 -9
  46. package/dist/tools.js +4 -0
  47. package/dist/validators.d.ts +21 -0
  48. package/dist/validators.js +91 -0
  49. package/package.json +2 -3
  50. package/src/api-client.ts +1752 -0
  51. package/src/cli.test.ts +128 -302
  52. package/src/cli.ts +41 -285
  53. package/src/handlers/__test-setup__.ts +210 -0
  54. package/src/handlers/__test-utils__.ts +4 -134
  55. package/src/handlers/blockers.test.ts +114 -124
  56. package/src/handlers/blockers.ts +68 -70
  57. package/src/handlers/bodies-of-work.test.ts +236 -831
  58. package/src/handlers/bodies-of-work.ts +194 -525
  59. package/src/handlers/cost.test.ts +149 -113
  60. package/src/handlers/cost.ts +44 -132
  61. package/src/handlers/decisions.test.ts +111 -209
  62. package/src/handlers/decisions.ts +35 -27
  63. package/src/handlers/deployment.test.ts +193 -239
  64. package/src/handlers/deployment.ts +140 -895
  65. package/src/handlers/discovery.test.ts +20 -67
  66. package/src/handlers/discovery.ts +32 -0
  67. package/src/handlers/fallback.test.ts +128 -361
  68. package/src/handlers/fallback.ts +62 -148
  69. package/src/handlers/findings.test.ts +127 -345
  70. package/src/handlers/findings.ts +49 -66
  71. package/src/handlers/git-issues.test.ts +623 -0
  72. package/src/handlers/git-issues.ts +174 -0
  73. package/src/handlers/ideas.test.ts +229 -343
  74. package/src/handlers/ideas.ts +69 -143
  75. package/src/handlers/index.ts +6 -0
  76. package/src/handlers/milestones.test.ts +167 -281
  77. package/src/handlers/milestones.ts +54 -93
  78. package/src/handlers/organizations.test.ts +275 -467
  79. package/src/handlers/organizations.ts +84 -294
  80. package/src/handlers/progress.test.ts +112 -218
  81. package/src/handlers/progress.ts +29 -142
  82. package/src/handlers/project.test.ts +203 -226
  83. package/src/handlers/project.ts +48 -238
  84. package/src/handlers/requests.test.ts +74 -342
  85. package/src/handlers/requests.ts +25 -83
  86. package/src/handlers/session.test.ts +241 -206
  87. package/src/handlers/session.ts +110 -657
  88. package/src/handlers/sprints.test.ts +711 -0
  89. package/src/handlers/sprints.ts +497 -0
  90. package/src/handlers/tasks.test.ts +608 -353
  91. package/src/handlers/tasks.ts +248 -1025
  92. package/src/handlers/types.ts +12 -4
  93. package/src/handlers/validation.test.ts +189 -572
  94. package/src/handlers/validation.ts +29 -166
  95. package/src/index.ts +473 -184
  96. package/src/knowledge.ts +107 -9
  97. package/src/tools.ts +2506 -0
  98. package/src/validators.test.ts +223 -223
  99. package/src/validators.ts +127 -0
  100. package/tsconfig.json +1 -1
  101. package/vitest.config.ts +14 -13
  102. package/dist/cli.test.d.ts +0 -1
  103. package/dist/cli.test.js +0 -367
  104. package/dist/handlers/__test-utils__.d.ts +0 -72
  105. package/dist/handlers/__test-utils__.js +0 -176
  106. package/dist/handlers/checkouts.d.ts +0 -37
  107. package/dist/handlers/checkouts.js +0 -377
  108. package/dist/handlers/knowledge-query.d.ts +0 -22
  109. package/dist/handlers/knowledge-query.js +0 -253
  110. package/dist/handlers/knowledge.d.ts +0 -12
  111. package/dist/handlers/knowledge.js +0 -108
  112. package/dist/handlers/roles.d.ts +0 -30
  113. package/dist/handlers/roles.js +0 -281
  114. package/dist/handlers/tasks.test.d.ts +0 -1
  115. package/dist/handlers/tasks.test.js +0 -431
  116. package/dist/utils.test.d.ts +0 -1
  117. package/dist/utils.test.js +0 -532
  118. package/dist/validators.test.d.ts +0 -1
  119. package/dist/validators.test.js +0 -176
  120. package/src/tmpclaude-0078-cwd +0 -1
  121. package/src/tmpclaude-0ee1-cwd +0 -1
  122. package/src/tmpclaude-2dd5-cwd +0 -1
  123. package/src/tmpclaude-344c-cwd +0 -1
  124. package/src/tmpclaude-3860-cwd +0 -1
  125. package/src/tmpclaude-4b63-cwd +0 -1
  126. package/src/tmpclaude-5c73-cwd +0 -1
  127. package/src/tmpclaude-5ee3-cwd +0 -1
  128. package/src/tmpclaude-6795-cwd +0 -1
  129. package/src/tmpclaude-709e-cwd +0 -1
  130. package/src/tmpclaude-9839-cwd +0 -1
  131. package/src/tmpclaude-d829-cwd +0 -1
  132. package/src/tmpclaude-e072-cwd +0 -1
  133. package/src/tmpclaude-f6ee-cwd +0 -1
  134. package/tmpclaude-0439-cwd +0 -1
  135. package/tmpclaude-132f-cwd +0 -1
  136. package/tmpclaude-15bb-cwd +0 -1
  137. package/tmpclaude-165a-cwd +0 -1
  138. package/tmpclaude-1ba9-cwd +0 -1
  139. package/tmpclaude-21a3-cwd +0 -1
  140. package/tmpclaude-2a38-cwd +0 -1
  141. package/tmpclaude-2adf-cwd +0 -1
  142. package/tmpclaude-2f56-cwd +0 -1
  143. package/tmpclaude-3626-cwd +0 -1
  144. package/tmpclaude-3727-cwd +0 -1
  145. package/tmpclaude-40bc-cwd +0 -1
  146. package/tmpclaude-436f-cwd +0 -1
  147. package/tmpclaude-4783-cwd +0 -1
  148. package/tmpclaude-4b6d-cwd +0 -1
  149. package/tmpclaude-4ba4-cwd +0 -1
  150. package/tmpclaude-51e6-cwd +0 -1
  151. package/tmpclaude-5ecf-cwd +0 -1
  152. package/tmpclaude-6f97-cwd +0 -1
  153. package/tmpclaude-7fb2-cwd +0 -1
  154. package/tmpclaude-825c-cwd +0 -1
  155. package/tmpclaude-8baf-cwd +0 -1
  156. package/tmpclaude-8d9f-cwd +0 -1
  157. package/tmpclaude-975c-cwd +0 -1
  158. package/tmpclaude-9983-cwd +0 -1
  159. package/tmpclaude-a045-cwd +0 -1
  160. package/tmpclaude-ac4a-cwd +0 -1
  161. package/tmpclaude-b593-cwd +0 -1
  162. package/tmpclaude-b891-cwd +0 -1
  163. package/tmpclaude-c032-cwd +0 -1
  164. package/tmpclaude-cf43-cwd +0 -1
  165. package/tmpclaude-d040-cwd +0 -1
  166. package/tmpclaude-dcdd-cwd +0 -1
  167. package/tmpclaude-dcee-cwd +0 -1
  168. package/tmpclaude-e16b-cwd +0 -1
  169. package/tmpclaude-ecd2-cwd +0 -1
  170. package/tmpclaude-f48d-cwd +0 -1
@@ -1,431 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import { getTasks, addTask, updateTask, completeTask, deleteTask, addTaskReference, removeTaskReference, getProjectGitConfig, } from './tasks.js';
3
- import { ValidationError } from '../validators.js';
4
- // ============================================================================
5
- // Test Utilities
6
- // ============================================================================
7
- /**
8
- * Creates a mock Supabase client with chainable methods
9
- */
10
- function createMockSupabase(overrides = {}) {
11
- const defaultResult = { data: null, error: null };
12
- // Track both the operation type AND if insert has been followed by select
13
- let currentOperation = 'select';
14
- let insertThenSelect = false;
15
- const mock = {
16
- from: vi.fn().mockReturnThis(),
17
- select: vi.fn(() => {
18
- // If we just did an insert and now calling select, it's insert().select() chain
19
- if (currentOperation === 'insert') {
20
- insertThenSelect = true;
21
- }
22
- else {
23
- currentOperation = 'select';
24
- insertThenSelect = false;
25
- }
26
- return mock;
27
- }),
28
- insert: vi.fn(() => {
29
- currentOperation = 'insert';
30
- insertThenSelect = false;
31
- return mock;
32
- }),
33
- update: vi.fn(() => {
34
- currentOperation = 'update';
35
- insertThenSelect = false;
36
- return mock;
37
- }),
38
- delete: vi.fn(() => {
39
- currentOperation = 'delete';
40
- insertThenSelect = false;
41
- return mock;
42
- }),
43
- eq: vi.fn().mockReturnThis(),
44
- neq: vi.fn().mockReturnThis(),
45
- in: vi.fn().mockReturnThis(),
46
- is: vi.fn().mockReturnThis(),
47
- not: vi.fn().mockReturnThis(),
48
- or: vi.fn().mockReturnThis(),
49
- lt: vi.fn().mockReturnThis(),
50
- order: vi.fn().mockReturnThis(),
51
- limit: vi.fn().mockReturnThis(),
52
- single: vi.fn(() => {
53
- // Handle insert().select().single() pattern
54
- if (currentOperation === 'insert' || insertThenSelect) {
55
- return Promise.resolve(overrides.insertResult ?? defaultResult);
56
- }
57
- if (currentOperation === 'select') {
58
- return Promise.resolve(overrides.selectResult ?? defaultResult);
59
- }
60
- if (currentOperation === 'update') {
61
- return Promise.resolve(overrides.updateResult ?? defaultResult);
62
- }
63
- return Promise.resolve(defaultResult);
64
- }),
65
- maybeSingle: vi.fn(() => {
66
- return Promise.resolve(overrides.selectResult ?? defaultResult);
67
- }),
68
- then: vi.fn((resolve) => {
69
- if (currentOperation === 'insert' || insertThenSelect) {
70
- return Promise.resolve(overrides.insertResult ?? defaultResult).then(resolve);
71
- }
72
- if (currentOperation === 'select') {
73
- return Promise.resolve(overrides.selectResult ?? defaultResult).then(resolve);
74
- }
75
- if (currentOperation === 'update') {
76
- return Promise.resolve(overrides.updateResult ?? defaultResult).then(resolve);
77
- }
78
- if (currentOperation === 'delete') {
79
- return Promise.resolve(overrides.deleteResult ?? defaultResult).then(resolve);
80
- }
81
- return Promise.resolve(defaultResult).then(resolve);
82
- }),
83
- };
84
- return mock;
85
- }
86
- /**
87
- * Creates a mock handler context
88
- */
89
- function createMockContext(supabase, sessionId = 'session-123') {
90
- return {
91
- supabase,
92
- auth: {
93
- userId: 'user-123',
94
- apiKeyId: 'api-key-123',
95
- },
96
- session: {
97
- currentSessionId: sessionId,
98
- },
99
- };
100
- }
101
- // ============================================================================
102
- // getTasks Tests
103
- // ============================================================================
104
- describe('getTasks', () => {
105
- beforeEach(() => {
106
- vi.clearAllMocks();
107
- });
108
- it('should return tasks for a valid project', async () => {
109
- const mockTasks = [
110
- { id: 'task-1', title: 'Task 1', status: 'pending', priority: 1 },
111
- { id: 'task-2', title: 'Task 2', status: 'in_progress', priority: 2 },
112
- ];
113
- const supabase = createMockSupabase({
114
- selectResult: { data: mockTasks, error: null },
115
- });
116
- const ctx = createMockContext(supabase);
117
- const result = await getTasks({ project_id: '123e4567-e89b-12d3-a456-426614174000' }, ctx);
118
- expect(result.result.tasks).toEqual(mockTasks);
119
- expect(supabase.from).toHaveBeenCalledWith('tasks');
120
- });
121
- it('should throw error for missing project_id', async () => {
122
- const supabase = createMockSupabase();
123
- const ctx = createMockContext(supabase);
124
- await expect(getTasks({}, ctx)).rejects.toThrow(ValidationError);
125
- });
126
- it('should throw error for invalid project_id UUID', async () => {
127
- const supabase = createMockSupabase();
128
- const ctx = createMockContext(supabase);
129
- await expect(getTasks({ project_id: 'not-a-uuid' }, ctx)).rejects.toThrow(ValidationError);
130
- });
131
- it('should filter by status when provided', async () => {
132
- const mockTasks = [{ id: 'task-1', title: 'Task 1', status: 'pending', priority: 1 }];
133
- const supabase = createMockSupabase({
134
- selectResult: { data: mockTasks, error: null },
135
- });
136
- const ctx = createMockContext(supabase);
137
- await getTasks({ project_id: '123e4567-e89b-12d3-a456-426614174000', status: 'pending' }, ctx);
138
- expect(supabase.eq).toHaveBeenCalledWith('status', 'pending');
139
- });
140
- it('should throw error for invalid status', async () => {
141
- const supabase = createMockSupabase();
142
- const ctx = createMockContext(supabase);
143
- await expect(getTasks({ project_id: '123e4567-e89b-12d3-a456-426614174000', status: 'invalid' }, ctx)).rejects.toThrow(ValidationError);
144
- });
145
- it('should handle database errors', async () => {
146
- const supabase = createMockSupabase({
147
- selectResult: { data: null, error: { message: 'Database error' } },
148
- });
149
- const ctx = createMockContext(supabase);
150
- // The handler uses .then() pattern, so we need to adjust the mock
151
- vi.mocked(supabase.from('tasks').select).mockReturnValue({
152
- ...supabase,
153
- then: (resolve) => Promise.resolve({ data: null, error: { message: 'Database error' } }).then(resolve),
154
- });
155
- await expect(getTasks({ project_id: '123e4567-e89b-12d3-a456-426614174000' }, ctx)).rejects.toThrow('Failed to fetch tasks');
156
- });
157
- });
158
- // ============================================================================
159
- // addTask Tests
160
- // ============================================================================
161
- describe('addTask', () => {
162
- beforeEach(() => {
163
- vi.clearAllMocks();
164
- });
165
- it('should add a task successfully', async () => {
166
- const supabase = createMockSupabase({
167
- insertResult: { data: { id: 'new-task-123', blocking: false }, error: null },
168
- });
169
- const ctx = createMockContext(supabase);
170
- const result = await addTask({
171
- project_id: '123e4567-e89b-12d3-a456-426614174000',
172
- title: 'New Task',
173
- description: 'Task description',
174
- priority: 2,
175
- }, ctx);
176
- expect(result.result.success).toBe(true);
177
- expect(result.result.task_id).toBe('new-task-123');
178
- expect(result.result.title).toBe('New Task');
179
- expect(supabase.from).toHaveBeenCalledWith('tasks');
180
- expect(supabase.insert).toHaveBeenCalled();
181
- });
182
- it('should throw error for missing project_id', async () => {
183
- const supabase = createMockSupabase();
184
- const ctx = createMockContext(supabase);
185
- await expect(addTask({ title: 'Test' }, ctx)).rejects.toThrow(ValidationError);
186
- });
187
- it('should throw error for missing title', async () => {
188
- const supabase = createMockSupabase();
189
- const ctx = createMockContext(supabase);
190
- await expect(addTask({ project_id: '123e4567-e89b-12d3-a456-426614174000' }, ctx)).rejects.toThrow(ValidationError);
191
- });
192
- it('should throw error for invalid priority', async () => {
193
- const supabase = createMockSupabase();
194
- const ctx = createMockContext(supabase);
195
- await expect(addTask({
196
- project_id: '123e4567-e89b-12d3-a456-426614174000',
197
- title: 'Test',
198
- priority: 10, // Invalid: should be 1-5
199
- }, ctx)).rejects.toThrow(ValidationError);
200
- });
201
- it('should throw error for invalid estimated_minutes', async () => {
202
- const supabase = createMockSupabase();
203
- const ctx = createMockContext(supabase);
204
- await expect(addTask({
205
- project_id: '123e4567-e89b-12d3-a456-426614174000',
206
- title: 'Test',
207
- estimated_minutes: 0, // Invalid: must be positive
208
- }, ctx)).rejects.toThrow(ValidationError);
209
- });
210
- it('should include blocking message for blocking tasks', async () => {
211
- const supabase = createMockSupabase({
212
- insertResult: { data: { id: 'blocking-task', blocking: true }, error: null },
213
- });
214
- const ctx = createMockContext(supabase);
215
- const result = await addTask({
216
- project_id: '123e4567-e89b-12d3-a456-426614174000',
217
- title: 'Blocking Task',
218
- blocking: true,
219
- }, ctx);
220
- expect(result.result.blocking).toBe(true);
221
- expect(result.result.message).toContain('BLOCKING TASK');
222
- });
223
- it('should use default priority when not provided', async () => {
224
- const supabase = createMockSupabase({
225
- insertResult: { data: { id: 'task-1', blocking: false }, error: null },
226
- });
227
- const ctx = createMockContext(supabase);
228
- await addTask({
229
- project_id: '123e4567-e89b-12d3-a456-426614174000',
230
- title: 'Test',
231
- }, ctx);
232
- // Check that insert was called with priority: 3 (default)
233
- expect(supabase.insert).toHaveBeenCalledWith(expect.objectContaining({ priority: 3 }));
234
- });
235
- });
236
- // ============================================================================
237
- // deleteTask Tests
238
- // ============================================================================
239
- describe('deleteTask', () => {
240
- beforeEach(() => {
241
- vi.clearAllMocks();
242
- });
243
- it('should delete a task successfully', async () => {
244
- const supabase = createMockSupabase({
245
- deleteResult: { data: null, error: null },
246
- });
247
- const ctx = createMockContext(supabase);
248
- const result = await deleteTask({ task_id: '123e4567-e89b-12d3-a456-426614174000' }, ctx);
249
- expect(result.result.success).toBe(true);
250
- expect(result.result.deleted_id).toBe('123e4567-e89b-12d3-a456-426614174000');
251
- expect(supabase.from).toHaveBeenCalledWith('tasks');
252
- expect(supabase.delete).toHaveBeenCalled();
253
- });
254
- it('should throw error for missing task_id', async () => {
255
- const supabase = createMockSupabase();
256
- const ctx = createMockContext(supabase);
257
- await expect(deleteTask({}, ctx)).rejects.toThrow(ValidationError);
258
- });
259
- it('should throw error for invalid task_id UUID', async () => {
260
- const supabase = createMockSupabase();
261
- const ctx = createMockContext(supabase);
262
- await expect(deleteTask({ task_id: 'invalid' }, ctx)).rejects.toThrow(ValidationError);
263
- });
264
- });
265
- // ============================================================================
266
- // addTaskReference Tests
267
- // ============================================================================
268
- describe('addTaskReference', () => {
269
- beforeEach(() => {
270
- vi.clearAllMocks();
271
- });
272
- it('should add a reference successfully', async () => {
273
- const supabase = createMockSupabase({
274
- selectResult: { data: { references: [] }, error: null },
275
- updateResult: { data: null, error: null },
276
- });
277
- const ctx = createMockContext(supabase);
278
- const result = await addTaskReference({
279
- task_id: '123e4567-e89b-12d3-a456-426614174000',
280
- url: 'https://github.com/user/repo/pull/123',
281
- label: 'PR #123',
282
- }, ctx);
283
- expect(result.result.success).toBe(true);
284
- expect(result.result.reference).toEqual({
285
- url: 'https://github.com/user/repo/pull/123',
286
- label: 'PR #123',
287
- });
288
- expect(result.result.total_references).toBe(1);
289
- });
290
- it('should throw error for missing task_id', async () => {
291
- const supabase = createMockSupabase();
292
- const ctx = createMockContext(supabase);
293
- await expect(addTaskReference({ url: 'https://example.com' }, ctx)).rejects.toThrow(ValidationError);
294
- });
295
- it('should throw error for missing url', async () => {
296
- const supabase = createMockSupabase();
297
- const ctx = createMockContext(supabase);
298
- await expect(addTaskReference({ task_id: '123e4567-e89b-12d3-a456-426614174000' }, ctx)).rejects.toThrow(ValidationError);
299
- });
300
- it('should reject duplicate URL', async () => {
301
- const existingRef = { url: 'https://example.com', label: 'Existing' };
302
- const supabase = createMockSupabase({
303
- selectResult: { data: { references: [existingRef] }, error: null },
304
- });
305
- const ctx = createMockContext(supabase);
306
- const result = await addTaskReference({
307
- task_id: '123e4567-e89b-12d3-a456-426614174000',
308
- url: 'https://example.com',
309
- }, ctx);
310
- expect(result.result.success).toBe(false);
311
- expect(result.result.error).toContain('already exists');
312
- });
313
- });
314
- // ============================================================================
315
- // removeTaskReference Tests
316
- // ============================================================================
317
- describe('removeTaskReference', () => {
318
- beforeEach(() => {
319
- vi.clearAllMocks();
320
- });
321
- it('should remove a reference successfully', async () => {
322
- const existingRef = { url: 'https://example.com', label: 'Test' };
323
- const supabase = createMockSupabase({
324
- selectResult: { data: { references: [existingRef] }, error: null },
325
- updateResult: { data: null, error: null },
326
- });
327
- const ctx = createMockContext(supabase);
328
- const result = await removeTaskReference({
329
- task_id: '123e4567-e89b-12d3-a456-426614174000',
330
- url: 'https://example.com',
331
- }, ctx);
332
- expect(result.result.success).toBe(true);
333
- expect(result.result.remaining_references).toBe(0);
334
- });
335
- it('should return error when URL not found', async () => {
336
- const supabase = createMockSupabase({
337
- selectResult: { data: { references: [] }, error: null },
338
- });
339
- const ctx = createMockContext(supabase);
340
- const result = await removeTaskReference({
341
- task_id: '123e4567-e89b-12d3-a456-426614174000',
342
- url: 'https://nonexistent.com',
343
- }, ctx);
344
- expect(result.result.success).toBe(false);
345
- expect(result.result.error).toContain('not found');
346
- });
347
- });
348
- // ============================================================================
349
- // getProjectGitConfig Tests
350
- // ============================================================================
351
- describe('getProjectGitConfig', () => {
352
- it('should return git config for a project', async () => {
353
- const mockConfig = {
354
- git_workflow: 'github-flow',
355
- git_main_branch: 'main',
356
- git_develop_branch: null,
357
- git_auto_branch: true,
358
- };
359
- const supabase = createMockSupabase({
360
- selectResult: { data: mockConfig, error: null },
361
- });
362
- const result = await getProjectGitConfig(supabase, '123e4567-e89b-12d3-a456-426614174000');
363
- expect(result).toEqual(mockConfig);
364
- expect(supabase.from).toHaveBeenCalledWith('projects');
365
- });
366
- it('should return null when project not found', async () => {
367
- const supabase = createMockSupabase({
368
- selectResult: { data: null, error: { message: 'Not found' } },
369
- });
370
- const result = await getProjectGitConfig(supabase, '123e4567-e89b-12d3-a456-426614174000');
371
- expect(result).toBeNull();
372
- });
373
- });
374
- // ============================================================================
375
- // completeTask Tests
376
- // ============================================================================
377
- describe('completeTask', () => {
378
- beforeEach(() => {
379
- vi.clearAllMocks();
380
- });
381
- it('should throw error for missing task_id', async () => {
382
- const supabase = createMockSupabase();
383
- const ctx = createMockContext(supabase);
384
- await expect(completeTask({}, ctx)).rejects.toThrow(ValidationError);
385
- });
386
- it('should throw error for invalid task_id UUID', async () => {
387
- const supabase = createMockSupabase();
388
- const ctx = createMockContext(supabase);
389
- await expect(completeTask({ task_id: 'invalid' }, ctx)).rejects.toThrow(ValidationError);
390
- });
391
- it('should throw error when task not found', async () => {
392
- const supabase = createMockSupabase({
393
- selectResult: { data: null, error: { message: 'Not found' } },
394
- });
395
- const ctx = createMockContext(supabase);
396
- await expect(completeTask({ task_id: '123e4567-e89b-12d3-a456-426614174000' }, ctx)).rejects.toThrow('Task not found');
397
- });
398
- });
399
- // ============================================================================
400
- // updateTask Tests
401
- // ============================================================================
402
- describe('updateTask', () => {
403
- beforeEach(() => {
404
- vi.clearAllMocks();
405
- });
406
- it('should throw error for missing task_id', async () => {
407
- const supabase = createMockSupabase();
408
- const ctx = createMockContext(supabase);
409
- await expect(updateTask({}, ctx)).rejects.toThrow(ValidationError);
410
- });
411
- it('should throw error for invalid task_id UUID', async () => {
412
- const supabase = createMockSupabase();
413
- const ctx = createMockContext(supabase);
414
- await expect(updateTask({ task_id: 'invalid' }, ctx)).rejects.toThrow(ValidationError);
415
- });
416
- it('should throw error for invalid status', async () => {
417
- const supabase = createMockSupabase();
418
- const ctx = createMockContext(supabase);
419
- await expect(updateTask({ task_id: '123e4567-e89b-12d3-a456-426614174000', status: 'invalid' }, ctx)).rejects.toThrow(ValidationError);
420
- });
421
- it('should throw error for invalid priority', async () => {
422
- const supabase = createMockSupabase();
423
- const ctx = createMockContext(supabase);
424
- await expect(updateTask({ task_id: '123e4567-e89b-12d3-a456-426614174000', priority: 0 }, ctx)).rejects.toThrow(ValidationError);
425
- });
426
- it('should throw error for invalid progress_percentage', async () => {
427
- const supabase = createMockSupabase();
428
- const ctx = createMockContext(supabase);
429
- await expect(updateTask({ task_id: '123e4567-e89b-12d3-a456-426614174000', progress_percentage: 150 }, ctx)).rejects.toThrow(ValidationError);
430
- });
431
- });
@@ -1 +0,0 @@
1
- export {};