import 'reflect-metadata'; import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'; import { Global, Module } from '@nestjs/common'; import { Test } from '@nestjs/testing'; import { FastifyAdapter, type NestFastifyApplication } from '@nestjs/platform-fastify'; import { AUTH } from '../auth/auth.tokens.js'; import { AuthGuard } from '../auth/auth.guard.js'; import { InteractionCoordinationController } from './interaction-coordination.controller.js'; import { InteractionCoordinationService } from './interaction-coordination.service.js'; @Global() @Module({ providers: [ { provide: AUTH, useValue: { api: { getSession: vi.fn(async ({ headers }: { headers: Headers }) => headers.get('cookie') === 'session=trusted' ? { user: { id: 'operator-1', tenantId: 'tenant-1' }, session: { id: 'session-1' } } : null, ), }, }, }, AuthGuard, ], exports: [AUTH, AuthGuard], }) class AuthenticatedRequestModule {} describe('InteractionCoordinationController route aliases', (): void => { let app: NestFastifyApplication | undefined; const coordination = { handoff: vi.fn(async () => ({ handoffId: 'handoff-1' })), observe: vi.fn(async () => ({ status: 'running' })), result: vi.fn(async () => ({ status: 'completed' })), }; beforeAll(async (): Promise => { const moduleRef = await Test.createTestingModule({ imports: [AuthenticatedRequestModule], controllers: [InteractionCoordinationController], providers: [{ provide: InteractionCoordinationService, useValue: coordination }], }).compile(); app = moduleRef.createNestApplication(new FastifyAdapter()); await app.init(); await app.getHttpAdapter().getInstance().ready(); }); afterAll(async (): Promise => app?.close()); it('routes handoff, observe, and result through the same AuthGuard-protected service for both prefixes', async (): Promise => { if (!app) throw new Error('test app was not initialized'); for (const prefix of ['/api/coord/interaction', '/api/coord/mos']) { const headers = { cookie: 'session=trusted', 'x-correlation-id': `corr-${prefix}` }; expect( ( await app.inject({ method: 'POST', url: `${prefix}/handoff`, headers, payload: { idempotencyKey: `key-${prefix}`, summary: 'handoff' }, }) ).statusCode, ).toBe(201); expect( (await app.inject({ method: 'GET', url: `${prefix}/handoff-1/observe`, headers })) .statusCode, ).toBe(200); expect( (await app.inject({ method: 'GET', url: `${prefix}/handoff-1/result`, headers })) .statusCode, ).toBe(200); } expect(coordination.handoff).toHaveBeenCalledTimes(2); expect(coordination.observe).toHaveBeenCalledTimes(2); expect(coordination.result).toHaveBeenCalledTimes(2); expect( ( await app.inject({ method: 'POST', url: '/api/coord/interaction/handoff', payload: { idempotencyKey: 'denied', summary: 'x' }, }) ).statusCode, ).toBe(401); }); });