import { Test, TestingModule } from "@nestjs/testing"; import { AgentTasksService } from "./agent-tasks.service"; import { PrismaService } from "../prisma/prisma.service"; import { AgentTaskStatus, AgentTaskPriority } from "@prisma/client"; import { NotFoundException } from "@nestjs/common"; import { describe, it, expect, beforeEach, vi } from "vitest"; describe("AgentTasksService", () => { let service: AgentTasksService; let prisma: PrismaService; const mockPrismaService = { agentTask: { create: vi.fn(), findMany: vi.fn(), findUnique: vi.fn(), update: vi.fn(), delete: vi.fn(), count: vi.fn(), }, }; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ AgentTasksService, { provide: PrismaService, useValue: mockPrismaService, }, ], }).compile(); service = module.get(AgentTasksService); prisma = module.get(PrismaService); // Reset mocks vi.clearAllMocks(); }); describe("create", () => { it("should create a new agent task with default values", async () => { const workspaceId = "workspace-1"; const userId = "user-1"; const createDto = { title: "Test Task", description: "Test Description", agentType: "test-agent", }; const mockTask = { id: "task-1", workspaceId, title: "Test Task", description: "Test Description", status: AgentTaskStatus.PENDING, priority: AgentTaskPriority.MEDIUM, agentType: "test-agent", agentConfig: {}, result: null, error: null, createdById: userId, createdAt: new Date(), updatedAt: new Date(), startedAt: null, completedAt: null, createdBy: { id: userId, name: "Test User", email: "test@example.com", }, }; mockPrismaService.agentTask.create.mockResolvedValue(mockTask); const result = await service.create(workspaceId, userId, createDto); expect(mockPrismaService.agentTask.create).toHaveBeenCalledWith({ data: expect.objectContaining({ title: "Test Task", description: "Test Description", agentType: "test-agent", workspaceId, createdById: userId, status: AgentTaskStatus.PENDING, priority: AgentTaskPriority.MEDIUM, agentConfig: {}, }), include: { createdBy: { select: { id: true, name: true, email: true }, }, }, }); expect(result).toEqual(mockTask); }); it("should set startedAt when status is RUNNING", async () => { const workspaceId = "workspace-1"; const userId = "user-1"; const createDto = { title: "Running Task", agentType: "test-agent", status: AgentTaskStatus.RUNNING, }; mockPrismaService.agentTask.create.mockResolvedValue({ id: "task-1", startedAt: expect.any(Date), }); await service.create(workspaceId, userId, createDto); expect(mockPrismaService.agentTask.create).toHaveBeenCalledWith( expect.objectContaining({ data: expect.objectContaining({ startedAt: expect.any(Date), }), }) ); }); it("should set completedAt when status is COMPLETED", async () => { const workspaceId = "workspace-1"; const userId = "user-1"; const createDto = { title: "Completed Task", agentType: "test-agent", status: AgentTaskStatus.COMPLETED, }; mockPrismaService.agentTask.create.mockResolvedValue({ id: "task-1", completedAt: expect.any(Date), }); await service.create(workspaceId, userId, createDto); expect(mockPrismaService.agentTask.create).toHaveBeenCalledWith( expect.objectContaining({ data: expect.objectContaining({ startedAt: expect.any(Date), completedAt: expect.any(Date), }), }) ); }); }); describe("findAll", () => { it("should return paginated agent tasks", async () => { const workspaceId = "workspace-1"; const query = { workspaceId, page: 1, limit: 10 }; const mockTasks = [ { id: "task-1", title: "Task 1" }, { id: "task-2", title: "Task 2" }, ]; mockPrismaService.agentTask.findMany.mockResolvedValue(mockTasks); mockPrismaService.agentTask.count.mockResolvedValue(2); const result = await service.findAll(query); expect(result).toEqual({ data: mockTasks, meta: { total: 2, page: 1, limit: 10, totalPages: 1, }, }); expect(mockPrismaService.agentTask.findMany).toHaveBeenCalledWith({ where: { workspaceId }, include: { createdBy: { select: { id: true, name: true, email: true }, }, }, orderBy: { createdAt: "desc", }, skip: 0, take: 10, }); }); it("should apply filters correctly", async () => { const workspaceId = "workspace-1"; const query = { workspaceId, status: AgentTaskStatus.PENDING, priority: AgentTaskPriority.HIGH, agentType: "test-agent", }; mockPrismaService.agentTask.findMany.mockResolvedValue([]); mockPrismaService.agentTask.count.mockResolvedValue(0); await service.findAll(query); expect(mockPrismaService.agentTask.findMany).toHaveBeenCalledWith( expect.objectContaining({ where: { workspaceId, status: AgentTaskStatus.PENDING, priority: AgentTaskPriority.HIGH, agentType: "test-agent", }, }) ); }); }); describe("findOne", () => { it("should return a single agent task", async () => { const id = "task-1"; const workspaceId = "workspace-1"; const mockTask = { id, title: "Task 1", workspaceId }; mockPrismaService.agentTask.findUnique.mockResolvedValue(mockTask); const result = await service.findOne(id, workspaceId); expect(result).toEqual(mockTask); expect(mockPrismaService.agentTask.findUnique).toHaveBeenCalledWith({ where: { id, workspaceId }, include: { createdBy: { select: { id: true, name: true, email: true }, }, }, }); }); it("should throw NotFoundException when task not found", async () => { const id = "non-existent"; const workspaceId = "workspace-1"; mockPrismaService.agentTask.findUnique.mockResolvedValue(null); await expect(service.findOne(id, workspaceId)).rejects.toThrow(NotFoundException); }); }); describe("update", () => { it("should update an agent task", async () => { const id = "task-1"; const workspaceId = "workspace-1"; const updateDto = { title: "Updated Task" }; const existingTask = { id, workspaceId, status: AgentTaskStatus.PENDING, startedAt: null, }; const updatedTask = { ...existingTask, ...updateDto }; mockPrismaService.agentTask.findUnique.mockResolvedValue(existingTask); mockPrismaService.agentTask.update.mockResolvedValue(updatedTask); const result = await service.update(id, workspaceId, updateDto); expect(result).toEqual(updatedTask); expect(mockPrismaService.agentTask.update).toHaveBeenCalledWith({ where: { id, workspaceId }, data: updateDto, include: { createdBy: { select: { id: true, name: true, email: true }, }, }, }); }); it("should set startedAt when status changes to RUNNING", async () => { const id = "task-1"; const workspaceId = "workspace-1"; const updateDto = { status: AgentTaskStatus.RUNNING }; const existingTask = { id, workspaceId, status: AgentTaskStatus.PENDING, startedAt: null, }; mockPrismaService.agentTask.findUnique.mockResolvedValue(existingTask); mockPrismaService.agentTask.update.mockResolvedValue({ ...existingTask, ...updateDto, }); await service.update(id, workspaceId, updateDto); expect(mockPrismaService.agentTask.update).toHaveBeenCalledWith( expect.objectContaining({ data: expect.objectContaining({ startedAt: expect.any(Date), }), }) ); }); it("should throw NotFoundException when task not found", async () => { const id = "non-existent"; const workspaceId = "workspace-1"; const updateDto = { title: "Updated Task" }; mockPrismaService.agentTask.findUnique.mockResolvedValue(null); await expect(service.update(id, workspaceId, updateDto)).rejects.toThrow(NotFoundException); }); }); describe("remove", () => { it("should delete an agent task", async () => { const id = "task-1"; const workspaceId = "workspace-1"; const mockTask = { id, workspaceId, title: "Task 1" }; mockPrismaService.agentTask.findUnique.mockResolvedValue(mockTask); mockPrismaService.agentTask.delete.mockResolvedValue(mockTask); const result = await service.remove(id, workspaceId); expect(result).toEqual({ message: "Agent task deleted successfully" }); expect(mockPrismaService.agentTask.delete).toHaveBeenCalledWith({ where: { id, workspaceId }, }); }); it("should throw NotFoundException when task not found", async () => { const id = "non-existent"; const workspaceId = "workspace-1"; mockPrismaService.agentTask.findUnique.mockResolvedValue(null); await expect(service.remove(id, workspaceId)).rejects.toThrow(NotFoundException); }); }); });