Some checks failed
ci/woodpecker/push/api Pipeline failed
Co-authored-by: Jason Woltje <jason@diversecanvas.com> Co-committed-by: Jason Woltje <jason@diversecanvas.com>
259 lines
7.7 KiB
TypeScript
259 lines
7.7 KiB
TypeScript
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>(AdminController);
|
|
service = module.get<AdminService>(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 });
|
|
});
|
|
});
|
|
});
|