/** * Unit tests for POST /api/v1/libs/:id/versions/discover * * Verifies: * - Local repo returns discovered tags * - GitHub repo returns empty tags gracefully (no error) * - Non-existent repo returns 404 */ import { beforeEach, describe, expect, it, vi } from 'vitest'; import Database from 'better-sqlite3'; import { readFileSync } from 'node:fs'; import { join } from 'node:path'; let db: Database.Database; vi.mock('$lib/server/db/client', () => ({ getClient: () => db })); vi.mock('$lib/server/db/client.js', () => ({ getClient: () => db })); vi.mock('$lib/server/pipeline/startup', () => ({ getQueue: () => null })); vi.mock('$lib/server/pipeline/startup.js', () => ({ getQueue: () => null })); // Mock git utilities so tests don't require a real git repo vi.mock('$lib/server/utils/git', () => ({ discoverVersionTags: vi.fn(), resolveTagToCommit: vi.fn() })); vi.mock('$lib/server/utils/git.js', () => ({ discoverVersionTags: vi.fn(), resolveTagToCommit: vi.fn() })); import { POST as postDiscover } from './+server.js'; const NOW_S = Math.floor(Date.now() / 1000); function createTestDb(): Database.Database { const client = new Database(':memory:'); client.pragma('foreign_keys = ON'); const migrationsFolder = join( import.meta.dirname, '../../../../../../../lib/server/db/migrations' ); const ftsFile = join(import.meta.dirname, '../../../../../../../lib/server/db/fts.sql'); const migration0 = readFileSync(join(migrationsFolder, '0000_large_master_chief.sql'), 'utf-8'); const migration1 = readFileSync(join(migrationsFolder, '0001_quick_nighthawk.sql'), 'utf-8'); const migration2 = readFileSync(join(migrationsFolder, '0002_silky_stellaris.sql'), 'utf-8'); for (const migration of [migration0, migration1, migration2]) { for (const stmt of migration .split('--> statement-breakpoint') .map((s) => s.trim()) .filter(Boolean)) { client.exec(stmt); } } client.exec(readFileSync(ftsFile, 'utf-8')); return client; } function seedRepo( client: Database.Database, overrides: { id?: string; source?: 'github' | 'local'; sourceUrl?: string } = {} ): string { const id = overrides.id ?? '/facebook/react'; client .prepare( `INSERT INTO repositories (id, title, source, source_url, state, created_at, updated_at) VALUES (?, ?, ?, ?, 'indexed', ?, ?)` ) .run( id, 'React', overrides.source ?? 'github', overrides.sourceUrl ?? 'https://github.com/facebook/react', NOW_S, NOW_S ); return id; } describe('POST /api/v1/libs/:id/versions/discover', () => { beforeEach(async () => { db = createTestDb(); const git = await import('$lib/server/utils/git'); vi.mocked(git.discoverVersionTags).mockReset(); vi.mocked(git.resolveTagToCommit).mockReset(); }); it('returns 404 when repo does not exist', async () => { const response = await postDiscover({ params: { id: encodeURIComponent('/nonexistent/repo') } } as never); expect(response.status).toBe(404); const body = await response.json(); expect(body.error).toBeDefined(); }); it('returns discovered tags for a local repository', async () => { const { discoverVersionTags, resolveTagToCommit } = await import('$lib/server/utils/git'); vi.mocked(discoverVersionTags).mockReturnValue(['v2.0.0', 'v1.0.0']); vi.mocked(resolveTagToCommit).mockImplementation(({ tag }) => tag === 'v2.0.0' ? 'abc12345' : 'def67890' ); seedRepo(db, { source: 'local', sourceUrl: '/home/user/myrepo' }); const response = await postDiscover({ params: { id: encodeURIComponent('/facebook/react') } } as never); expect(response.status).toBe(200); const body = await response.json(); expect(body.tags).toHaveLength(2); expect(body.tags[0]).toEqual({ tag: 'v2.0.0', commitHash: 'abc12345' }); expect(body.tags[1]).toEqual({ tag: 'v1.0.0', commitHash: 'def67890' }); }); it('returns empty tags for a GitHub repository (no error)', async () => { seedRepo(db, { source: 'github', sourceUrl: 'https://github.com/facebook/react' }); const response = await postDiscover({ params: { id: encodeURIComponent('/facebook/react') } } as never); expect(response.status).toBe(200); const body = await response.json(); expect(body.tags).toEqual([]); }); it('returns empty tags when git discovery throws', async () => { const { discoverVersionTags } = await import('$lib/server/utils/git'); vi.mocked(discoverVersionTags).mockImplementation(() => { throw new Error('git command failed'); }); seedRepo(db, { source: 'local', sourceUrl: '/home/user/myrepo' }); const response = await postDiscover({ params: { id: encodeURIComponent('/facebook/react') } } as never); expect(response.status).toBe(200); const body = await response.json(); expect(body.tags).toEqual([]); }); });