/** * PartyShare Repository Integration Tests */ import { Test, TestingModule } from '@nestjs/testing'; import { PartyShareRepositoryImpl } from '../../src/infrastructure/persistence/repositories/party-share.repository.impl'; import { PartyShareMapper } from '../../src/infrastructure/persistence/mappers/party-share.mapper'; import { PrismaService } from '../../src/infrastructure/persistence/prisma/prisma.service'; import { PartyShare } from '../../src/domain/entities/party-share.entity'; import { ShareId, PartyId, SessionId, Threshold, ShareData, PublicKey, } from '../../src/domain/value-objects'; import { PartyShareType, PartyShareStatus } from '../../src/domain/enums'; describe('PartyShareRepository (Integration)', () => { let repository: PartyShareRepositoryImpl; let prismaService: any; let mapper: PartyShareMapper; const createMockShare = (): PartyShare => { return PartyShare.create({ partyId: PartyId.create('user123-server'), sessionId: SessionId.generate(), shareType: PartyShareType.WALLET, shareData: ShareData.create( Buffer.from('encrypted-test-share-data'), Buffer.from('123456789012'), Buffer.from('1234567890123456'), ), publicKey: PublicKey.fromHex('03' + '0'.repeat(64)), threshold: Threshold.create(3, 2), }); }; beforeEach(async () => { prismaService = { partyShare: { findUnique: jest.fn(), findFirst: jest.fn(), findMany: jest.fn(), create: jest.fn(), update: jest.fn(), delete: jest.fn(), count: jest.fn(), }, $transaction: jest.fn((fn: any) => fn(prismaService)), }; mapper = new PartyShareMapper(); const module: TestingModule = await Test.createTestingModule({ providers: [ PartyShareRepositoryImpl, { provide: PrismaService, useValue: prismaService }, PartyShareMapper, ], }).compile(); repository = module.get(PartyShareRepositoryImpl); }); describe('save', () => { it('should save a new share', async () => { const share = createMockShare(); const persistenceData = mapper.toPersistence(share); prismaService.partyShare.create.mockResolvedValue({ ...persistenceData, id: share.id.value, }); await repository.save(share); expect(prismaService.partyShare.create).toHaveBeenCalled(); }); }); describe('update', () => { it('should update an existing share', async () => { const share = createMockShare(); const persistenceData = mapper.toPersistence(share); prismaService.partyShare.update.mockResolvedValue({ ...persistenceData, id: share.id.value, }); await repository.update(share); expect(prismaService.partyShare.update).toHaveBeenCalled(); }); }); describe('findById', () => { it('should return share when found', async () => { const share = createMockShare(); const persistenceData = mapper.toPersistence(share); prismaService.partyShare.findUnique.mockResolvedValue({ ...persistenceData, id: share.id.value, }); const result = await repository.findById(share.id); expect(result).toBeDefined(); expect(result).toBeInstanceOf(PartyShare); }); it('should return null when not found', async () => { prismaService.partyShare.findUnique.mockResolvedValue(null); const result = await repository.findById(ShareId.generate()); expect(result).toBeNull(); }); }); describe('findByPartyId', () => { it('should return all shares for party', async () => { const share = createMockShare(); const persistenceData = mapper.toPersistence(share); prismaService.partyShare.findMany.mockResolvedValue([ { ...persistenceData, id: share.id.value }, ]); const result = await repository.findByPartyId(PartyId.create('user123-server')); expect(result).toHaveLength(1); result.forEach((s) => { expect(s).toBeInstanceOf(PartyShare); }); }); it('should return empty array when no shares', async () => { prismaService.partyShare.findMany.mockResolvedValue([]); const result = await repository.findByPartyId(PartyId.create('nonexistent-party')); expect(result).toHaveLength(0); }); }); describe('findByPublicKey', () => { it('should return share when found', async () => { const share = createMockShare(); const persistenceData = mapper.toPersistence(share); prismaService.partyShare.findFirst.mockResolvedValue({ ...persistenceData, id: share.id.value, }); const result = await repository.findByPublicKey( PublicKey.fromHex('03' + '0'.repeat(64)), ); expect(result).toBeDefined(); expect(result).toBeInstanceOf(PartyShare); }); it('should return null when not found', async () => { prismaService.partyShare.findFirst.mockResolvedValue(null); const result = await repository.findByPublicKey( PublicKey.fromHex('03' + '1'.repeat(64)), ); expect(result).toBeNull(); }); }); describe('findBySessionId', () => { it('should return shares for session', async () => { const share = createMockShare(); const persistenceData = mapper.toPersistence(share); prismaService.partyShare.findMany.mockResolvedValue([ { ...persistenceData, id: share.id.value }, ]); const result = await repository.findBySessionId(share.sessionId); expect(result).toHaveLength(1); }); }); describe('delete', () => { it('should soft delete share by updating status to revoked', async () => { const shareId = ShareId.generate(); prismaService.partyShare.update.mockResolvedValue({}); await repository.delete(shareId); expect(prismaService.partyShare.update).toHaveBeenCalledWith({ where: { id: shareId.value }, data: { status: PartyShareStatus.REVOKED, updatedAt: expect.any(Date), }, }); }); }); });