hospital-log/backend/api/src/modules/proof/proof.controller.spec.ts

174 lines
5.3 KiB
TypeScript

import { Test, TestingModule } from '@nestjs/testing';
import { ProofController } from './proof.controller';
import { ProofService } from './proof.service';
import { RequestProofDto } from './dto/request-proof.dto';
import { LogProofDto } from './dto/log-proof.dto';
import { BadRequestException, NotFoundException } from '@nestjs/common';
describe('ProofController', () => {
let controller: ProofController;
let proofService: jest.Mocked<ProofService>;
const mockProofService = {
getProof: jest.fn(),
logVerificationProof: jest.fn(),
};
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [ProofController],
providers: [
{
provide: ProofService,
useValue: mockProofService,
},
],
}).compile();
controller = module.get<ProofController>(ProofController);
proofService = module.get(ProofService);
jest.clearAllMocks();
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
describe('requestProof', () => {
const validRequestProofDto: RequestProofDto = {
id_visit: 'VISIT_001',
};
const mockProofResponse = {
proof: {
pi_a: ['123', '456'],
pi_b: [
['789', '012'],
['345', '678'],
],
pi_c: ['901', '234'],
protocol: 'groth16',
curve: 'bn128',
},
publicSignals: ['1', '18'],
};
it('should return proof successfully for valid id_visit', async () => {
mockProofService.getProof.mockResolvedValue(mockProofResponse);
const result = await controller.requestProof(validRequestProofDto);
expect(result).toEqual(mockProofResponse);
expect(proofService.getProof).toHaveBeenCalledWith(validRequestProofDto);
expect(proofService.getProof).toHaveBeenCalledTimes(1);
});
it('should throw NotFoundException when id_visit does not exist', async () => {
mockProofService.getProof.mockRejectedValue(
new NotFoundException('ID Visit tidak ditemukan'),
);
await expect(
controller.requestProof(validRequestProofDto),
).rejects.toThrow(NotFoundException);
expect(proofService.getProof).toHaveBeenCalledWith(validRequestProofDto);
});
it('should throw BadRequestException when proof generation fails', async () => {
mockProofService.getProof.mockRejectedValue(
new BadRequestException(
"Can't generate proof from input based on constraint. Please check the input data and try again.",
),
);
await expect(
controller.requestProof(validRequestProofDto),
).rejects.toThrow(BadRequestException);
});
it('should pass dto with empty id_visit to service (validation happens at pipe level)', async () => {
const emptyDto: RequestProofDto = { id_visit: '' };
mockProofService.getProof.mockRejectedValue(
new NotFoundException('ID Visit tidak ditemukan'),
);
await expect(controller.requestProof(emptyDto)).rejects.toThrow(
NotFoundException,
);
expect(proofService.getProof).toHaveBeenCalledWith(emptyDto);
});
});
describe('logVerification', () => {
const validLogProofDto: LogProofDto = {
id_visit: 'VISIT_001',
proof: { pi_a: ['123'], pi_b: [['456']], pi_c: ['789'] },
proofResult: true,
timestamp: '2025-12-10T10:00:00Z',
};
const mockLogResponse = {
response: {
txId: 'tx_123',
success: true,
},
responseData: {
id: 'PROOF_VISIT_001',
event: 'proof_verification_logged',
user_id: '0',
payload: 'hashed_payload',
},
};
it('should log verification proof successfully', async () => {
mockProofService.logVerificationProof.mockResolvedValue(mockLogResponse);
const result = await controller.logVerification(validLogProofDto);
expect(result).toEqual(mockLogResponse);
expect(proofService.logVerificationProof).toHaveBeenCalledWith(
validLogProofDto,
);
expect(proofService.logVerificationProof).toHaveBeenCalledTimes(1);
});
it('should handle service errors gracefully', async () => {
mockProofService.logVerificationProof.mockRejectedValue(
new Error('Blockchain connection failed'),
);
await expect(
controller.logVerification(validLogProofDto),
).rejects.toThrow('Blockchain connection failed');
});
it('should pass dto with false proofResult to service', async () => {
const failedProofDto: LogProofDto = {
...validLogProofDto,
proofResult: false,
};
mockProofService.logVerificationProof.mockResolvedValue({
...mockLogResponse,
responseData: { ...mockLogResponse.responseData },
});
await controller.logVerification(failedProofDto);
expect(proofService.logVerificationProof).toHaveBeenCalledWith(
failedProofDto,
);
});
// NOTE: This endpoint intentionally has no authentication
// as it is designed for external parties to log verification proofs
it('should accept request without authentication (intended for external parties)', async () => {
mockProofService.logVerificationProof.mockResolvedValue(mockLogResponse);
const result = await controller.logVerification(validLogProofDto);
expect(result).toBeDefined();
});
});
});