import { describe, it, expect, beforeEach, vi } from "vitest"; import { Test, TestingModule } from "@nestjs/testing"; import { PersonalitiesController } from "./personalities.controller"; import { PersonalitiesService } from "./personalities.service"; import type { CreatePersonalityDto } from "./dto/create-personality.dto"; import type { UpdatePersonalityDto } from "./dto/update-personality.dto"; import { AuthGuard } from "../auth/guards/auth.guard"; import { WorkspaceGuard, PermissionGuard } from "../common/guards"; import { FormalityLevel } from "@prisma/client"; describe("PersonalitiesController", () => { let controller: PersonalitiesController; let service: PersonalitiesService; const mockWorkspaceId = "workspace-123"; const mockPersonalityId = "personality-123"; /** API response shape (frontend field names) */ const mockPersonality = { id: mockPersonalityId, workspaceId: mockWorkspaceId, name: "professional-assistant", description: "A professional communication assistant", tone: "professional", formalityLevel: FormalityLevel.FORMAL, systemPromptTemplate: "You are a professional assistant who helps with tasks.", isDefault: true, isActive: true, createdAt: new Date("2026-01-01"), updatedAt: new Date("2026-01-01"), }; const mockPersonalitiesService = { create: vi.fn(), findAll: vi.fn(), findOne: vi.fn(), findByName: vi.fn(), findDefault: vi.fn(), update: vi.fn(), delete: vi.fn(), setDefault: vi.fn(), }; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [PersonalitiesController], providers: [ { provide: PersonalitiesService, useValue: mockPersonalitiesService, }, ], }) .overrideGuard(AuthGuard) .useValue({ canActivate: () => true }) .overrideGuard(WorkspaceGuard) .useValue({ canActivate: (ctx: { switchToHttp: () => { getRequest: () => { workspaceId: string } }; }) => { const req = ctx.switchToHttp().getRequest(); req.workspaceId = mockWorkspaceId; return true; }, }) .overrideGuard(PermissionGuard) .useValue({ canActivate: () => true }) .compile(); controller = module.get(PersonalitiesController); service = module.get(PersonalitiesService); vi.clearAllMocks(); }); describe("findAll", () => { it("should return success response with personalities list", async () => { const mockList = [mockPersonality]; mockPersonalitiesService.findAll.mockResolvedValue(mockList); const result = await controller.findAll(mockWorkspaceId, {}); expect(result).toEqual({ success: true, data: mockList }); expect(service.findAll).toHaveBeenCalledWith(mockWorkspaceId, {}); }); it("should pass isActive query filter to service", async () => { mockPersonalitiesService.findAll.mockResolvedValue([mockPersonality]); await controller.findAll(mockWorkspaceId, { isActive: true }); expect(service.findAll).toHaveBeenCalledWith(mockWorkspaceId, { isActive: true }); }); }); describe("findDefault", () => { it("should return the default personality", async () => { mockPersonalitiesService.findDefault.mockResolvedValue(mockPersonality); const result = await controller.findDefault(mockWorkspaceId); expect(result).toEqual(mockPersonality); expect(service.findDefault).toHaveBeenCalledWith(mockWorkspaceId); }); }); describe("findOne", () => { it("should return a personality by id", async () => { mockPersonalitiesService.findOne.mockResolvedValue(mockPersonality); const result = await controller.findOne(mockWorkspaceId, mockPersonalityId); expect(result).toEqual(mockPersonality); expect(service.findOne).toHaveBeenCalledWith(mockWorkspaceId, mockPersonalityId); }); }); describe("create", () => { it("should create a new personality", async () => { const createDto: CreatePersonalityDto = { name: "casual-helper", description: "A casual helper", tone: "casual", formalityLevel: FormalityLevel.CASUAL, systemPromptTemplate: "You are a casual assistant.", }; const created = { ...mockPersonality, ...createDto, isActive: true, isDefault: false }; mockPersonalitiesService.create.mockResolvedValue(created); const result = await controller.create(mockWorkspaceId, createDto); expect(result).toMatchObject({ name: createDto.name, tone: createDto.tone }); expect(service.create).toHaveBeenCalledWith(mockWorkspaceId, createDto); }); }); describe("update", () => { it("should update a personality", async () => { const updateDto: UpdatePersonalityDto = { description: "Updated description", tone: "enthusiastic", }; const updated = { ...mockPersonality, ...updateDto }; mockPersonalitiesService.update.mockResolvedValue(updated); const result = await controller.update(mockWorkspaceId, mockPersonalityId, updateDto); expect(result).toMatchObject(updateDto); expect(service.update).toHaveBeenCalledWith(mockWorkspaceId, mockPersonalityId, updateDto); }); }); describe("delete", () => { it("should delete a personality", async () => { mockPersonalitiesService.delete.mockResolvedValue(undefined); await controller.delete(mockWorkspaceId, mockPersonalityId); expect(service.delete).toHaveBeenCalledWith(mockWorkspaceId, mockPersonalityId); }); }); describe("setDefault", () => { it("should set a personality as default", async () => { const updated = { ...mockPersonality, isDefault: true }; mockPersonalitiesService.setDefault.mockResolvedValue(updated); const result = await controller.setDefault(mockWorkspaceId, mockPersonalityId); expect(result).toMatchObject({ isDefault: true }); expect(service.setDefault).toHaveBeenCalledWith(mockWorkspaceId, mockPersonalityId); }); }); });