import { convexTest } from 'convex-test'; import { describe, expect, test } from 'vitest'; import { api } from '../../convex/_generated/api'; import schema from '../../convex/schema'; const modules = import.meta.glob('../../convex/**/*.*s'); const createUser = async (t: ReturnType, email: string) => await t.mutation(async (ctx) => { return await ctx.db.insert('users', { email, name: email }); }); const authed = (t: ReturnType, userId: string) => t.withIdentity({ subject: `${userId}|session`, issuer: 'https://convex.test', }); const spoonInput = { name: 'Editor Spoon', provider: 'gitea' as const, upstreamOwner: 'upstream', upstreamRepo: 'editor', upstreamDefaultBranch: 'main', upstreamUrl: 'https://git.example.com/upstream/editor', forkOwner: 'team', forkRepo: 'editor-spoon', forkUrl: 'https://git.example.com/team/editor-spoon', visibility: 'private' as const, maintenanceMode: 'watch' as const, syncCadence: 'daily' as const, productionRefStrategy: 'default_branch' as const, }; describe('convex-test harness', () => { test('boots and executes against the project schema', async () => { const t = convexTest(schema, modules); expect(await t.run(() => Promise.resolve(42))).toBe(42); }); test('requires authentication to create a Spoon', async () => { const t = convexTest(schema, modules); await expect( t.mutation(api.spoons.createManual, spoonInput), ).rejects.toThrow('Not authenticated.'); }); test('creates and lists Spoons for the current user', async () => { const t = convexTest(schema, modules); const userId = await createUser(t, 'one@example.com'); const session = authed(t, userId); const spoonId = await session.mutation(api.spoons.createManual, spoonInput); const spoons = await session.query(api.spoons.listMine, {}); expect(spoons).toHaveLength(1); expect(spoons[0]?._id).toBe(spoonId); expect(spoons[0]?.ownerId).toBe(userId); }); test('does not allow reading another user’s Spoon', async () => { const t = convexTest(schema, modules); const ownerId = await createUser(t, 'owner@example.com'); const otherId = await createUser(t, 'other@example.com'); const spoonId = await authed(t, ownerId).mutation( api.spoons.createManual, spoonInput, ); await expect( authed(t, otherId).query(api.spoons.get, { spoonId }), ).rejects.toThrow('Spoon not found.'); }); test('requires Spoon ownership for agent requests', async () => { const t = convexTest(schema, modules); const ownerId = await createUser(t, 'owner@example.com'); const otherId = await createUser(t, 'other@example.com'); const spoonId = await authed(t, ownerId).mutation( api.spoons.createManual, spoonInput, ); await expect( authed(t, otherId).mutation(api.agentRequests.create, { spoonId, prompt: 'Add a settings page', }), ).rejects.toThrow('Spoon not found.'); }); });