/** * 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); }); 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, }); }); }); });