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 links from '../../lib/db/repos/links.js'; let app, ownerHeaders, space; 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); }); describe('pages routes', () => { it('POST creates page with revision', async () => { const res = await request(app).post(`/api/spaces/${space.id}/pages`).set(ownerHeaders) .send({ slug: 'intro', title: 'Intro', body_md: 'hello' }); expect(res.status).toBe(201); const revs = await request(app).get(`/api/pages/${res.body.id}/revisions`).set(ownerHeaders); expect(revs.body.length).toBe(1); expect(revs.body[0].body_md).toBe('hello'); }); it('PATCH body_md adds another revision', async () => { const c = await request(app).post(`/api/spaces/${space.id}/pages`).set(ownerHeaders) .send({ slug: 'pg', title: 'PG', body_md: 'v1' }); await request(app).patch(`/api/pages/${c.body.id}`).set(ownerHeaders) .send({ body_md: 'v2' }); const revs = await request(app).get(`/api/pages/${c.body.id}/revisions`).set(ownerHeaders); expect(revs.body.length).toBe(2); expect(revs.body[0].body_md).toBe('v2'); expect(revs.body[1].body_md).toBe('v1'); }); it('GET by-slug returns the page', async () => { await request(app).post(`/api/spaces/${space.id}/pages`).set(ownerHeaders) .send({ slug: 'lookup', title: 'L', body_md: '' }); const res = await request(app) .get(`/api/spaces/${space.id}/pages/by-slug/lookup`).set(ownerHeaders); expect(res.status).toBe(200); expect(res.body.slug).toBe('lookup'); }); it('POST duplicate slug → 400', async () => { await request(app).post(`/api/spaces/${space.id}/pages`).set(ownerHeaders) .send({ slug: 'dup', title: 'A' }); const res = await request(app).post(`/api/spaces/${space.id}/pages`).set(ownerHeaders) .send({ slug: 'dup', title: 'B' }); expect(res.status).toBe(400); }); it('GET /:id/backlinks returns links pointing at the page', async () => { const pageRes = await request(app).post(`/api/spaces/${space.id}/pages`).set(ownerHeaders) .send({ slug: 'target', title: 'Target' }); const otherRes = await request(app).post(`/api/spaces/${space.id}/pages`).set(ownerHeaders) .send({ slug: 'src', title: 'Source' }); await links.create('page', otherRes.body.id, 'page', pageRes.body.id, 'mentions'); const res = await request(app).get(`/api/pages/${pageRes.body.id}/backlinks`).set(ownerHeaders); expect(res.status).toBe(200); expect(res.body.length).toBe(1); expect(res.body[0].from_id).toBe(otherRes.body.id); expect(res.body[0].source_title).toBe('Source'); }); it('DELETE returns 204 then GET → 404', async () => { const c = await request(app).post(`/api/spaces/${space.id}/pages`).set(ownerHeaders) .send({ slug: 'gone', title: 'Gone' }); const del = await request(app).delete(`/api/pages/${c.body.id}`).set(ownerHeaders); expect(del.status).toBe(204); const g = await request(app).get(`/api/pages/${c.body.id}`).set(ownerHeaders); expect(g.status).toBe(404); }); });