import { SearchResultView } from '@dorfteich/shared'; import { Test } from '@nestjs/testing'; import { User } from '@prisma/client'; import { describe, expect, it, vi } from 'vitest'; import { AuthedRequest } from '../auth/auth.guard'; import { SearchController } from './search.controller'; import { SearchProvider } from './search.provider'; /** * Proves the `SearchProvider` seam (ADR 0010 / issue #49): the controller * depends on the abstract token, so a fake implementation can replace the * PostgreSQL binding entirely in a test — which is exactly how an external * engine would be swapped in. */ describe('SearchProvider DI seam (issue #49)', () => { it('lets a fake provider replace the real binding', async () => { const hit: SearchResultView = { pageId: 'p1', title: 'Hit', slug: 'hit', pondId: 'pond1', pondSlug: 'pond', pondName: 'Pond', labelIds: [], classification: 'unclassified', snippet: 'a snippet', }; const fake: SearchProvider = { indexPage: vi.fn(), removePage: vi.fn(), removePond: vi.fn(), reindexPond: vi.fn(), reindexAll: vi.fn(), search: vi.fn().mockResolvedValue([hit]), }; const moduleRef = await Test.createTestingModule({ controllers: [SearchController], providers: [{ provide: SearchProvider, useValue: fake }], }).compile(); const controller = moduleRef.get(SearchController); const user = { id: 'u1', isSiteAdmin: false } as User; const result = await controller.query('hello', 'pond1', 'a,b', { user, } as AuthedRequest); expect(result).toEqual([hit]); expect(fake.search).toHaveBeenCalledWith( { q: 'hello', pondId: 'pond1', labels: ['a', 'b'] }, user, ); }); });