@vibescope/mcp-server 0.0.1 → 0.2.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 (173) hide show
  1. package/README.md +113 -98
  2. package/dist/api-client.d.ts +1169 -0
  3. package/dist/api-client.js +713 -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 +108 -477
  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 +113 -828
  16. package/dist/handlers/discovery.d.ts +3 -0
  17. package/dist/handlers/discovery.js +26 -627
  18. package/dist/handlers/fallback.d.ts +2 -0
  19. package/dist/handlers/fallback.js +56 -142
  20. package/dist/handlers/findings.d.ts +8 -1
  21. package/dist/handlers/findings.js +65 -68
  22. package/dist/handlers/git-issues.d.ts +9 -13
  23. package/dist/handlers/git-issues.js +80 -225
  24. package/dist/handlers/ideas.d.ts +3 -0
  25. package/dist/handlers/ideas.js +53 -134
  26. package/dist/handlers/index.d.ts +2 -0
  27. package/dist/handlers/index.js +6 -0
  28. package/dist/handlers/milestones.d.ts +2 -0
  29. package/dist/handlers/milestones.js +51 -98
  30. package/dist/handlers/organizations.js +79 -275
  31. package/dist/handlers/progress.d.ts +2 -0
  32. package/dist/handlers/progress.js +25 -123
  33. package/dist/handlers/project.js +42 -221
  34. package/dist/handlers/requests.d.ts +2 -0
  35. package/dist/handlers/requests.js +23 -83
  36. package/dist/handlers/session.js +119 -590
  37. package/dist/handlers/sprints.d.ts +32 -0
  38. package/dist/handlers/sprints.js +275 -0
  39. package/dist/handlers/tasks.d.ts +7 -10
  40. package/dist/handlers/tasks.js +245 -894
  41. package/dist/handlers/tool-docs.d.ts +9 -0
  42. package/dist/handlers/tool-docs.js +904 -0
  43. package/dist/handlers/types.d.ts +11 -3
  44. package/dist/handlers/validation.d.ts +1 -1
  45. package/dist/handlers/validation.js +38 -153
  46. package/dist/index.js +493 -162
  47. package/dist/knowledge.js +106 -9
  48. package/dist/tools.js +34 -4
  49. package/dist/validators.d.ts +21 -0
  50. package/dist/validators.js +91 -0
  51. package/package.json +2 -3
  52. package/src/api-client.ts +1822 -0
  53. package/src/cli.test.ts +128 -302
  54. package/src/cli.ts +41 -285
  55. package/src/handlers/__test-setup__.ts +215 -0
  56. package/src/handlers/__test-utils__.ts +4 -134
  57. package/src/handlers/blockers.test.ts +114 -124
  58. package/src/handlers/blockers.ts +68 -70
  59. package/src/handlers/bodies-of-work.test.ts +236 -831
  60. package/src/handlers/bodies-of-work.ts +210 -525
  61. package/src/handlers/cost.test.ts +149 -113
  62. package/src/handlers/cost.ts +44 -132
  63. package/src/handlers/decisions.test.ts +111 -209
  64. package/src/handlers/decisions.ts +35 -27
  65. package/src/handlers/deployment.test.ts +193 -239
  66. package/src/handlers/deployment.ts +143 -896
  67. package/src/handlers/discovery.test.ts +20 -67
  68. package/src/handlers/discovery.ts +29 -714
  69. package/src/handlers/fallback.test.ts +206 -361
  70. package/src/handlers/fallback.ts +81 -156
  71. package/src/handlers/findings.test.ts +229 -320
  72. package/src/handlers/findings.ts +76 -64
  73. package/src/handlers/git-issues.test.ts +623 -0
  74. package/src/handlers/git-issues.ts +174 -0
  75. package/src/handlers/ideas.test.ts +229 -343
  76. package/src/handlers/ideas.ts +69 -143
  77. package/src/handlers/index.ts +6 -0
  78. package/src/handlers/milestones.test.ts +167 -281
  79. package/src/handlers/milestones.ts +54 -93
  80. package/src/handlers/organizations.test.ts +275 -467
  81. package/src/handlers/organizations.ts +84 -294
  82. package/src/handlers/progress.test.ts +112 -218
  83. package/src/handlers/progress.ts +29 -142
  84. package/src/handlers/project.test.ts +203 -226
  85. package/src/handlers/project.ts +48 -238
  86. package/src/handlers/requests.test.ts +74 -342
  87. package/src/handlers/requests.ts +25 -83
  88. package/src/handlers/session.test.ts +276 -206
  89. package/src/handlers/session.ts +136 -662
  90. package/src/handlers/sprints.test.ts +711 -0
  91. package/src/handlers/sprints.ts +510 -0
  92. package/src/handlers/tasks.test.ts +669 -353
  93. package/src/handlers/tasks.ts +263 -1015
  94. package/src/handlers/tool-docs.ts +1024 -0
  95. package/src/handlers/types.ts +12 -4
  96. package/src/handlers/validation.test.ts +237 -568
  97. package/src/handlers/validation.ts +43 -167
  98. package/src/index.ts +493 -186
  99. package/src/tools.ts +2532 -0
  100. package/src/validators.test.ts +223 -223
  101. package/src/validators.ts +127 -0
  102. package/tsconfig.json +1 -1
  103. package/vitest.config.ts +14 -13
  104. package/dist/cli.test.d.ts +0 -1
  105. package/dist/cli.test.js +0 -367
  106. package/dist/handlers/__test-utils__.d.ts +0 -72
  107. package/dist/handlers/__test-utils__.js +0 -176
  108. package/dist/handlers/checkouts.d.ts +0 -37
  109. package/dist/handlers/checkouts.js +0 -377
  110. package/dist/handlers/knowledge-query.d.ts +0 -22
  111. package/dist/handlers/knowledge-query.js +0 -253
  112. package/dist/handlers/knowledge.d.ts +0 -12
  113. package/dist/handlers/knowledge.js +0 -108
  114. package/dist/handlers/roles.d.ts +0 -30
  115. package/dist/handlers/roles.js +0 -281
  116. package/dist/handlers/tasks.test.d.ts +0 -1
  117. package/dist/handlers/tasks.test.js +0 -431
  118. package/dist/utils.test.d.ts +0 -1
  119. package/dist/utils.test.js +0 -532
  120. package/dist/validators.test.d.ts +0 -1
  121. package/dist/validators.test.js +0 -176
  122. package/src/knowledge.ts +0 -132
  123. package/src/tmpclaude-0078-cwd +0 -1
  124. package/src/tmpclaude-0ee1-cwd +0 -1
  125. package/src/tmpclaude-2dd5-cwd +0 -1
  126. package/src/tmpclaude-344c-cwd +0 -1
  127. package/src/tmpclaude-3860-cwd +0 -1
  128. package/src/tmpclaude-4b63-cwd +0 -1
  129. package/src/tmpclaude-5c73-cwd +0 -1
  130. package/src/tmpclaude-5ee3-cwd +0 -1
  131. package/src/tmpclaude-6795-cwd +0 -1
  132. package/src/tmpclaude-709e-cwd +0 -1
  133. package/src/tmpclaude-9839-cwd +0 -1
  134. package/src/tmpclaude-d829-cwd +0 -1
  135. package/src/tmpclaude-e072-cwd +0 -1
  136. package/src/tmpclaude-f6ee-cwd +0 -1
  137. package/tmpclaude-0439-cwd +0 -1
  138. package/tmpclaude-132f-cwd +0 -1
  139. package/tmpclaude-15bb-cwd +0 -1
  140. package/tmpclaude-165a-cwd +0 -1
  141. package/tmpclaude-1ba9-cwd +0 -1
  142. package/tmpclaude-21a3-cwd +0 -1
  143. package/tmpclaude-2a38-cwd +0 -1
  144. package/tmpclaude-2adf-cwd +0 -1
  145. package/tmpclaude-2f56-cwd +0 -1
  146. package/tmpclaude-3626-cwd +0 -1
  147. package/tmpclaude-3727-cwd +0 -1
  148. package/tmpclaude-40bc-cwd +0 -1
  149. package/tmpclaude-436f-cwd +0 -1
  150. package/tmpclaude-4783-cwd +0 -1
  151. package/tmpclaude-4b6d-cwd +0 -1
  152. package/tmpclaude-4ba4-cwd +0 -1
  153. package/tmpclaude-51e6-cwd +0 -1
  154. package/tmpclaude-5ecf-cwd +0 -1
  155. package/tmpclaude-6f97-cwd +0 -1
  156. package/tmpclaude-7fb2-cwd +0 -1
  157. package/tmpclaude-825c-cwd +0 -1
  158. package/tmpclaude-8baf-cwd +0 -1
  159. package/tmpclaude-8d9f-cwd +0 -1
  160. package/tmpclaude-975c-cwd +0 -1
  161. package/tmpclaude-9983-cwd +0 -1
  162. package/tmpclaude-a045-cwd +0 -1
  163. package/tmpclaude-ac4a-cwd +0 -1
  164. package/tmpclaude-b593-cwd +0 -1
  165. package/tmpclaude-b891-cwd +0 -1
  166. package/tmpclaude-c032-cwd +0 -1
  167. package/tmpclaude-cf43-cwd +0 -1
  168. package/tmpclaude-d040-cwd +0 -1
  169. package/tmpclaude-dcdd-cwd +0 -1
  170. package/tmpclaude-dcee-cwd +0 -1
  171. package/tmpclaude-e16b-cwd +0 -1
  172. package/tmpclaude-ecd2-cwd +0 -1
  173. 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 {};