Some checks failed
CI / lint-typecheck (pull_request) Failing after 12s
CI / tests (pull_request) Has been skipped
CI / contract-tests (pull_request) Has been skipped
CI / e2e-tests (pull_request) Has been skipped
CI / comment-pr (pull_request) Has been skipped
CI / commit-types (pull_request) Has been skipped
220 lines
5.8 KiB
TypeScript
220 lines
5.8 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest';
|
|
import { AdminController } from './AdminController';
|
|
import { DashboardStatsResponseDto } from './dtos/DashboardStatsResponseDto';
|
|
import { ListUsersRequestDto } from './dtos/ListUsersRequestDto';
|
|
import { UserListResponseDto, UserResponseDto } from './dtos/UserResponseDto';
|
|
|
|
describe('AdminController', () => {
|
|
let controller: AdminController;
|
|
let mockService: {
|
|
listUsers: ReturnType<typeof vi.fn>;
|
|
getDashboardStats: ReturnType<typeof vi.fn>;
|
|
};
|
|
|
|
beforeEach(() => {
|
|
mockService = {
|
|
listUsers: vi.fn(),
|
|
getDashboardStats: vi.fn(),
|
|
};
|
|
|
|
controller = new AdminController(mockService as never);
|
|
});
|
|
|
|
describe('listUsers', () => {
|
|
it('should list users with basic query params', async () => {
|
|
const mockUser: UserResponseDto = {
|
|
id: 'user-1',
|
|
email: 'test@example.com',
|
|
displayName: 'Test User',
|
|
roles: ['admin'],
|
|
status: 'active',
|
|
isSystemAdmin: false,
|
|
createdAt: new Date(),
|
|
updatedAt: new Date(),
|
|
};
|
|
|
|
const mockResponse: UserListResponseDto = {
|
|
users: [mockUser],
|
|
total: 1,
|
|
page: 1,
|
|
limit: 10,
|
|
totalPages: 1,
|
|
};
|
|
|
|
mockService.listUsers.mockResolvedValue(mockResponse);
|
|
|
|
const query: ListUsersRequestDto = {
|
|
page: 1,
|
|
limit: 10,
|
|
};
|
|
|
|
const req = { user: { userId: 'admin-1' } } as never;
|
|
const result = await controller.listUsers(query, req);
|
|
|
|
expect(mockService.listUsers).toHaveBeenCalledWith({
|
|
actorId: 'admin-1',
|
|
page: 1,
|
|
limit: 10,
|
|
});
|
|
expect(result).toEqual(mockResponse);
|
|
});
|
|
|
|
it('should list users with all query params', async () => {
|
|
const mockResponse: UserListResponseDto = {
|
|
users: [],
|
|
total: 0,
|
|
page: 2,
|
|
limit: 20,
|
|
totalPages: 0,
|
|
};
|
|
|
|
mockService.listUsers.mockResolvedValue(mockResponse);
|
|
|
|
const query: ListUsersRequestDto = {
|
|
page: 2,
|
|
limit: 20,
|
|
role: 'owner',
|
|
status: 'active',
|
|
email: 'admin',
|
|
search: 'test',
|
|
sortBy: 'email',
|
|
sortDirection: 'desc',
|
|
};
|
|
|
|
const req = { user: { userId: 'owner-1' } } as never;
|
|
const result = await controller.listUsers(query, req);
|
|
|
|
expect(mockService.listUsers).toHaveBeenCalledWith({
|
|
actorId: 'owner-1',
|
|
page: 2,
|
|
limit: 20,
|
|
role: 'owner',
|
|
status: 'active',
|
|
email: 'admin',
|
|
search: 'test',
|
|
sortBy: 'email',
|
|
sortDirection: 'desc',
|
|
});
|
|
expect(result).toEqual(mockResponse);
|
|
});
|
|
|
|
it('should handle missing user ID from request', async () => {
|
|
const mockResponse: UserListResponseDto = {
|
|
users: [],
|
|
total: 0,
|
|
page: 1,
|
|
limit: 10,
|
|
totalPages: 0,
|
|
};
|
|
|
|
mockService.listUsers.mockResolvedValue(mockResponse);
|
|
|
|
const query: ListUsersRequestDto = { page: 1, limit: 10 };
|
|
const req = {} as never;
|
|
|
|
await controller.listUsers(query, req);
|
|
|
|
expect(mockService.listUsers).toHaveBeenCalledWith({
|
|
actorId: 'current-user',
|
|
page: 1,
|
|
limit: 10,
|
|
});
|
|
});
|
|
|
|
it('should handle optional query params being undefined', async () => {
|
|
const mockResponse: UserListResponseDto = {
|
|
users: [],
|
|
total: 0,
|
|
page: 1,
|
|
limit: 10,
|
|
totalPages: 0,
|
|
};
|
|
|
|
mockService.listUsers.mockResolvedValue(mockResponse);
|
|
|
|
const query: ListUsersRequestDto = {
|
|
page: 1,
|
|
limit: 10,
|
|
};
|
|
|
|
const req = { user: { userId: 'admin-1' } } as never;
|
|
await controller.listUsers(query, req);
|
|
|
|
expect(mockService.listUsers).toHaveBeenCalledWith({
|
|
actorId: 'admin-1',
|
|
page: 1,
|
|
limit: 10,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('getDashboardStats', () => {
|
|
it('should return dashboard stats', async () => {
|
|
const mockStats: DashboardStatsResponseDto = {
|
|
totalUsers: 150,
|
|
activeUsers: 120,
|
|
suspendedUsers: 20,
|
|
deletedUsers: 10,
|
|
systemAdmins: 5,
|
|
recentLogins: 25,
|
|
newUsersToday: 8,
|
|
userGrowth: [],
|
|
roleDistribution: [],
|
|
statusDistribution: {
|
|
active: 120,
|
|
suspended: 20,
|
|
deleted: 10,
|
|
},
|
|
activityTimeline: [],
|
|
};
|
|
|
|
mockService.getDashboardStats.mockResolvedValue(mockStats);
|
|
|
|
const req = { user: { userId: 'admin-1' } } as never;
|
|
const result = await controller.getDashboardStats(req);
|
|
|
|
expect(mockService.getDashboardStats).toHaveBeenCalledWith({
|
|
actorId: 'admin-1',
|
|
});
|
|
expect(result).toEqual(mockStats);
|
|
});
|
|
|
|
it('should handle missing user ID from request', async () => {
|
|
const mockStats: DashboardStatsResponseDto = {
|
|
totalUsers: 0,
|
|
activeUsers: 0,
|
|
suspendedUsers: 0,
|
|
deletedUsers: 0,
|
|
systemAdmins: 0,
|
|
recentLogins: 0,
|
|
newUsersToday: 0,
|
|
userGrowth: [],
|
|
roleDistribution: [],
|
|
statusDistribution: {
|
|
active: 0,
|
|
suspended: 0,
|
|
deleted: 0,
|
|
},
|
|
activityTimeline: [],
|
|
};
|
|
|
|
mockService.getDashboardStats.mockResolvedValue(mockStats);
|
|
|
|
const req = {} as never;
|
|
const result = await controller.getDashboardStats(req);
|
|
|
|
expect(mockService.getDashboardStats).toHaveBeenCalledWith({
|
|
actorId: 'current-user',
|
|
});
|
|
expect(result).toEqual(mockStats);
|
|
});
|
|
|
|
it('should handle service errors gracefully', async () => {
|
|
mockService.getDashboardStats.mockRejectedValue(new Error('Database connection failed'));
|
|
|
|
const req = { user: { userId: 'admin-1' } } as never;
|
|
|
|
await expect(controller.getDashboardStats(req)).rejects.toThrow('Database connection failed');
|
|
});
|
|
});
|
|
}); |