Skip to content

Commit 4451aa4

Browse files
committed
test: update unit tests for numeric IDs and structured edge responses
- REST tests: send numeric IDs instead of String() (matches new validation) - MCP tests: check structured arrays (subtasks, dependsOn, related) instead of raw edges, matching updated get handlers
1 parent 8a2e09b commit 4451aa4

5 files changed

Lines changed: 50 additions & 56 deletions

File tree

src/tests/mcp-skills.test.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -255,10 +255,10 @@ describe('MCP Skill Tools', () => {
255255
expect(res.created).toBe(true);
256256
});
257257

258-
it('skills_get edges shows depends_on link', async () => {
259-
const skill = json<SkillResult>(await call('skills_get', { skillId: runTestSuiteId }));
260-
const dep = skill.edges?.find(e => e.toGraph === 'skills' && e.toId === addRestEndpointId && e.kind === 'depends_on');
261-
expect(dep).toBeDefined();
258+
it('skills_get shows depends_on link', async () => {
259+
const skill = json<any>(await call('skills_get', { skillId: runTestSuiteId }));
260+
expect(skill.dependsOn).toBeDefined();
261+
expect(skill.dependsOn).toContain(addRestEndpointId);
262262
});
263263

264264
it('skills_link duplicate is silently ignored (INSERT OR IGNORE)', async () => {
@@ -487,10 +487,11 @@ describe('Same-graph skill links via skills_create_link/skills_delete_link', ()
487487
expect(res.targetId).toBe(skillBId);
488488
});
489489

490-
it('link is visible via skills_get edges', async () => {
491-
const skill = json<SkillResult>(await sgCall('skills_get', { skillId: skillAId }));
492-
const edge = skill.edges?.find(e => e.toGraph === 'skills' && e.toId === skillBId && e.kind === 'depends_on');
493-
expect(edge).toBeDefined();
490+
it('link is visible via skills_get dependsOn', async () => {
491+
const skill = json<any>(await sgCall('skills_get', { skillId: skillAId }));
492+
// skills_get now returns structured arrays instead of raw edges
493+
expect(skill.dependsOn).toBeDefined();
494+
expect(skill.dependsOn).toContain(skillBId);
494495
});
495496

496497
it('skills_delete_link without targetGraph removes same-graph link', async () => {
@@ -504,9 +505,8 @@ describe('Same-graph skill links via skills_create_link/skills_delete_link', ()
504505
expect(res.deleted).toBe(true);
505506
});
506507

507-
it('after deletion, link no longer exists in edges', async () => {
508-
const skill = json<SkillResult>(await sgCall('skills_get', { skillId: skillAId }));
509-
const edge = skill.edges?.find(e => e.toGraph === 'skills' && e.toId === skillBId && e.kind === 'depends_on');
510-
expect(edge).toBeUndefined();
508+
it('after deletion, link no longer exists', async () => {
509+
const skill = json<any>(await sgCall('skills_get', { skillId: skillAId }));
510+
expect(skill.dependsOn ?? []).not.toContain(skillBId);
511511
});
512512
});

src/tests/mcp-tasks.test.ts

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -298,16 +298,13 @@ describe('Task CRUD tools', () => {
298298
expect(res.created).toBe(true);
299299
});
300300

301-
it('get_task shows edges for subtask and blocks links', async () => {
301+
it('get_task shows structured link arrays', async () => {
302302
const task = json<any>(await call('tasks_get', { taskId: fixAuthId }));
303-
const edges = task.edges as Array<{ fromGraph: string; fromId: number; toGraph: string; toId: number; kind: string }>;
304-
expect(edges).toBeDefined();
305-
// refactorConfig subtask_of fixAuth → edge from=refactorConfig to=fixAuth
306-
const subtaskEdge = edges.find(e => e.kind === 'subtask_of');
307-
expect(subtaskEdge).toBeDefined();
308-
// fixAuth blocks addSearch → edge from=fixAuth to=addSearch
309-
const blocksEdge = edges.find(e => e.kind === 'blocks');
310-
expect(blocksEdge).toBeDefined();
303+
// tasks_get now returns structured arrays: subtasks, blockedBy, blocks, related
304+
expect(task.subtasks).toBeDefined();
305+
expect(task.subtasks.length).toBeGreaterThan(0);
306+
expect(task.blocks).toBeDefined();
307+
expect(task.blocks.length).toBeGreaterThan(0);
311308
});
312309

313310
it('link_task duplicate is silently ignored', async () => {
@@ -452,13 +449,11 @@ describe('Same-graph task links via tasks_create_link/tasks_delete_link', () =>
452449
expect(res.targetId).toBe(childTaskId);
453450
});
454451

455-
it('same-graph link appears in tasks_get edges', async () => {
452+
it('same-graph link appears in tasks_get related', async () => {
456453
const task = json<any>(await sgCall('tasks_get', { taskId: parentTaskId }));
457-
const edges = task.edges as Array<{ fromId: number; toId: number; kind: string }>;
458-
expect(edges).toBeDefined();
459-
const relEdge = edges.find(e => e.kind === 'related_to');
460-
expect(relEdge).toBeDefined();
461-
expect(relEdge!.toId).toBe(childTaskId);
454+
// tasks_get now returns structured arrays instead of raw edges
455+
expect(task.related).toBeDefined();
456+
expect(task.related).toContain(childTaskId);
462457
});
463458

464459
it('tasks_delete_link without targetGraph removes same-graph link', async () => {
@@ -472,10 +467,9 @@ describe('Same-graph task links via tasks_create_link/tasks_delete_link', () =>
472467
expect(res.deleted).toBe(true);
473468
});
474469

475-
it('after deletion, link no longer appears in tasks_get edges', async () => {
470+
it('after deletion, link no longer appears in tasks_get related', async () => {
476471
const task = json<any>(await sgCall('tasks_get', { taskId: parentTaskId }));
477-
const edges = (task.edges ?? []) as Array<{ kind: string }>;
478-
expect(edges.find(e => e.kind === 'related_to')).toBeUndefined();
472+
expect(task.related ?? []).not.toContain(childTaskId);
479473
});
480474
});
481475

src/tests/rest-api-errors.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ describe('REST API error responses', () => {
338338

339339
const res = await request(app)
340340
.post('/api/projects/test/tasks/bulk/move')
341-
.send({ taskIds: [String(t1.body.id), String(t2.body.id)], status: 'done' });
341+
.send({ taskIds: [t1.body.id, t2.body.id], status: 'done' });
342342
expect(res.status).toBe(200);
343343
});
344344

@@ -348,7 +348,7 @@ describe('REST API error responses', () => {
348348

349349
const res = await request(app)
350350
.post('/api/projects/test/tasks/bulk/delete')
351-
.send({ taskIds: [String(t1.body.id), String(t2.body.id)] });
351+
.send({ taskIds: [t1.body.id, t2.body.id] });
352352
expect(res.status).toBe(200);
353353
});
354354

src/tests/rest-api-gaps.test.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -201,15 +201,15 @@ describe('REST Skills', () => {
201201
const createdSkill = await request(app).post(base).send({ title: 'Linked Skill', description: '' });
202202
const createdNote = await request(app).post('/api/projects/test/knowledge/notes').send({ title: 'Link Target', content: '' });
203203
const res = await request(app).post(`${base}/links`).send({
204-
fromId: String(createdSkill.body.id), toId: String(createdNote.body.id), kind: 'references', targetGraph: 'knowledge',
204+
fromId: createdSkill.body.id, toId: createdNote.body.id, kind: 'references', targetGraph: 'knowledge',
205205
});
206206
expect(res.status).toBe(201);
207207
});
208208

209209
it('DELETE /links returns 204 for non-existent link (idempotent)', async () => {
210210
const created = await request(app).post(base).send({ title: 'Unlink Skill', description: '' });
211211
const del = await request(app).delete(`${base}/links`).set('Content-Type', 'application/json').send({
212-
fromId: String(created.body.id), toId: '999999', targetGraph: 'knowledge',
212+
fromId: created.body.id, toId: 999999, targetGraph: 'knowledge',
213213
});
214214
expect(del.status).toBe(204);
215215
});
@@ -218,12 +218,12 @@ describe('REST Skills', () => {
218218
const createdSkill = await request(app).post(base).send({ title: 'DSkill', description: '' });
219219
const createdNote = await request(app).post('/api/projects/test/knowledge/notes').send({ title: 'DNote', content: '' });
220220
const cr = await request(app).post(`${base}/links`).send({
221-
fromId: String(createdSkill.body.id), toId: String(createdNote.body.id), kind: 'references', targetGraph: 'knowledge',
221+
fromId: createdSkill.body.id, toId: createdNote.body.id, kind: 'references', targetGraph: 'knowledge',
222222
});
223223
expect(cr.status).toBe(201);
224224
// DELETE /links is idempotent — returns 204 even for non-matching edge
225225
const del = await request(app).delete(`${base}/links`).set('Content-Type', 'application/json').send({
226-
fromId: String(createdSkill.body.id), toId: '999999', targetGraph: 'knowledge',
226+
fromId: createdSkill.body.id, toId: 999999, targetGraph: 'knowledge',
227227
});
228228
expect(del.status).toBe(204);
229229
});
@@ -232,7 +232,7 @@ describe('REST Skills', () => {
232232
const createdSkill = await request(app).post(base).send({ title: 'Find Skill', description: '' });
233233
const createdNote = await request(app).post('/api/projects/test/knowledge/notes').send({ title: 'Find Note', content: '' });
234234
await request(app).post(`${base}/links`).send({
235-
fromId: String(createdSkill.body.id), toId: String(createdNote.body.id), kind: 'references', targetGraph: 'knowledge',
235+
fromId: createdSkill.body.id, toId: createdNote.body.id, kind: 'references', targetGraph: 'knowledge',
236236
});
237237
const res = await request(app).get(`${base}/linked?targetGraph=knowledge&targetNodeId=${createdNote.body.id}`);
238238
expect(res.status).toBe(200);
@@ -460,10 +460,10 @@ describe('REST Knowledge gaps', () => {
460460
const fromNote = await request(app).post('/api/projects/test/knowledge/notes').send({ title: 'From', content: '' });
461461
const toNote = await request(app).post('/api/projects/test/knowledge/notes').send({ title: 'To', content: '' });
462462
await request(app).post('/api/projects/test/knowledge/relations').send({
463-
fromId: String(fromNote.body.id), toId: String(toNote.body.id), kind: 'relates_to',
463+
fromId: fromNote.body.id, toId: toNote.body.id, kind: 'relates_to',
464464
});
465465
const del = await request(app).delete('/api/projects/test/knowledge/relations').send({
466-
fromId: String(fromNote.body.id), toId: String(toNote.body.id),
466+
fromId: fromNote.body.id, toId: toNote.body.id,
467467
});
468468
expect(del.status).toBe(204);
469469
});
@@ -472,7 +472,7 @@ describe('REST Knowledge gaps', () => {
472472
const createdNote = await request(app).post('/api/projects/test/knowledge/notes').send({ title: 'KNote', content: '' });
473473
const createdTask = await request(app).post('/api/projects/test/tasks').send({ title: 'KTask', description: '' });
474474
await request(app).post('/api/projects/test/knowledge/relations').send({
475-
fromId: String(createdNote.body.id), toId: String(createdTask.body.id), kind: 'tracks', targetGraph: 'tasks',
475+
fromId: createdNote.body.id, toId: createdTask.body.id, kind: 'tracks', targetGraph: 'tasks',
476476
});
477477
const res = await request(app).get(`/api/projects/test/knowledge/linked?targetGraph=tasks&targetNodeId=${createdTask.body.id}`);
478478
expect(res.status).toBe(200);
@@ -515,15 +515,15 @@ describe('REST Tasks gaps', () => {
515515
const createdTask = await request(app).post('/api/projects/test/tasks').send({ title: 'Link Task', description: '' });
516516
const createdNote = await request(app).post('/api/projects/test/knowledge/notes').send({ title: 'Link Note', content: '' });
517517
const res = await request(app).post('/api/projects/test/tasks/links').send({
518-
fromId: String(createdTask.body.id), toId: String(createdNote.body.id), kind: 'references', targetGraph: 'knowledge',
518+
fromId: createdTask.body.id, toId: createdNote.body.id, kind: 'references', targetGraph: 'knowledge',
519519
});
520520
expect(res.status).toBe(201);
521521
});
522522

523523
it('DELETE /links returns 204 for non-existent link (idempotent)', async () => {
524524
const created = await request(app).post('/api/projects/test/tasks').send({ title: 'Ul Task', description: '' });
525525
const del = await request(app).delete('/api/projects/test/tasks/links').set('Content-Type', 'application/json').send({
526-
fromId: String(created.body.id), toId: '999999', targetGraph: 'knowledge',
526+
fromId: created.body.id, toId: 999999, targetGraph: 'knowledge',
527527
});
528528
expect(del.status).toBe(204);
529529
});
@@ -532,12 +532,12 @@ describe('REST Tasks gaps', () => {
532532
const createdTask = await request(app).post('/api/projects/test/tasks').send({ title: 'DTask', description: '' });
533533
const createdNote = await request(app).post('/api/projects/test/knowledge/notes').send({ title: 'DNote2', content: '' });
534534
const cr = await request(app).post('/api/projects/test/tasks/links').send({
535-
fromId: String(createdTask.body.id), toId: String(createdNote.body.id), kind: 'references', targetGraph: 'knowledge',
535+
fromId: createdTask.body.id, toId: createdNote.body.id, kind: 'references', targetGraph: 'knowledge',
536536
});
537537
expect(cr.status).toBe(201);
538538
// DELETE /links is idempotent — returns 204 even for non-matching edge
539539
const del = await request(app).delete('/api/projects/test/tasks/links').set('Content-Type', 'application/json').send({
540-
fromId: String(createdTask.body.id), toId: '999999', targetGraph: 'knowledge',
540+
fromId: createdTask.body.id, toId: 999999, targetGraph: 'knowledge',
541541
});
542542
expect(del.status).toBe(204);
543543
});
@@ -553,7 +553,7 @@ describe('REST Tasks gaps', () => {
553553
const createdTask = await request(app).post('/api/projects/test/tasks').send({ title: 'FTask', description: '' });
554554
const createdNote = await request(app).post('/api/projects/test/knowledge/notes').send({ title: 'FNote', content: '' });
555555
await request(app).post('/api/projects/test/tasks/links').send({
556-
fromId: String(createdTask.body.id), toId: String(createdNote.body.id), kind: 'references', targetGraph: 'knowledge',
556+
fromId: createdTask.body.id, toId: createdNote.body.id, kind: 'references', targetGraph: 'knowledge',
557557
});
558558
const res = await request(app).get(`/api/projects/test/tasks/linked?targetGraph=knowledge&targetNodeId=${createdNote.body.id}`);
559559
expect(res.status).toBe(200);

src/tests/rest-api.test.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -311,10 +311,10 @@ describe('REST API', () => {
311311

312312
const rel = await request(app)
313313
.post('/api/projects/test/knowledge/relations')
314-
.send({ fromId: String(noteAId), toId: String(noteBId), kind: 'relates_to' });
314+
.send({ fromId: noteAId, toId: noteBId, kind: 'relates_to' });
315315
expect(rel.status).toBe(201);
316-
expect(Number(rel.body.fromId)).toBe(noteAId);
317-
expect(Number(rel.body.toId)).toBe(noteBId);
316+
expect(rel.body.fromId).toBe(noteAId);
317+
expect(rel.body.toId).toBe(noteBId);
318318

319319
const list = await request(app).get(`/api/projects/test/knowledge/notes/${noteAId}/relations`);
320320
expect(list.body.results.length).toBeGreaterThan(0);
@@ -451,7 +451,7 @@ describe('REST API', () => {
451451

452452
const res = await request(app)
453453
.post('/api/projects/test/tasks/bulk/move')
454-
.send({ taskIds: [String(t1.body.id), String(t2.body.id)], status: 'done' });
454+
.send({ taskIds: [t1.body.id, t2.body.id], status: 'done' });
455455
expect(res.status).toBe(200);
456456
expect(typeof res.body.moved).toBe('number');
457457
expect(res.body.moved).toBe(2);
@@ -466,7 +466,7 @@ describe('REST API', () => {
466466

467467
const res = await request(app)
468468
.post('/api/projects/test/tasks/bulk/priority')
469-
.send({ taskIds: [String(t1.body.id), String(t2.body.id)], priority: 'critical' });
469+
.send({ taskIds: [t1.body.id, t2.body.id], priority: 'critical' });
470470
expect(res.status).toBe(200);
471471
expect(typeof res.body.updated).toBe('number');
472472
expect(res.body.updated).toBe(2);
@@ -481,7 +481,7 @@ describe('REST API', () => {
481481

482482
const res = await request(app)
483483
.post('/api/projects/test/tasks/bulk/delete')
484-
.send({ taskIds: [String(t1.body.id), String(t2.body.id)] });
484+
.send({ taskIds: [t1.body.id, t2.body.id] });
485485
expect(res.status).toBe(200);
486486
expect(typeof res.body.deleted).toBe('number');
487487
expect(res.body.deleted).toBe(2);
@@ -495,7 +495,7 @@ describe('REST API', () => {
495495

496496
const res = await request(app)
497497
.post('/api/projects/test/tasks/bulk/move')
498-
.send({ taskIds: [String(t1.body.id), '999999'], status: 'review' });
498+
.send({ taskIds: [t1.body.id, 999999], status: 'review' });
499499
expect(res.status).toBe(200);
500500
expect(typeof res.body.moved).toBe('number');
501501
expect(res.body.moved).toBe(1);
@@ -577,7 +577,7 @@ describe('REST API', () => {
577577
// Link
578578
const linkRes = await request(app)
579579
.post(`/api/projects/test/epics/${epic.body.id}/link`)
580-
.send({ taskId: String(task.body.id) });
580+
.send({ taskId: task.body.id });
581581
expect(linkRes.status).toBe(201);
582582

583583
// Get tasks
@@ -589,7 +589,7 @@ describe('REST API', () => {
589589
// Unlink
590590
const unlinkRes = await request(app)
591591
.delete(`/api/projects/test/epics/${epic.body.id}/link`)
592-
.send({ taskId: String(task.body.id) });
592+
.send({ taskId: task.body.id });
593593
expect(unlinkRes.status).toBe(204);
594594
});
595595

@@ -601,8 +601,8 @@ describe('REST API', () => {
601601
const t1 = await request(app).post('/api/projects/test/tasks').send({ title: 'T1', description: '' });
602602
const t2 = await request(app).post('/api/projects/test/tasks').send({ title: 'T2', description: '', status: 'done' });
603603

604-
await request(app).post(`/api/projects/test/epics/${epic.body.id}/link`).send({ taskId: String(t1.body.id) });
605-
await request(app).post(`/api/projects/test/epics/${epic.body.id}/link`).send({ taskId: String(t2.body.id) });
604+
await request(app).post(`/api/projects/test/epics/${epic.body.id}/link`).send({ taskId: t1.body.id });
605+
await request(app).post(`/api/projects/test/epics/${epic.body.id}/link`).send({ taskId: t2.body.id });
606606

607607
const res = await request(app).get(`/api/projects/test/epics/${epic.body.id}`);
608608
expect(res.body.progress.total).toBe(2);

0 commit comments

Comments
 (0)