249 lines
6.3 KiB
TypeScript
249 lines
6.3 KiB
TypeScript
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<T> = {
|
|
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<any>,
|
|
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<typeof createPrismaMock>;
|
|
let logService: ReturnType<typeof createLogServiceMock>;
|
|
|
|
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>(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 = {
|
|
id_visit: 'VISIT-1',
|
|
obat: 'Ibuprofen',
|
|
jumlah_obat: 1,
|
|
aturan_pakai: '2x1',
|
|
};
|
|
|
|
it('updates obat and stores log', async () => {
|
|
prisma.pemberian_obat.update.mockResolvedValueOnce({
|
|
id: 99,
|
|
...updatePayload,
|
|
id_visit: 'VISIT-1',
|
|
});
|
|
logService.storeLog.mockResolvedValueOnce({ txId: 'updated' });
|
|
|
|
const result = await service.updateObat(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,
|
|
});
|
|
});
|
|
});
|
|
});
|