2025-10-21 10:42:59 +00:00
|
|
|
import { Test, TestingModule } from '@nestjs/testing';
|
|
|
|
|
import { ObatController } from './obat.controller';
|
2025-12-10 07:23:56 +00:00
|
|
|
import { ObatService } from './obat.service';
|
|
|
|
|
import { AuthGuard } from '../auth/guard/auth.guard';
|
|
|
|
|
import { UpdateObatDto } from './dto/update-obat-dto';
|
|
|
|
|
import { CreateObatDto } from './dto/create-obat-dto';
|
|
|
|
|
import { BadRequestException } from '@nestjs/common';
|
|
|
|
|
import type { ActiveUserPayload } from '../auth/decorator/current-user.decorator';
|
2025-10-21 10:42:59 +00:00
|
|
|
|
|
|
|
|
describe('ObatController', () => {
|
|
|
|
|
let controller: ObatController;
|
2025-12-10 07:23:56 +00:00
|
|
|
let obatService: jest.Mocked<ObatService>;
|
|
|
|
|
|
|
|
|
|
const mockUser: ActiveUserPayload = {
|
|
|
|
|
sub: 1,
|
|
|
|
|
username: 'testuser',
|
|
|
|
|
role: 'admin' as any,
|
|
|
|
|
csrf: 'test-csrf-token',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const mockObat = {
|
|
|
|
|
id: 1,
|
|
|
|
|
id_visit: 'VISIT001',
|
|
|
|
|
obat: 'Paracetamol',
|
|
|
|
|
jumlah_obat: 10,
|
|
|
|
|
aturan_pakai: '3x1',
|
|
|
|
|
deleted_status: null,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const mockObatService = {
|
|
|
|
|
getAllObat: jest.fn(),
|
|
|
|
|
getObatById: jest.fn(),
|
|
|
|
|
createObat: jest.fn(),
|
|
|
|
|
updateObat: jest.fn(),
|
|
|
|
|
getLogObatById: jest.fn(),
|
|
|
|
|
deleteObat: jest.fn(),
|
|
|
|
|
};
|
2025-10-21 10:42:59 +00:00
|
|
|
|
|
|
|
|
beforeEach(async () => {
|
|
|
|
|
const module: TestingModule = await Test.createTestingModule({
|
|
|
|
|
controllers: [ObatController],
|
2025-12-10 07:23:56 +00:00
|
|
|
providers: [
|
|
|
|
|
{
|
|
|
|
|
provide: ObatService,
|
|
|
|
|
useValue: mockObatService,
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
})
|
|
|
|
|
.overrideGuard(AuthGuard)
|
|
|
|
|
.useValue({ canActivate: () => true })
|
|
|
|
|
.compile();
|
2025-10-21 10:42:59 +00:00
|
|
|
|
|
|
|
|
controller = module.get<ObatController>(ObatController);
|
2025-12-10 07:23:56 +00:00
|
|
|
obatService = module.get(ObatService);
|
|
|
|
|
|
|
|
|
|
jest.clearAllMocks();
|
2025-10-21 10:42:59 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should be defined', () => {
|
|
|
|
|
expect(controller).toBeDefined();
|
|
|
|
|
});
|
2025-12-10 07:23:56 +00:00
|
|
|
|
|
|
|
|
describe('getAllObat', () => {
|
|
|
|
|
it('should return all obat with pagination', async () => {
|
|
|
|
|
const expectedResult = {
|
|
|
|
|
0: mockObat,
|
|
|
|
|
totalCount: 1,
|
|
|
|
|
};
|
|
|
|
|
mockObatService.getAllObat.mockResolvedValue(expectedResult);
|
|
|
|
|
|
|
|
|
|
const result = await controller.getAllObat(
|
|
|
|
|
10,
|
|
|
|
|
0,
|
|
|
|
|
1,
|
|
|
|
|
'id',
|
|
|
|
|
'Paracetamol',
|
|
|
|
|
'asc',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect(result).toEqual(expectedResult);
|
|
|
|
|
expect(obatService.getAllObat).toHaveBeenCalledWith({
|
|
|
|
|
take: 10,
|
|
|
|
|
skip: 0,
|
|
|
|
|
page: 1,
|
|
|
|
|
orderBy: { id: 'asc' },
|
|
|
|
|
obat: 'Paracetamol',
|
|
|
|
|
order: 'asc',
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle undefined orderBy parameter', async () => {
|
|
|
|
|
const expectedResult = { 0: mockObat, totalCount: 1 };
|
|
|
|
|
mockObatService.getAllObat.mockResolvedValue(expectedResult);
|
|
|
|
|
|
|
|
|
|
await controller.getAllObat(
|
|
|
|
|
10,
|
|
|
|
|
0,
|
|
|
|
|
1,
|
|
|
|
|
undefined as unknown as string,
|
|
|
|
|
undefined as unknown as string,
|
|
|
|
|
undefined as unknown as 'asc' | 'desc',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect(obatService.getAllObat).toHaveBeenCalledWith({
|
|
|
|
|
take: 10,
|
|
|
|
|
skip: 0,
|
|
|
|
|
page: 1,
|
|
|
|
|
orderBy: undefined,
|
|
|
|
|
obat: undefined,
|
|
|
|
|
order: undefined,
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should pass order parameter when orderBy is provided', async () => {
|
|
|
|
|
mockObatService.getAllObat.mockResolvedValue({ totalCount: 0 });
|
|
|
|
|
|
|
|
|
|
await controller.getAllObat(
|
|
|
|
|
10,
|
|
|
|
|
0,
|
|
|
|
|
1,
|
|
|
|
|
'obat',
|
|
|
|
|
undefined as unknown as string,
|
|
|
|
|
'desc',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect(obatService.getAllObat).toHaveBeenCalledWith(
|
|
|
|
|
expect.objectContaining({
|
|
|
|
|
orderBy: { obat: 'desc' },
|
|
|
|
|
order: 'desc',
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('getObatById', () => {
|
|
|
|
|
it('should return obat by id', async () => {
|
|
|
|
|
mockObatService.getObatById.mockResolvedValue(mockObat);
|
|
|
|
|
|
|
|
|
|
const result = await controller.getObatById(1);
|
|
|
|
|
|
|
|
|
|
expect(result).toEqual(mockObat);
|
|
|
|
|
expect(obatService.getObatById).toHaveBeenCalledWith(1);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should return null when obat not found', async () => {
|
|
|
|
|
mockObatService.getObatById.mockResolvedValue(null);
|
|
|
|
|
|
|
|
|
|
const result = await controller.getObatById(999);
|
|
|
|
|
|
|
|
|
|
expect(result).toBeNull();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('createObat', () => {
|
|
|
|
|
it('should create obat successfully', async () => {
|
|
|
|
|
const createDto: CreateObatDto = {
|
|
|
|
|
id_visit: 'VISIT001',
|
|
|
|
|
obat: 'Paracetamol',
|
|
|
|
|
jumlah_obat: 10,
|
|
|
|
|
aturan_pakai: '3x1',
|
|
|
|
|
};
|
|
|
|
|
const expectedResult = { id: 1, ...createDto, status: 'PENDING' };
|
|
|
|
|
mockObatService.createObat.mockResolvedValue(expectedResult);
|
|
|
|
|
|
|
|
|
|
const result = await controller.createObat(createDto, mockUser);
|
|
|
|
|
|
|
|
|
|
expect(result).toEqual(expectedResult);
|
|
|
|
|
expect(obatService.createObat).toHaveBeenCalledWith(createDto, mockUser);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should throw BadRequestException when visit ID not found', async () => {
|
|
|
|
|
const createDto: CreateObatDto = {
|
|
|
|
|
id_visit: 'INVALID',
|
|
|
|
|
obat: 'Paracetamol',
|
|
|
|
|
jumlah_obat: 10,
|
|
|
|
|
aturan_pakai: '3x1',
|
|
|
|
|
};
|
|
|
|
|
mockObatService.createObat.mockRejectedValue(
|
|
|
|
|
new BadRequestException('Visit ID INVALID not found'),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await expect(controller.createObat(createDto, mockUser)).rejects.toThrow(
|
|
|
|
|
BadRequestException,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('updateObatById', () => {
|
|
|
|
|
it('should update obat successfully', async () => {
|
|
|
|
|
const updateDto: UpdateObatDto = {
|
|
|
|
|
obat: 'Ibuprofen',
|
|
|
|
|
jumlah_obat: 20,
|
|
|
|
|
aturan_pakai: '2x1',
|
|
|
|
|
};
|
|
|
|
|
const expectedResult = { id: 1, status: 'PENDING' };
|
|
|
|
|
mockObatService.updateObat.mockResolvedValue(expectedResult);
|
|
|
|
|
|
|
|
|
|
const result = await controller.updateObatById(1, updateDto, mockUser);
|
|
|
|
|
|
|
|
|
|
expect(result).toEqual(expectedResult);
|
|
|
|
|
expect(obatService.updateObat).toHaveBeenCalledWith(
|
|
|
|
|
1,
|
|
|
|
|
updateDto,
|
|
|
|
|
mockUser,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should throw BadRequestException when obat not found', async () => {
|
|
|
|
|
const updateDto: UpdateObatDto = {
|
|
|
|
|
obat: 'Ibuprofen',
|
|
|
|
|
jumlah_obat: 20,
|
|
|
|
|
aturan_pakai: '2x1',
|
|
|
|
|
};
|
|
|
|
|
mockObatService.updateObat.mockRejectedValue(
|
|
|
|
|
new BadRequestException('Medicine with ID 999 not found'),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await expect(
|
|
|
|
|
controller.updateObatById(999, updateDto, mockUser),
|
|
|
|
|
).rejects.toThrow(BadRequestException);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should throw BadRequestException when no changes detected', async () => {
|
|
|
|
|
const updateDto: UpdateObatDto = {
|
|
|
|
|
obat: 'Paracetamol',
|
|
|
|
|
jumlah_obat: 10,
|
|
|
|
|
aturan_pakai: '3x1',
|
|
|
|
|
};
|
|
|
|
|
mockObatService.updateObat.mockRejectedValue(
|
|
|
|
|
new BadRequestException('No changes in medicine data detected'),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await expect(
|
|
|
|
|
controller.updateObatById(1, updateDto, mockUser),
|
|
|
|
|
).rejects.toThrow('No changes in medicine data detected');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('getObatLogs', () => {
|
|
|
|
|
it('should return obat logs', async () => {
|
|
|
|
|
const expectedLogs = {
|
|
|
|
|
logs: [
|
|
|
|
|
{
|
|
|
|
|
id: 'OBAT_1',
|
|
|
|
|
event: 'obat_created',
|
|
|
|
|
status: 'ORIGINAL',
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
isTampered: false,
|
|
|
|
|
currentDataHash: 'abc123',
|
|
|
|
|
};
|
|
|
|
|
mockObatService.getLogObatById.mockResolvedValue(expectedLogs);
|
|
|
|
|
|
|
|
|
|
const result = await controller.getObatLogs('1');
|
|
|
|
|
|
|
|
|
|
expect(result).toEqual(expectedLogs);
|
|
|
|
|
expect(obatService.getLogObatById).toHaveBeenCalledWith('1');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle tampered data detection', async () => {
|
|
|
|
|
const expectedLogs = {
|
|
|
|
|
logs: [],
|
|
|
|
|
isTampered: true,
|
|
|
|
|
currentDataHash: 'abc123',
|
|
|
|
|
};
|
|
|
|
|
mockObatService.getLogObatById.mockResolvedValue(expectedLogs);
|
|
|
|
|
|
|
|
|
|
const result = await controller.getObatLogs('1');
|
|
|
|
|
|
|
|
|
|
expect(result.isTampered).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('deleteObatById', () => {
|
|
|
|
|
it('should delete obat successfully', async () => {
|
|
|
|
|
const expectedResult = { id: 1, status: 'PENDING', action: 'DELETE' };
|
|
|
|
|
mockObatService.deleteObat.mockResolvedValue(expectedResult);
|
|
|
|
|
|
|
|
|
|
const result = await controller.deleteObatById(1, mockUser);
|
|
|
|
|
|
|
|
|
|
expect(result).toEqual(expectedResult);
|
|
|
|
|
expect(obatService.deleteObat).toHaveBeenCalledWith(1, mockUser);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should throw BadRequestException when obat not found', async () => {
|
|
|
|
|
mockObatService.deleteObat.mockRejectedValue(
|
|
|
|
|
new BadRequestException('Obat with id 999 not found'),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await expect(controller.deleteObatById(999, mockUser)).rejects.toThrow(
|
|
|
|
|
BadRequestException,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
});
|
2025-10-21 10:42:59 +00:00
|
|
|
});
|