import { BadRequestException } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; import { PrismaService } from '../prisma/prisma.service'; import { LogService } from '../log/log.service'; import { ActiveUserPayload } from '../auth/decorator/current-user.decorator'; import { CreateObatDto } from './dto/create-obat-dto'; import { UpdateObatDto } from './dto/update-obat-dto'; import { ObatService } from './obat.service'; type PrismaDelegate = { findMany: jest.Mock; findUnique: jest.Mock; count: jest.Mock; create: jest.Mock; update: jest.Mock; }; const createPrismaMock = () => ({ pemberian_obat: { findMany: jest.fn(), findUnique: jest.fn(), count: jest.fn(), create: jest.fn(), update: jest.fn(), } as PrismaDelegate, rekam_medis: { findUnique: jest.fn(), }, }); const createLogServiceMock = () => ({ storeLog: jest.fn(), getLogById: jest.fn(), }); const mockUser: ActiveUserPayload = { sub: 1, username: 'tester', role: 'admin' as any, csrf: 'token', }; describe('ObatService', () => { let service: ObatService; let prisma: ReturnType; let logService: ReturnType; beforeEach(async () => { prisma = createPrismaMock(); logService = createLogServiceMock(); const module: TestingModule = await Test.createTestingModule({ providers: [ ObatService, { provide: PrismaService, useValue: prisma }, { provide: LogService, useValue: logService }, ], }).compile(); service = module.get(ObatService); }); it('should be defined', () => { expect(service).toBeDefined(); }); describe('getAllObat', () => { it('returns paginated data and total count', async () => { prisma.pemberian_obat.findMany.mockResolvedValueOnce([ { id: 1, obat: 'Paracetamol' }, ]); prisma.pemberian_obat.count.mockResolvedValueOnce(10); const result = await service.getAllObat({ take: 10, page: 1, orderBy: { id: 'asc' }, order: 'asc', obat: 'Para', }); expect(prisma.pemberian_obat.findMany).toHaveBeenCalledWith({ skip: 0, take: 10, where: { obat: { contains: 'Para' }, }, orderBy: { id: 'asc' }, }); expect(prisma.pemberian_obat.count).toHaveBeenCalledWith({ where: { obat: { contains: 'Para' }, }, }); expect(result).toEqual({ 0: { id: 1, obat: 'Paracetamol' }, totalCount: 10, }); }); }); describe('createObat', () => { const payload: CreateObatDto = { id_visit: 'VISIT-1', obat: 'Amoxicillin', jumlah_obat: 2, aturan_pakai: '3x1', }; it('throws when visit not found', async () => { prisma.rekam_medis.findUnique.mockResolvedValueOnce(null); await expect(service.createObat(payload, mockUser)).rejects.toThrow( BadRequestException, ); expect(prisma.pemberian_obat.create).not.toHaveBeenCalled(); }); it('creates obat and stores log', async () => { prisma.rekam_medis.findUnique.mockResolvedValueOnce({ id_visit: 'VISIT-1', }); prisma.pemberian_obat.create.mockResolvedValueOnce({ id: 42, ...payload, }); logService.storeLog.mockResolvedValueOnce({ txId: 'abc' }); const result = await service.createObat(payload, mockUser); expect(prisma.pemberian_obat.create).toHaveBeenCalledWith({ data: { id_visit: 'VISIT-1', obat: 'Amoxicillin', jumlah_obat: 2, aturan_pakai: '3x1', }, }); expect(logService.storeLog).toHaveBeenCalledWith({ id: 'OBAT_42', event: 'obat_created', user_id: mockUser.sub, payload: expect.any(String), }); expect(result).toEqual({ id: 42, id_visit: 'VISIT-1', obat: 'Amoxicillin', jumlah_obat: 2, aturan_pakai: '3x1', txId: 'abc', }); }); }); describe('updateObatById', () => { const updatePayload: UpdateObatDto = { obat: 'Ibuprofen', jumlah_obat: 1, aturan_pakai: '2x1', }; it('updates obat and stores log', async () => { prisma.pemberian_obat.update.mockResolvedValueOnce({ id: 99, id_visit: 'VISIT-1', ...updatePayload, }); logService.storeLog.mockResolvedValueOnce({ txId: 'updated' }); const result = await service.updateObatById(99, updatePayload, mockUser); expect(prisma.pemberian_obat.update).toHaveBeenCalledWith({ where: { id: 99 }, data: { obat: 'Ibuprofen', jumlah_obat: 1, aturan_pakai: '2x1', }, }); expect(logService.storeLog).toHaveBeenCalledWith({ id: 'OBAT_99', event: 'obat_updated', user_id: mockUser.sub, payload: expect.any(String), }); expect(result).toEqual({ id: 99, id_visit: 'VISIT-1', obat: 'Ibuprofen', jumlah_obat: 1, aturan_pakai: '2x1', txId: 'updated', }); }); }); describe('getLogObatById', () => { it('returns processed logs and tamper status', async () => { prisma.pemberian_obat.findUnique.mockResolvedValueOnce({ id: 5, obat: 'Paracetamol', jumlah_obat: 1, aturan_pakai: '3x1', }); const expectedHash = service.createHashingPayload({ obat: 'Paracetamol', jumlah_obat: 1, aturan_pakai: '3x1', }); logService.getLogById.mockResolvedValueOnce([ { value: { event: 'obat_created', payload: expectedHash, timestamp: '2024-01-01T00:00:00Z', user_id: 1, }, txId: 'abc', }, ]); const result = await service.getLogObatById('5'); expect(logService.getLogById).toHaveBeenCalledWith('OBAT_5'); expect(result).toEqual({ logs: [ { event: 'obat_created', payload: expectedHash, timestamp: '2024-01-01T00:00:00Z', user_id: 1, txId: 'abc', status: 'ORIGINAL', }, ], isTampered: false, currentDataHash: expectedHash, }); }); }); });