import 'package:flutter_test/flutter_test.dart'; import 'package:immich_mobile/domain/services/partner.service.dart'; import 'package:mocktail/mocktail.dart'; import '../service_context.dart'; void main() { late MediumServiceContext ctx; late PartnerService sut; setUp(() { ctx = MediumServiceContext(); sut = PartnerService(ctx.userRepository, ctx.partnerRepository, ctx.partnerApi); }); tearDown(() async { await ctx.dispose(); }); group('getCandidates', () { test('returns the other users and excludes the current user', () async { final me = await ctx.newUser(); final other = await ctx.newUser(); final result = await sut.getCandidates(me.id).first; expect(result.map((user) => user.id), unorderedEquals([other.id])); }); test('excludes users the current user already shares with', () async { final me = await ctx.newUser(); final partner = await ctx.newUser(); final other = await ctx.newUser(); await ctx.newPartner(sharedById: me.id, sharedWithId: partner.id); final result = await sut.getCandidates(me.id).first; expect(result.map((user) => user.id), unorderedEquals([other.id])); }); test('includes users who share with the current user but are not shared with back', () async { final me = await ctx.newUser(); final inbound = await ctx.newUser(); await ctx.newPartner(sharedById: inbound.id, sharedWithId: me.id); final result = await sut.getCandidates(me.id).first; expect(result.map((user) => user.id), unorderedEquals([inbound.id])); }); test('emits an updated list when the current user adds a partner', () async { final me = await ctx.newUser(); final a = await ctx.newUser(); final b = await ctx.newUser(); final ids = sut.getCandidates(me.id).map((users) => users.map((user) => user.id).toList()); final expectation = expectLater( ids, emitsInOrder([ unorderedEquals([a.id, b.id]), unorderedEquals([b.id]), ]), ); await ctx.newPartner(sharedById: me.id, sharedWithId: a.id); await expectation; }); }); group('create', () { test('calls the API then persists the partnership locally', () async { final me = await ctx.newUser(); final partner = await ctx.newUser(); await sut.create(sharedById: me.id, sharedWithId: partner.id); verify(() => ctx.partnerApi.create(partner.id)).called(1); final shared = await sut.search(me.id, .sharedBy).first; expect(shared.map((p) => p.id), unorderedEquals([partner.id])); }); }); group('delete', () { test('calls the API then removes the partnership locally', () async { final me = await ctx.newUser(); final recipient = await ctx.newUser(); await ctx.newPartner(sharedById: me.id, sharedWithId: recipient.id); await sut.delete(sharedById: me.id, sharedWithId: recipient.id); verify(() => ctx.partnerApi.delete(recipient.id)).called(1); final shared = await sut.search(me.id, .sharedBy).first; expect(shared, isEmpty); }); }); group('update', () { test('calls the API then updates the inTimeline flag locally', () async { final me = await ctx.newUser(); final sharer = await ctx.newUser(); await ctx.newPartner(sharedById: sharer.id, sharedWithId: me.id, inTimeline: false); await sut.update(sharedById: sharer.id, sharedWithId: me.id, inTimeline: true); verify(() => ctx.partnerApi.update(sharer.id, inTimeline: true)).called(1); final partner = await ctx.partnerRepository.get(sharedById: sharer.id, sharedWithId: me.id); expect(partner.inTimeline, isTrue); }); }); }