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); }); 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(); }); }); });