import { describe, it, expect, beforeEach, vi } from "vitest"; import { Test, TestingModule } from "@nestjs/testing"; import { AdminController } from "./admin.controller"; import { AdminService } from "./admin.service"; import { AuthGuard } from "../auth/guards/auth.guard"; import { AdminGuard } from "../auth/guards/admin.guard"; import { WorkspaceMemberRole } from "@prisma/client"; import type { ExecutionContext } from "@nestjs/common"; describe("AdminController", () => { let controller: AdminController; let service: AdminService; const mockAdminService = { listUsers: vi.fn(), inviteUser: vi.fn(), updateUser: vi.fn(), deactivateUser: vi.fn(), createWorkspace: vi.fn(), updateWorkspace: vi.fn(), }; const mockAuthGuard = { canActivate: vi.fn((context: ExecutionContext) => { const request = context.switchToHttp().getRequest(); request.user = { id: "550e8400-e29b-41d4-a716-446655440001", email: "admin@example.com", name: "Admin User", }; return true; }), }; const mockAdminGuard = { canActivate: vi.fn(() => true), }; const mockAdminId = "550e8400-e29b-41d4-a716-446655440001"; const mockUserId = "550e8400-e29b-41d4-a716-446655440002"; const mockWorkspaceId = "550e8400-e29b-41d4-a716-446655440003"; const mockAdminUser = { id: mockAdminId, email: "admin@example.com", name: "Admin User", }; const mockUserResponse = { id: mockUserId, name: "Test User", email: "test@example.com", emailVerified: false, image: null, createdAt: new Date("2026-01-01"), deactivatedAt: null, isLocalAuth: false, invitedAt: null, invitedBy: null, workspaceMemberships: [], }; const mockWorkspaceResponse = { id: mockWorkspaceId, name: "Test Workspace", ownerId: mockAdminId, settings: {}, createdAt: new Date("2026-01-01"), updatedAt: new Date("2026-01-01"), memberCount: 1, }; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [AdminController], providers: [ { provide: AdminService, useValue: mockAdminService, }, ], }) .overrideGuard(AuthGuard) .useValue(mockAuthGuard) .overrideGuard(AdminGuard) .useValue(mockAdminGuard) .compile(); controller = module.get(AdminController); service = module.get(AdminService); vi.clearAllMocks(); }); it("should be defined", () => { expect(controller).toBeDefined(); }); describe("listUsers", () => { it("should return paginated users", async () => { const paginatedResult = { data: [mockUserResponse], meta: { total: 1, page: 1, limit: 50, totalPages: 1 }, }; mockAdminService.listUsers.mockResolvedValue(paginatedResult); const result = await controller.listUsers({ page: 1, limit: 50 }); expect(result).toEqual(paginatedResult); expect(service.listUsers).toHaveBeenCalledWith(1, 50); }); it("should use default pagination", async () => { const paginatedResult = { data: [], meta: { total: 0, page: 1, limit: 50, totalPages: 0 }, }; mockAdminService.listUsers.mockResolvedValue(paginatedResult); await controller.listUsers({}); expect(service.listUsers).toHaveBeenCalledWith(undefined, undefined); }); }); describe("inviteUser", () => { it("should invite a user", async () => { const inviteDto = { email: "new@example.com" }; const invitationResponse = { userId: "new-id", invitationToken: "token", email: "new@example.com", invitedAt: new Date(), }; mockAdminService.inviteUser.mockResolvedValue(invitationResponse); const result = await controller.inviteUser(inviteDto, mockAdminUser); expect(result).toEqual(invitationResponse); expect(service.inviteUser).toHaveBeenCalledWith(inviteDto, mockAdminId); }); it("should invite a user with workspace and role", async () => { const inviteDto = { email: "new@example.com", workspaceId: mockWorkspaceId, role: WorkspaceMemberRole.ADMIN, }; mockAdminService.inviteUser.mockResolvedValue({ userId: "new-id", invitationToken: "token", email: "new@example.com", invitedAt: new Date(), }); await controller.inviteUser(inviteDto, mockAdminUser); expect(service.inviteUser).toHaveBeenCalledWith(inviteDto, mockAdminId); }); }); describe("updateUser", () => { it("should update a user", async () => { const updateDto = { name: "Updated Name" }; mockAdminService.updateUser.mockResolvedValue({ ...mockUserResponse, name: "Updated Name", }); const result = await controller.updateUser(mockUserId, updateDto); expect(result.name).toBe("Updated Name"); expect(service.updateUser).toHaveBeenCalledWith(mockUserId, updateDto); }); it("should deactivate a user via update", async () => { const deactivatedAt = "2026-02-28T00:00:00.000Z"; const updateDto = { deactivatedAt }; mockAdminService.updateUser.mockResolvedValue({ ...mockUserResponse, deactivatedAt: new Date(deactivatedAt), }); const result = await controller.updateUser(mockUserId, updateDto); expect(result.deactivatedAt).toEqual(new Date(deactivatedAt)); }); }); describe("deactivateUser", () => { it("should soft-delete a user", async () => { mockAdminService.deactivateUser.mockResolvedValue({ ...mockUserResponse, deactivatedAt: new Date(), }); const result = await controller.deactivateUser(mockUserId); expect(result.deactivatedAt).toBeDefined(); expect(service.deactivateUser).toHaveBeenCalledWith(mockUserId); }); }); describe("createWorkspace", () => { it("should create a workspace", async () => { const createDto = { name: "New Workspace", ownerId: mockAdminId }; mockAdminService.createWorkspace.mockResolvedValue(mockWorkspaceResponse); const result = await controller.createWorkspace(createDto); expect(result).toEqual(mockWorkspaceResponse); expect(service.createWorkspace).toHaveBeenCalledWith(createDto); }); it("should create workspace with settings", async () => { const createDto = { name: "New Workspace", ownerId: mockAdminId, settings: { feature: true }, }; mockAdminService.createWorkspace.mockResolvedValue({ ...mockWorkspaceResponse, settings: { feature: true }, }); const result = await controller.createWorkspace(createDto); expect(result.settings).toEqual({ feature: true }); }); }); describe("updateWorkspace", () => { it("should update a workspace", async () => { const updateDto = { name: "Updated Workspace" }; mockAdminService.updateWorkspace.mockResolvedValue({ ...mockWorkspaceResponse, name: "Updated Workspace", }); const result = await controller.updateWorkspace(mockWorkspaceId, updateDto); expect(result.name).toBe("Updated Workspace"); expect(service.updateWorkspace).toHaveBeenCalledWith(mockWorkspaceId, updateDto); }); it("should update workspace settings", async () => { const updateDto = { settings: { notifications: false } }; mockAdminService.updateWorkspace.mockResolvedValue({ ...mockWorkspaceResponse, settings: { notifications: false }, }); const result = await controller.updateWorkspace(mockWorkspaceId, updateDto); expect(result.settings).toEqual({ notifications: false }); }); }); });