rwadurian/backend/services/mpc-service/tests/integration/mpc-party.controller.spec.ts

238 lines
7.2 KiB
TypeScript

/**
* MPC Party Controller Integration Tests
*
* Note: Full controller integration tests require the complete app setup.
* These are simplified tests for core functionality.
*/
import { Test, TestingModule } from '@nestjs/testing';
import { MPCPartyController } from '../../src/api/controllers/mpc-party.controller';
import { MPCPartyApplicationService } from '../../src/application/services/mpc-party-application.service';
import { PartyShareType } from '../../src/domain/enums';
import { JwtService } from '@nestjs/jwt';
import { ConfigService } from '@nestjs/config';
import { Reflector } from '@nestjs/core';
describe('MPCPartyController (Integration)', () => {
let controller: MPCPartyController;
let mockApplicationService: any;
beforeEach(async () => {
mockApplicationService = {
participateInKeygen: jest.fn(),
participateInSigning: jest.fn(),
rotateShare: jest.fn(),
getShareInfo: jest.fn(),
listShares: jest.fn(),
};
const module: TestingModule = await Test.createTestingModule({
controllers: [MPCPartyController],
providers: [
{ provide: MPCPartyApplicationService, useValue: mockApplicationService },
{ provide: JwtService, useValue: { verifyAsync: jest.fn() } },
{ provide: ConfigService, useValue: { get: jest.fn() } },
{ provide: Reflector, useValue: { getAllAndOverride: jest.fn().mockReturnValue(true) } },
],
}).compile();
controller = module.get<MPCPartyController>(MPCPartyController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
describe('health', () => {
it('should return health status', () => {
const result = controller.health();
expect(result.status).toBe('ok');
expect(result.service).toBe('mpc-party-service');
expect(result.timestamp).toBeDefined();
});
});
describe('listShares', () => {
it('should call application service listShares', async () => {
const mockResult = {
items: [],
total: 0,
page: 1,
limit: 10,
totalPages: 0,
};
mockApplicationService.listShares.mockResolvedValue(mockResult);
const query = {
partyId: 'user123-server',
page: 1,
limit: 10,
};
const result = await controller.listShares(query);
expect(mockApplicationService.listShares).toHaveBeenCalledWith({
partyId: 'user123-server',
status: undefined,
shareType: undefined,
publicKey: undefined,
page: 1,
limit: 10,
});
expect(result).toEqual(mockResult);
});
});
describe('getShareInfo', () => {
it('should call application service getShareInfo', async () => {
const mockResult = {
shareId: 'share-123',
partyId: 'user123-server',
publicKey: '03' + '0'.repeat(64),
threshold: '2-of-3',
status: 'active',
};
mockApplicationService.getShareInfo.mockResolvedValue(mockResult);
const result = await controller.getShareInfo('share-123');
expect(mockApplicationService.getShareInfo).toHaveBeenCalledWith('share-123');
expect(result).toEqual(mockResult);
});
});
describe('participateInKeygen', () => {
it('should return accepted response for async keygen', async () => {
// Mock the promise that won't resolve during the test
mockApplicationService.participateInKeygen.mockReturnValue(new Promise(() => {}));
const dto = {
sessionId: '550e8400-e29b-41d4-a716-446655440000',
partyId: 'user123-server',
joinToken: 'join-token-abc',
shareType: PartyShareType.WALLET,
userId: 'user-id-123',
};
const result = await controller.participateInKeygen(dto);
expect(result).toEqual({
message: 'Keygen participation started',
sessionId: dto.sessionId,
partyId: dto.partyId,
});
});
});
describe('participateInKeygenSync', () => {
it('should call application service and return result', async () => {
const mockResult = {
shareId: 'share-123',
publicKey: '03' + '0'.repeat(64),
threshold: '2-of-3',
sessionId: '550e8400-e29b-41d4-a716-446655440000',
partyId: 'user123-server',
};
mockApplicationService.participateInKeygen.mockResolvedValue(mockResult);
const dto = {
sessionId: '550e8400-e29b-41d4-a716-446655440000',
partyId: 'user123-server',
joinToken: 'join-token-abc',
shareType: PartyShareType.WALLET,
userId: 'user-id-123',
};
const result = await controller.participateInKeygenSync(dto);
expect(mockApplicationService.participateInKeygen).toHaveBeenCalledWith({
sessionId: dto.sessionId,
partyId: dto.partyId,
joinToken: dto.joinToken,
shareType: dto.shareType,
userId: dto.userId,
});
expect(result).toEqual(mockResult);
});
});
describe('participateInSigning', () => {
it('should return accepted response for async signing', async () => {
// Mock the promise that won't resolve during the test
mockApplicationService.participateInSigning.mockReturnValue(new Promise(() => {}));
const dto = {
sessionId: '550e8400-e29b-41d4-a716-446655440000',
partyId: 'user123-server',
joinToken: 'join-token-abc',
messageHash: 'a'.repeat(64),
publicKey: '03' + '0'.repeat(64),
};
const result = await controller.participateInSigning(dto);
expect(result).toEqual({
message: 'Signing participation started',
sessionId: dto.sessionId,
partyId: dto.partyId,
});
});
});
describe('participateInSigningSync', () => {
it('should call application service and return result', async () => {
const mockResult = {
signature: '0'.repeat(128),
messageHash: 'a'.repeat(64),
publicKey: '03' + '0'.repeat(64),
};
mockApplicationService.participateInSigning.mockResolvedValue(mockResult);
const dto = {
sessionId: '550e8400-e29b-41d4-a716-446655440000',
partyId: 'user123-server',
joinToken: 'join-token-abc',
messageHash: 'a'.repeat(64),
publicKey: '03' + '0'.repeat(64),
};
const result = await controller.participateInSigningSync(dto);
expect(mockApplicationService.participateInSigning).toHaveBeenCalledWith({
sessionId: dto.sessionId,
partyId: dto.partyId,
joinToken: dto.joinToken,
messageHash: dto.messageHash,
publicKey: dto.publicKey,
});
expect(result).toEqual(mockResult);
});
});
describe('rotateShare', () => {
it('should return accepted response for async rotation', async () => {
// Mock the promise that won't resolve during the test
mockApplicationService.rotateShare.mockReturnValue(new Promise(() => {}));
const dto = {
sessionId: '550e8400-e29b-41d4-a716-446655440000',
partyId: 'user123-server',
joinToken: 'join-token-abc',
publicKey: '03' + '0'.repeat(64),
};
const result = await controller.rotateShare(dto);
expect(result).toEqual({
message: 'Share rotation started',
sessionId: dto.sessionId,
partyId: dto.partyId,
});
});
});
});