128 lines
4.6 KiB
TypeScript
128 lines
4.6 KiB
TypeScript
import { Test, TestingModule } from '@nestjs/testing';
|
|
import { StoreBackupShareHandler } from '../../../src/application/commands/store-backup-share/store-backup-share.handler';
|
|
import { StoreBackupShareCommand } from '../../../src/application/commands/store-backup-share/store-backup-share.command';
|
|
import { BACKUP_SHARE_REPOSITORY } from '../../../src/domain';
|
|
import { AesEncryptionService } from '../../../src/infrastructure/crypto/aes-encryption.service';
|
|
import { AuditLogRepository } from '../../../src/infrastructure/persistence/repositories/audit-log.repository';
|
|
import { ApplicationError } from '../../../src/application/errors/application.error';
|
|
|
|
describe('StoreBackupShareHandler', () => {
|
|
let handler: StoreBackupShareHandler;
|
|
let mockRepository: any;
|
|
let mockEncryptionService: any;
|
|
let mockAuditLogRepository: any;
|
|
|
|
beforeEach(async () => {
|
|
mockRepository = {
|
|
findByUserId: jest.fn(),
|
|
findByPublicKey: jest.fn(),
|
|
save: jest.fn(),
|
|
};
|
|
|
|
mockEncryptionService = {
|
|
encrypt: jest.fn().mockResolvedValue({
|
|
encrypted: 'double-encrypted-data',
|
|
keyId: 'key-v1',
|
|
}),
|
|
};
|
|
|
|
mockAuditLogRepository = {
|
|
log: jest.fn().mockResolvedValue(undefined),
|
|
};
|
|
|
|
const module: TestingModule = await Test.createTestingModule({
|
|
providers: [
|
|
StoreBackupShareHandler,
|
|
{ provide: BACKUP_SHARE_REPOSITORY, useValue: mockRepository },
|
|
{ provide: AesEncryptionService, useValue: mockEncryptionService },
|
|
{ provide: AuditLogRepository, useValue: mockAuditLogRepository },
|
|
],
|
|
}).compile();
|
|
|
|
handler = module.get<StoreBackupShareHandler>(StoreBackupShareHandler);
|
|
});
|
|
|
|
it('should be defined', () => {
|
|
expect(handler).toBeDefined();
|
|
});
|
|
|
|
describe('execute', () => {
|
|
const validCommand = new StoreBackupShareCommand(
|
|
'12345',
|
|
1001,
|
|
'02' + 'a'.repeat(64),
|
|
'encrypted-share-data',
|
|
'identity-service',
|
|
'127.0.0.1',
|
|
);
|
|
|
|
it('should store backup share successfully', async () => {
|
|
mockRepository.findByUserId.mockResolvedValue(null);
|
|
mockRepository.findByPublicKey.mockResolvedValue(null);
|
|
mockRepository.save.mockImplementation((share: any) => {
|
|
share.setShareId(BigInt(1));
|
|
return Promise.resolve(share);
|
|
});
|
|
|
|
const result = await handler.execute(validCommand);
|
|
|
|
expect(result.shareId).toBe('1');
|
|
expect(mockRepository.findByUserId).toHaveBeenCalledWith(BigInt(12345));
|
|
expect(mockRepository.findByPublicKey).toHaveBeenCalledWith(validCommand.publicKey);
|
|
expect(mockEncryptionService.encrypt).toHaveBeenCalledWith(validCommand.encryptedShareData);
|
|
expect(mockRepository.save).toHaveBeenCalled();
|
|
expect(mockAuditLogRepository.log).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
action: 'STORE',
|
|
success: true,
|
|
}),
|
|
);
|
|
});
|
|
|
|
it('should throw error if share already exists for user', async () => {
|
|
mockRepository.findByUserId.mockResolvedValue({ userId: BigInt(12345) });
|
|
|
|
await expect(handler.execute(validCommand)).rejects.toThrow(ApplicationError);
|
|
await expect(handler.execute(validCommand)).rejects.toThrow(
|
|
'Backup share already exists for this user',
|
|
);
|
|
});
|
|
|
|
it('should throw error if share already exists for public key', async () => {
|
|
mockRepository.findByUserId.mockResolvedValue(null);
|
|
mockRepository.findByPublicKey.mockResolvedValue({ publicKey: validCommand.publicKey });
|
|
|
|
await expect(handler.execute(validCommand)).rejects.toThrow(ApplicationError);
|
|
await expect(handler.execute(validCommand)).rejects.toThrow(
|
|
'Backup share already exists for this public key',
|
|
);
|
|
});
|
|
|
|
it('should use custom threshold and totalParties if provided', async () => {
|
|
mockRepository.findByUserId.mockResolvedValue(null);
|
|
mockRepository.findByPublicKey.mockResolvedValue(null);
|
|
mockRepository.save.mockImplementation((share: any) => {
|
|
share.setShareId(BigInt(1));
|
|
expect(share.threshold).toBe(3);
|
|
expect(share.totalParties).toBe(5);
|
|
return Promise.resolve(share);
|
|
});
|
|
|
|
const commandWithCustomParams = new StoreBackupShareCommand(
|
|
'12345',
|
|
1001,
|
|
'02' + 'a'.repeat(64),
|
|
'encrypted-share-data',
|
|
'identity-service',
|
|
'127.0.0.1',
|
|
3, // threshold
|
|
5, // totalParties
|
|
);
|
|
|
|
await handler.execute(commandWithCustomParams);
|
|
|
|
expect(mockRepository.save).toHaveBeenCalled();
|
|
});
|
|
});
|
|
});
|