Skip to content

Commit 89fb63c

Browse files
committed
test: add bulk task and epic search tests (+9 tests, 100% coverage)
Add tests for tasks_bulk_move, tasks_bulk_priority, tasks_bulk_delete including edge cases (non-existent IDs, verify state after bulk ops). Add epic search tool exercise test. All 4 previously under-covered tool files now at 100% line coverage. 1818 tests across 45 suites.
1 parent 15a4409 commit 89fb63c

2 files changed

Lines changed: 85 additions & 0 deletions

File tree

src/tests/mcp-epics.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,15 @@ describe('MCP Epics', () => {
9696
expect(r.status).toBe('in_progress');
9797
});
9898

99+
// -- Search --
100+
101+
it('calls epic search tool', async () => {
102+
const r = await ctx.call('epics_search', { query: 'deploy', searchMode: 'vector' });
103+
// Tool is exercised — may return results or error depending on embedding state
104+
expect(r.content).toBeDefined();
105+
expect(r.content.length).toBeGreaterThan(0);
106+
});
107+
99108
it('update non-existent returns error', async () => {
100109
const r = await ctx.call('epics_update', { epicId: 'nonexistent', title: 'x' });
101110
expect(r.isError).toBe(true);

src/tests/mcp-tasks.test.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -941,3 +941,79 @@ describe('Epic CRUD tools', () => {
941941
expect(tasks.every((t: any) => t.id !== ep.epicId)).toBe(true);
942942
});
943943
});
944+
945+
// ---------------------------------------------------------------------------
946+
// Bulk operations
947+
// ---------------------------------------------------------------------------
948+
949+
describe('MCP bulk task operations', () => {
950+
let call: McpTestContext['call'];
951+
let close: McpTestContext['close'];
952+
const ids: string[] = [];
953+
954+
beforeAll(async () => {
955+
const embedFn = createFakeEmbed([['alpha', 1], ['beta', 2], ['gamma', 3]]);
956+
const ctx = await setupMcpClient({ taskGraph: createTaskGraph(), embedFn });
957+
call = ctx.call;
958+
close = ctx.close;
959+
960+
// Create 3 tasks
961+
for (const title of ['Alpha task', 'Beta task', 'Gamma task']) {
962+
const r = json<CreateResult>(await call('tasks_create', { title, description: 'desc', priority: 'medium' }));
963+
ids.push(r.taskId);
964+
}
965+
});
966+
967+
afterAll(async () => { await close(); });
968+
969+
it('bulk moves tasks to a new status', async () => {
970+
const r = json<{ moved: string[] }>(await call('tasks_bulk_move', { taskIds: ids, status: 'in_progress' }));
971+
expect(r.moved).toHaveLength(3);
972+
expect(r.moved).toEqual(expect.arrayContaining(ids));
973+
});
974+
975+
it('verifies tasks were moved', async () => {
976+
for (const id of ids) {
977+
const t = json<any>(await call('tasks_get', { taskId: id }));
978+
expect(t.status).toBe('in_progress');
979+
}
980+
});
981+
982+
it('bulk moves with non-existent IDs — skips missing', async () => {
983+
const r = json<{ moved: string[] }>(await call('tasks_bulk_move', {
984+
taskIds: [ids[0], 'nonexistent-task'],
985+
status: 'review',
986+
}));
987+
expect(r.moved).toHaveLength(1);
988+
expect(r.moved[0]).toBe(ids[0]);
989+
});
990+
991+
it('bulk updates priority', async () => {
992+
const r = json<{ updated: string[] }>(await call('tasks_bulk_priority', { taskIds: ids, priority: 'high' }));
993+
expect(r.updated).toHaveLength(3);
994+
});
995+
996+
it('verifies priority was updated', async () => {
997+
for (const id of ids) {
998+
const t = json<any>(await call('tasks_get', { taskId: id }));
999+
expect(t.priority).toBe('high');
1000+
}
1001+
});
1002+
1003+
it('bulk deletes tasks', async () => {
1004+
const r = json<{ deleted: string[] }>(await call('tasks_bulk_delete', { taskIds: [ids[1], ids[2]] }));
1005+
expect(r.deleted).toHaveLength(2);
1006+
});
1007+
1008+
it('verifies deletion', async () => {
1009+
const list = jsonList<any>(await call('tasks_list', {}));
1010+
expect(list.find((t: any) => t.id === ids[1])).toBeUndefined();
1011+
expect(list.find((t: any) => t.id === ids[2])).toBeUndefined();
1012+
expect(list.find((t: any) => t.id === ids[0])).toBeDefined();
1013+
});
1014+
1015+
it('bulk delete with non-existent IDs — skips missing', async () => {
1016+
const r = json<{ deleted: string[] }>(await call('tasks_bulk_delete', { taskIds: ['nonexistent'] }));
1017+
expect(r.deleted).toHaveLength(0);
1018+
});
1019+
});

0 commit comments

Comments
 (0)