@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.
- package/README.md +113 -98
- package/dist/api-client.d.ts +1169 -0
- package/dist/api-client.js +713 -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 +108 -477
- 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 +113 -828
- package/dist/handlers/discovery.d.ts +3 -0
- package/dist/handlers/discovery.js +26 -627
- package/dist/handlers/fallback.d.ts +2 -0
- package/dist/handlers/fallback.js +56 -142
- package/dist/handlers/findings.d.ts +8 -1
- package/dist/handlers/findings.js +65 -68
- 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 +119 -590
- package/dist/handlers/sprints.d.ts +32 -0
- package/dist/handlers/sprints.js +275 -0
- package/dist/handlers/tasks.d.ts +7 -10
- package/dist/handlers/tasks.js +245 -894
- package/dist/handlers/tool-docs.d.ts +9 -0
- package/dist/handlers/tool-docs.js +904 -0
- package/dist/handlers/types.d.ts +11 -3
- package/dist/handlers/validation.d.ts +1 -1
- package/dist/handlers/validation.js +38 -153
- package/dist/index.js +493 -162
- package/dist/knowledge.js +106 -9
- package/dist/tools.js +34 -4
- package/dist/validators.d.ts +21 -0
- package/dist/validators.js +91 -0
- package/package.json +2 -3
- package/src/api-client.ts +1822 -0
- package/src/cli.test.ts +128 -302
- package/src/cli.ts +41 -285
- package/src/handlers/__test-setup__.ts +215 -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 +210 -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 +143 -896
- package/src/handlers/discovery.test.ts +20 -67
- package/src/handlers/discovery.ts +29 -714
- package/src/handlers/fallback.test.ts +206 -361
- package/src/handlers/fallback.ts +81 -156
- package/src/handlers/findings.test.ts +229 -320
- package/src/handlers/findings.ts +76 -64
- 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 +276 -206
- package/src/handlers/session.ts +136 -662
- package/src/handlers/sprints.test.ts +711 -0
- package/src/handlers/sprints.ts +510 -0
- package/src/handlers/tasks.test.ts +669 -353
- package/src/handlers/tasks.ts +263 -1015
- package/src/handlers/tool-docs.ts +1024 -0
- package/src/handlers/types.ts +12 -4
- package/src/handlers/validation.test.ts +237 -568
- package/src/handlers/validation.ts +43 -167
- package/src/index.ts +493 -186
- package/src/tools.ts +2532 -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/knowledge.ts +0 -132
- 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
|
@@ -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
|
-
});
|
package/dist/utils.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|