import { describe, it, expect, beforeEach } from 'vitest'; import { resetDb, withClient } from '../helpers/db.js'; import { migrateUp } from '../../lib/db/migrate.js'; describe('migration 003 — resources', () => { beforeEach(async () => { await resetDb(); await migrateUp(); }); it('creates resources, resource_dependencies, resource_credentials, source_docs', async () => { await withClient(async (c) => { for (const t of ['resources','resource_dependencies','resource_credentials','source_docs']) { const { rows } = await c.query( `SELECT to_regclass('public.' || $1) AS t;`, [t] ); expect(rows[0].t).toBe(t); } }); }); it('resource_dependencies rejects cross-space endpoints', async () => { await withClient(async (c) => { const { rows: [s1] } = await c.query(`INSERT INTO spaces(slug,name) VALUES('a','A') RETURNING id;`); const { rows: [s2] } = await c.query(`INSERT INTO spaces(slug,name) VALUES('b','B') RETURNING id;`); const { rows: [a] } = await c.query( `INSERT INTO resources(space_id, slug, name, runtime_type) VALUES($1,'a','A','lxc') RETURNING id;`, [s1.id]); const { rows: [b] } = await c.query( `INSERT INTO resources(space_id, slug, name, runtime_type) VALUES($1,'b','B','lxc') RETURNING id;`, [s2.id]); await expect(c.query( `INSERT INTO resource_dependencies(resource_id, depends_on, space_id) VALUES($1,$2,$3);`, [a.id, b.id, s1.id] )).rejects.toThrow(/foreign key/i); }); }); it('resource_credentials rejects assignment to a resource in another space', async () => { await withClient(async (c) => { const { rows: [s1] } = await c.query(`INSERT INTO spaces(slug,name) VALUES('a','A') RETURNING id;`); const { rows: [s2] } = await c.query(`INSERT INTO spaces(slug,name) VALUES('b','B') RETURNING id;`); const { rows: [r] } = await c.query( `INSERT INTO resources(space_id, slug, name, runtime_type) VALUES($1,'r','R','lxc') RETURNING id;`, [s1.id]); await expect(c.query( `INSERT INTO resource_credentials(resource_id, space_id, label, vault_path) VALUES($1,$2,'l','env:X');`, [r.id, s2.id] )).rejects.toThrow(/foreign key/i); }); }); it('source_docs.resource_id is NOT NULL', async () => { await withClient(async (c) => { await expect(c.query( `INSERT INTO source_docs(name, upstream_url) VALUES('n','https://x');` )).rejects.toThrow(/not.null|null value/i); }); }); });