238 lines
7.2 KiB
TypeScript
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,
|
|
});
|
|
});
|
|
});
|
|
});
|