import { Test, TestingModule } from "@nestjs/testing"; import { describe, it, expect, beforeEach, vi } from "vitest"; import { FindingsController } from "./findings.controller"; import { FindingsService } from "./findings.service"; import { AuthGuard } from "../auth/guards/auth.guard"; import { WorkspaceGuard, PermissionGuard } from "../common/guards"; import { CreateFindingDto, QueryFindingsDto, SearchFindingsDto } from "./dto"; describe("FindingsController", () => { let controller: FindingsController; let service: FindingsService; const mockFindingsService = { create: vi.fn(), findAll: vi.fn(), findOne: vi.fn(), search: vi.fn(), remove: vi.fn(), }; const mockAuthGuard = { canActivate: vi.fn(() => true), }; const mockWorkspaceGuard = { canActivate: vi.fn(() => true), }; const mockPermissionGuard = { canActivate: vi.fn(() => true), }; const workspaceId = "550e8400-e29b-41d4-a716-446655440001"; const findingId = "550e8400-e29b-41d4-a716-446655440002"; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [FindingsController], providers: [ { provide: FindingsService, useValue: mockFindingsService, }, ], }) .overrideGuard(AuthGuard) .useValue(mockAuthGuard) .overrideGuard(WorkspaceGuard) .useValue(mockWorkspaceGuard) .overrideGuard(PermissionGuard) .useValue(mockPermissionGuard) .compile(); controller = module.get(FindingsController); service = module.get(FindingsService); vi.clearAllMocks(); }); it("should be defined", () => { expect(controller).toBeDefined(); }); describe("create", () => { it("should create a finding", async () => { const createDto: CreateFindingDto = { agentId: "research-agent", type: "security", title: "SQL injection risk", data: { severity: "high" }, summary: "Potential SQL injection in search endpoint.", }; const createdFinding = { id: findingId, workspaceId, taskId: null, ...createDto, createdAt: new Date(), updatedAt: new Date(), }; mockFindingsService.create.mockResolvedValue(createdFinding); const result = await controller.create(createDto, workspaceId); expect(result).toEqual(createdFinding); expect(service.create).toHaveBeenCalledWith(workspaceId, createDto); }); }); describe("findAll", () => { it("should return paginated findings", async () => { const query: QueryFindingsDto = { page: 1, limit: 10, type: "security", }; const response = { data: [], meta: { total: 0, page: 1, limit: 10, totalPages: 0, }, }; mockFindingsService.findAll.mockResolvedValue(response); const result = await controller.findAll(query, workspaceId); expect(result).toEqual(response); expect(service.findAll).toHaveBeenCalledWith(workspaceId, query); }); }); describe("findOne", () => { it("should return a finding", async () => { const finding = { id: findingId, workspaceId, taskId: null, agentId: "research-agent", type: "security", title: "SQL injection risk", data: { severity: "high" }, summary: "Potential SQL injection in search endpoint.", createdAt: new Date(), updatedAt: new Date(), }; mockFindingsService.findOne.mockResolvedValue(finding); const result = await controller.findOne(findingId, workspaceId); expect(result).toEqual(finding); expect(service.findOne).toHaveBeenCalledWith(findingId, workspaceId); }); }); describe("search", () => { it("should perform semantic search", async () => { const searchDto: SearchFindingsDto = { query: "sql injection", limit: 5, }; const response = { data: [ { id: findingId, workspaceId, taskId: null, agentId: "research-agent", type: "security", title: "SQL injection risk", data: { severity: "high" }, summary: "Potential SQL injection in search endpoint.", createdAt: new Date(), updatedAt: new Date(), score: 0.91, }, ], meta: { total: 1, page: 1, limit: 5, totalPages: 1, }, query: "sql injection", }; mockFindingsService.search.mockResolvedValue(response); const result = await controller.search(searchDto, workspaceId); expect(result).toEqual(response); expect(service.search).toHaveBeenCalledWith(workspaceId, searchDto); }); }); describe("remove", () => { it("should delete a finding", async () => { const response = { message: "Finding deleted successfully" }; mockFindingsService.remove.mockResolvedValue(response); const result = await controller.remove(findingId, workspaceId); expect(result).toEqual(response); expect(service.remove).toHaveBeenCalledWith(findingId, workspaceId); }); }); });