import { describe, it, expect, beforeAll, beforeEach } from 'vitest'; import request from 'supertest'; import { setup } from './helpers.js'; import * as spaces from '../../lib/db/repos/spaces.js'; import * as projects from '../../lib/db/repos/projects.js'; let app, ownerHeaders, space, project; const owner = { kind: 'user', id: null }; beforeAll(async () => { ({ app, ownerHeaders } = await setup()); }); beforeEach(async () => { space = await spaces.create({ slug: `s-${Date.now()}-${Math.random().toString(36).slice(2,5)}`, name: 'S' }, owner); project = await projects.create({ space_id: space.id, slug: 'p', name: 'P' }, owner); }); describe('tasks routes', () => { it('POST sibling task (no project_id)', async () => { const res = await request(app).post(`/api/spaces/${space.id}/tasks`).set(ownerHeaders) .send({ title: 'standalone' }); expect(res.status).toBe(201); expect(res.body.project_id).toBeNull(); expect(res.body.space_id).toBe(space.id); }); it('POST child task (with project_id)', async () => { const res = await request(app).post(`/api/spaces/${space.id}/tasks`).set(ownerHeaders) .send({ title: 'child', project_id: project.id }); expect(res.status).toBe(201); expect(res.body.project_id).toBe(project.id); }); it('GET /api/projects/:id/tasks ordered by position then created_at', async () => { await request(app).post(`/api/spaces/${space.id}/tasks`).set(ownerHeaders) .send({ title: 'second', project_id: project.id, position: 2 }); await request(app).post(`/api/spaces/${space.id}/tasks`).set(ownerHeaders) .send({ title: 'first', project_id: project.id, position: 1 }); const res = await request(app).get(`/api/projects/${project.id}/tasks`).set(ownerHeaders); expect(res.status).toBe(200); expect(res.body.map(t => t.title)).toEqual(['first', 'second']); }); it('PATCH status=done sets completed_at', async () => { const c = await request(app).post(`/api/spaces/${space.id}/tasks`).set(ownerHeaders) .send({ title: 'finish me' }); const res = await request(app).patch(`/api/tasks/${c.body.id}`).set(ownerHeaders) .send({ status: 'done' }); expect(res.status).toBe(200); expect(res.body.status).toBe('done'); expect(res.body.completed_at).not.toBeNull(); }); it('GET /api/spaces/:id/tasks?status=todo filters', async () => { const a = await request(app).post(`/api/spaces/${space.id}/tasks`).set(ownerHeaders) .send({ title: 'a' }); await request(app).patch(`/api/tasks/${a.body.id}`).set(ownerHeaders).send({ status: 'done' }); await request(app).post(`/api/spaces/${space.id}/tasks`).set(ownerHeaders).send({ title: 'b' }); const res = await request(app).get(`/api/spaces/${space.id}/tasks?status=todo`).set(ownerHeaders); expect(res.body.length).toBe(1); expect(res.body[0].title).toBe('b'); }); it('DELETE returns 204', async () => { const c = await request(app).post(`/api/spaces/${space.id}/tasks`).set(ownerHeaders) .send({ title: 'x' }); const del = await request(app).delete(`/api/tasks/${c.body.id}`).set(ownerHeaders); expect(del.status).toBe(204); }); });