import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import { mkdtempSync, rmSync } from 'fs'; import { tmpdir } from 'os'; import { join } from 'path'; import { createTask, listTasks, getTask, claimTask, doneTask, reviewTask, cancelTask, reopenTask, } from '../src/core/services/taskService.js'; describe('taskService', () => { let cwd: string; beforeEach(() => { cwd = mkdtempSync(join(tmpdir(), 'ah-task-')); }); afterEach(() => { rmSync(cwd, { recursive: true, force: true }); }); it('creates a task', () => { const task = createTask(cwd, { title: 'Test', role: 'implementer' }); expect(task.id).toBe('TSK-0001'); expect(task.title).toBe('Test'); expect(task.status).toBe('open'); }); it('lists tasks', () => { createTask(cwd, { title: 'A', role: 'implementer' }); expect(listTasks(cwd)).toHaveLength(1); }); it('claims and completes a task', () => { const task = createTask(cwd, { title: 'B', role: 'implementer' }); const claimed = claimTask(cwd, task.id, 'codex'); expect(claimed.status).toBe('in_progress'); expect(claimed.assignedTo).toBe('codex'); const done = doneTask(cwd, task.id); expect(done.status).toBe('done'); }); it('transitions a task to review', () => { const task = createTask(cwd, { title: 'C', role: 'implementer' }); const inReview = reviewTask(cwd, task.id); expect(inReview.status).toBe('review'); // Verify index is updated const listed = listTasks(cwd, { status: 'review' }); expect(listed).toHaveLength(1); expect(listed[0].id).toBe(task.id); }); it('cancels a task', () => { const task = createTask(cwd, { title: 'D', role: 'implementer' }); const cancelled = cancelTask(cwd, task.id); expect(cancelled.status).toBe('cancelled'); const listed = listTasks(cwd, { status: 'cancelled' }); expect(listed).toHaveLength(1); }); it('reopens a task (any status → open)', () => { const task = createTask(cwd, { title: 'E', role: 'implementer' }); cancelTask(cwd, task.id); const reopened = reopenTask(cwd, task.id); expect(reopened.status).toBe('open'); const listed = listTasks(cwd, { status: 'open' }); expect(listed).toHaveLength(1); }); it('getTask reads back the correct task', () => { const task = createTask(cwd, { title: 'F', role: 'architect' }); const { task: read } = getTask(cwd, task.id); expect(read.title).toBe('F'); expect(read.role).toBe('architect'); }); });