import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { resetDb } from '../../helpers/db.js'; import { migrateUp } from '../../../lib/db/migrate.js'; import { stopBoss, waitForJob } from '../../helpers/boss.js'; import { pool } from '../../../lib/db/pool.js'; import * as queue from '../../../lib/jobs/queue.js'; import { registerWorkers } from '../../../lib/jobs/index.js'; import * as spaces from '../../../lib/db/repos/spaces.js'; import * as pages from '../../../lib/db/repos/pages.js'; beforeEach(async () => { await resetDb(); await migrateUp(); await queue.start(); await registerWorkers(); global.fetch = vi.fn(async () => new Response( JSON.stringify({ embedding: new Array(768).fill(0.42) }), { status: 200, headers: { 'content-type': 'application/json' }} )); }); afterEach(async () => { await stopBoss(); vi.restoreAllMocks(); }); describe('embed.text worker', () => { it('writes a vector(1024) to the page row', async () => { const sp = await spaces.create({ slug: 'e', name: 'E' }, { kind: 'user', id: null }); const pg = await pages.create( { space_id: sp.id, slug: 'p', title: 'P', body_md: 'body' }, { kind: 'user', id: null } ); const id = await queue.enqueue('embed.text', { entity_type: 'page', entity_id: pg.id }); const j = await waitForJob('embed.text', id, { timeoutMs: 10_000 }); expect(j.state).toBe('completed'); const { rows: [row] } = await pool.query( 'SELECT embedding::text AS embedding FROM pages WHERE id=$1', [pg.id] ); expect(row.embedding).toBeTruthy(); // 1024 floats → at least 1023 commas in the literal const commas = (row.embedding.match(/,/g) || []).length; expect(commas).toBe(1023); }); it('emits an audit log entry', async () => { const sp = await spaces.create({ slug: 'e2', name: 'E2' }, { kind: 'user', id: null }); const pg = await pages.create( { space_id: sp.id, slug: 'p', title: 'P', body_md: 'body' }, { kind: 'user', id: null } ); const id = await queue.enqueue('embed.text', { entity_type: 'page', entity_id: pg.id }); await waitForJob('embed.text', id, { timeoutMs: 10_000 }); const { rows } = await pool.query( `SELECT * FROM audit_log WHERE entity_type='page' AND entity_id=$1 AND actor_kind='worker'`, [pg.id] ); expect(rows.length).toBeGreaterThan(0); }); });