d92476f841
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
108 lines
3.6 KiB
TypeScript
108 lines
3.6 KiB
TypeScript
import { Test, TestingModule } from '@nestjs/testing';
|
|
import { BadRequestException, ConflictException, NotFoundException } from '@nestjs/common';
|
|
import { Prisma } from '@prisma/client';
|
|
import { RoutesService } from './routes.service';
|
|
import { PrismaService } from '../../prisma/prisma.service';
|
|
|
|
const mockRoute = {
|
|
id: 'rt_1',
|
|
sourceGroupId: 'grp_1',
|
|
targetGroupId: 'grp_2',
|
|
isActive: true,
|
|
createdAt: new Date(),
|
|
sourceGroup: { name: 'Alpha' },
|
|
targetGroup: { name: 'Beta' },
|
|
};
|
|
|
|
describe('RoutesService', () => {
|
|
let service: RoutesService;
|
|
const mockPrisma = {
|
|
syncRoute: {
|
|
findMany: jest.fn().mockResolvedValue([mockRoute]),
|
|
create: jest.fn().mockResolvedValue(mockRoute),
|
|
delete: jest.fn().mockResolvedValue(mockRoute),
|
|
},
|
|
};
|
|
|
|
beforeEach(async () => {
|
|
jest.clearAllMocks();
|
|
const module: TestingModule = await Test.createTestingModule({
|
|
providers: [
|
|
RoutesService,
|
|
{ provide: PrismaService, useValue: mockPrisma },
|
|
],
|
|
}).compile();
|
|
service = module.get<RoutesService>(RoutesService);
|
|
});
|
|
|
|
describe('list', () => {
|
|
it('returns all routes with group names', async () => {
|
|
const result = await service.list();
|
|
expect(result).toHaveLength(1);
|
|
expect(result[0].sourceGroup.name).toBe('Alpha');
|
|
expect(mockPrisma.syncRoute.findMany).toHaveBeenCalledWith({
|
|
where: undefined,
|
|
include: {
|
|
sourceGroup: { select: { name: true } },
|
|
targetGroup: { select: { name: true } },
|
|
},
|
|
orderBy: { createdAt: 'desc' },
|
|
});
|
|
});
|
|
|
|
it('filters by sourceGroupId when provided', async () => {
|
|
await service.list('grp_1');
|
|
expect(mockPrisma.syncRoute.findMany).toHaveBeenCalledWith(
|
|
expect.objectContaining({ where: { sourceGroupId: 'grp_1' } }),
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('create', () => {
|
|
it('creates a route and returns it with group names', async () => {
|
|
const result = await service.create('grp_1', 'grp_2');
|
|
expect(result).toEqual(mockRoute);
|
|
expect(mockPrisma.syncRoute.create).toHaveBeenCalledWith({
|
|
data: { sourceGroupId: 'grp_1', targetGroupId: 'grp_2' },
|
|
include: {
|
|
sourceGroup: { select: { name: true } },
|
|
targetGroup: { select: { name: true } },
|
|
},
|
|
});
|
|
});
|
|
|
|
it('throws BadRequestException when sourceGroupId is empty', async () => {
|
|
await expect(service.create('', 'grp_2')).rejects.toThrow(BadRequestException);
|
|
});
|
|
|
|
it('throws BadRequestException when targetGroupId is empty', async () => {
|
|
await expect(service.create('grp_1', '')).rejects.toThrow(BadRequestException);
|
|
});
|
|
|
|
it('throws ConflictException when route already exists (Prisma P2002)', async () => {
|
|
const p2002 = new Prisma.PrismaClientKnownRequestError('Unique constraint', {
|
|
code: 'P2002',
|
|
clientVersion: '6.0.0',
|
|
});
|
|
mockPrisma.syncRoute.create.mockRejectedValueOnce(p2002);
|
|
await expect(service.create('grp_1', 'grp_2')).rejects.toThrow(ConflictException);
|
|
});
|
|
});
|
|
|
|
describe('remove', () => {
|
|
it('deletes a route by id', async () => {
|
|
await service.remove('rt_1');
|
|
expect(mockPrisma.syncRoute.delete).toHaveBeenCalledWith({ where: { id: 'rt_1' } });
|
|
});
|
|
|
|
it('throws NotFoundException when route does not exist (Prisma P2025)', async () => {
|
|
const p2025 = new Prisma.PrismaClientKnownRequestError('Record not found', {
|
|
code: 'P2025',
|
|
clientVersion: '6.0.0',
|
|
});
|
|
mockPrisma.syncRoute.delete.mockRejectedValueOnce(p2025);
|
|
await expect(service.remove('bad_id')).rejects.toThrow(NotFoundException);
|
|
});
|
|
});
|
|
});
|