import { describe, it, expect, beforeEach } from 'vitest'; import { mkdtemp } from 'node:fs/promises'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { writeCache, type CacheFile } from '../../src/lib/cache.js'; import { makeTasksTools } from '../../src/tools/tasks.js'; import type { Backend, CommitFileArgs, CommitResult, FileWithSha } from '../../src/lib/backend.js'; function recordingBackend(initial: Record = {}) { const files = { ...initial }; const backend: Backend = { async listUserRepos() { return []; }, async getRawFile(_u, repo, path) { return files[`${repo}:${path}`]?.content ?? null; }, async getFileWithSha(_u, repo, path) { return files[`${repo}:${path}`] ?? null; }, async commitFile(args: CommitFileArgs): Promise { return { fileSha: 'x', commitSha: 'y' }; }, }; return { backend, files }; } const fixture: CacheFile = { schemaVersion: 3, synced_at: '2026-06-08T12:00:00.000Z', synced_from: 'https://g', machine: 'm', projects: [ { name: 'OpeItcLoc03/alpha', default_branch: 'main', fetched_at: '2026-06-08T12:00:01.000Z', active_tasks: [], all_tasks_count: 0, raw: '', }, ], errors: [], }; const BOARD = '# Task Board\n\n## 🔵 [parked-task] — x\n\n**Status:** blocked\n**Branch:** master\n\n---\n' + '## 🔴 [live-task] — y\n\n**Status:** active\n**Branch:** master\n\n---\n'; let cacheFile: string; beforeEach(async () => { const dir = await mkdtemp(join(tmpdir(), 'getstatus-')); cacheFile = join(dir, 'tasks.json'); await writeCache(cacheFile, fixture); }); function makeTools(backend: Backend) { return makeTasksTools({ cacheFile, backend, giteaUser: 'u', agendaTasksRepo: 'projects-tasks' }); } function call(tools: ReturnType, name: string, args: Record) { const t = tools.find((x) => x.name === name)!; return t.handler(args); } describe('tasks.get_status', () => { it('returns the LIVE status of a task (reads the board, not the cache)', async () => { const { backend } = recordingBackend({ 'alpha:.tasks/STATUS.md': { content: BOARD, sha: 's' } }); const r = await call(makeTools(backend), 'tasks.get_status', { target_project: 'OpeItcLoc03/alpha', slug: 'parked-task', }); expect(JSON.parse(r.content[0].text).status).toBe('blocked'); }); it('distinguishes an active task', async () => { const { backend } = recordingBackend({ 'alpha:.tasks/STATUS.md': { content: BOARD, sha: 's' } }); const r = await call(makeTools(backend), 'tasks.get_status', { target_project: 'OpeItcLoc03/alpha', slug: 'live-task', }); expect(JSON.parse(r.content[0].text).status).toBe('active'); }); it('reports not-found for an absent slug', async () => { const { backend } = recordingBackend({ 'alpha:.tasks/STATUS.md': { content: BOARD, sha: 's' } }); const r = await call(makeTools(backend), 'tasks.get_status', { target_project: 'OpeItcLoc03/alpha', slug: 'ghost', }); const parsed = JSON.parse(r.content[0].text); expect(parsed.status).toBeNull(); expect(parsed.found).toBe(false); }); it('is disabled without a backend', async () => { const r = await call(makeTasksTools({ cacheFile }), 'tasks.get_status', { target_project: 'OpeItcLoc03/alpha', slug: 'live-task', }); expect(r.isError).toBe(true); }); });