import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; import { Test, TestingModule } from "@nestjs/testing"; import { JobEventsController } from "./job-events.controller"; import { JobEventsService } from "./job-events.service"; import { JOB_CREATED } from "./event-types"; import { AuthGuard } from "../auth/guards/auth.guard"; import { WorkspaceGuard } from "../common/guards/workspace.guard"; import { PermissionGuard } from "../common/guards/permission.guard"; import { ExecutionContext } from "@nestjs/common"; describe("JobEventsController", () => { let controller: JobEventsController; let service: JobEventsService; const mockJobEventsService = { getEventsByJobId: vi.fn(), }; const mockAuthGuard = { canActivate: vi.fn((context: ExecutionContext) => { const request = context.switchToHttp().getRequest(); request.user = { id: "user-123", workspaceId: "workspace-123", }; return true; }), }; const mockWorkspaceGuard = { canActivate: vi.fn(() => true), }; const mockPermissionGuard = { canActivate: vi.fn(() => true), }; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [JobEventsController], providers: [ { provide: JobEventsService, useValue: mockJobEventsService, }, ], }) .overrideGuard(AuthGuard) .useValue(mockAuthGuard) .overrideGuard(WorkspaceGuard) .useValue(mockWorkspaceGuard) .overrideGuard(PermissionGuard) .useValue(mockPermissionGuard) .compile(); controller = module.get(JobEventsController); service = module.get(JobEventsService); }); afterEach(() => { vi.clearAllMocks(); }); describe("getEvents", () => { const jobId = "job-123"; const workspaceId = "workspace-123"; const mockEvents = { data: [ { id: "event-1", jobId, stepId: null, type: JOB_CREATED, timestamp: new Date("2026-01-01T10:00:00Z"), actor: "system", payload: {}, }, ], meta: { total: 1, page: 1, limit: 50, totalPages: 1, }, }; it("should return paginated events for a job", async () => { mockJobEventsService.getEventsByJobId.mockResolvedValue(mockEvents); const result = await controller.getEvents(jobId, {}, workspaceId); expect(service.getEventsByJobId).toHaveBeenCalledWith(jobId, {}); expect(result).toEqual(mockEvents); }); it("should pass query parameters to service", async () => { const query = { type: JOB_CREATED, page: 2, limit: 10 }; mockJobEventsService.getEventsByJobId.mockResolvedValue(mockEvents); await controller.getEvents(jobId, query, workspaceId); expect(service.getEventsByJobId).toHaveBeenCalledWith(jobId, query); }); it("should handle filtering by type", async () => { const query = { type: JOB_CREATED }; mockJobEventsService.getEventsByJobId.mockResolvedValue(mockEvents); const result = await controller.getEvents(jobId, query, workspaceId); expect(service.getEventsByJobId).toHaveBeenCalledWith(jobId, query); expect(result).toEqual(mockEvents); }); it("should handle pagination parameters", async () => { const query = { page: 2, limit: 25 }; mockJobEventsService.getEventsByJobId.mockResolvedValue({ ...mockEvents, meta: { total: 100, page: 2, limit: 25, totalPages: 4, }, }); const result = await controller.getEvents(jobId, query, workspaceId); expect(service.getEventsByJobId).toHaveBeenCalledWith(jobId, query); expect(result.meta.page).toBe(2); expect(result.meta.limit).toBe(25); }); }); });