group_messages_provider_test.dart
1 import 'dart:typed_data'; 2 3 import 'package:dead_drop/providers/groups_provider.dart'; 4 import 'package:dead_drop/providers/messages_provider.dart' show bytesToHex; 5 import 'package:dead_drop/services/dead_drop_service.dart'; 6 import 'package:flutter_riverpod/flutter_riverpod.dart'; 7 import 'package:flutter_test/flutter_test.dart'; 8 import 'package:mocktail/mocktail.dart'; 9 10 import '../fixtures/test_fixtures.dart'; 11 import '../helpers/test_helpers.dart'; 12 import '../mocks/mock_dead_drop_service.dart'; 13 14 class MockUninitializedService extends MockDeadDropService { 15 @override 16 bool get isInitialized => false; 17 } 18 19 void main() { 20 late MockDeadDropService mockService; 21 late ProviderContainer container; 22 23 setUpAll(() { 24 registerFallbackValue(Uint8List(16)); 25 registerFallbackValue(<int>[]); 26 }); 27 28 setUp(() { 29 mockService = MockDeadDropService(); 30 }); 31 32 tearDown(() { 33 container.dispose(); 34 }); 35 36 group('GroupMessagesNotifier', () { 37 test('build() returns empty list when service not initialized', () async { 38 final uninitService = MockUninitializedService(); 39 40 final groupIdHex = bytesToHex(TestFixtures.groupId(1)); 41 container = createTestContainer(mockService: uninitService); 42 final result = 43 await container.read(groupMessagesProvider(groupIdHex).future); 44 45 expect(result, isEmpty); 46 }); 47 48 test('build() returns group messages from service', () async { 49 final groupId = TestFixtures.groupId(1); 50 final groupIdHex = bytesToHex(groupId); 51 final msg1 = TestFixtures.messageInfo( 52 messageIdBytes: TestFixtures.messageId(1), 53 groupIdBytes: groupId, 54 ); 55 final msg2 = TestFixtures.messageInfo( 56 messageIdBytes: TestFixtures.messageId(2), 57 groupIdBytes: groupId, 58 ); 59 60 when(() => mockService.getGroupConversation(any())) 61 .thenReturn([msg1, msg2]); 62 63 container = createTestContainer(mockService: mockService); 64 final result = 65 await container.read(groupMessagesProvider(groupIdHex).future); 66 67 expect(result, hasLength(2)); 68 verify(() => mockService.getGroupConversation(any())).called(1); 69 }); 70 71 test('sendText() calls sendGroupMessage and refreshes state', () async { 72 final groupId = TestFixtures.groupId(1); 73 final groupIdHex = bytesToHex(groupId); 74 75 when(() => mockService.getGroupConversation(any())).thenReturn([]); 76 when(() => mockService.sendGroupMessage(any(), any(), any())) 77 .thenAnswer((_) async => TestFixtures.messageId(10)); 78 when(() => mockService.getGroupMembers(any())).thenReturn([]); 79 80 container = createTestContainer(mockService: mockService); 81 await container.read(groupMessagesProvider(groupIdHex).future); 82 83 await container 84 .read(groupMessagesProvider(groupIdHex).notifier) 85 .sendText('Hello group'); 86 87 verify(() => mockService.sendGroupMessage(any(), any(), ContentType.text)) 88 .called(1); 89 // getGroupConversation called: once for build, once for refresh 90 verify(() => mockService.getGroupConversation(any())).called(2); 91 }); 92 93 test('sendDocument() calls sendGroupDocument and refreshes state', 94 () async { 95 final groupId = TestFixtures.groupId(1); 96 final groupIdHex = bytesToHex(groupId); 97 final content = Uint8List.fromList([1, 2, 3]); 98 99 when(() => mockService.getGroupConversation(any())).thenReturn([]); 100 when(() => mockService.sendGroupDocument(any(), any(), any())) 101 .thenAnswer((_) async => TestFixtures.messageId(20)); 102 when(() => mockService.getGroupMembers(any())).thenReturn([]); 103 104 container = createTestContainer(mockService: mockService); 105 await container.read(groupMessagesProvider(groupIdHex).future); 106 107 await container 108 .read(groupMessagesProvider(groupIdHex).notifier) 109 .sendDocument(content, 'test.pdf'); 110 111 verify(() => mockService.sendGroupDocument(any(), any(), 'test.pdf')) 112 .called(1); 113 verify(() => mockService.getGroupConversation(any())).called(2); 114 }); 115 116 test('refresh() reloads messages from service', () async { 117 final groupId = TestFixtures.groupId(1); 118 final groupIdHex = bytesToHex(groupId); 119 120 when(() => mockService.getGroupConversation(any())).thenReturn([]); 121 122 container = createTestContainer(mockService: mockService); 123 await container.read(groupMessagesProvider(groupIdHex).future); 124 125 // Add a message for next fetch 126 final msg = TestFixtures.messageInfo(groupIdBytes: groupId); 127 when(() => mockService.getGroupConversation(any())).thenReturn([msg]); 128 129 await container 130 .read(groupMessagesProvider(groupIdHex).notifier) 131 .refresh(); 132 133 final result = container.read(groupMessagesProvider(groupIdHex)).value; 134 expect(result, hasLength(1)); 135 }); 136 }); 137 138 group('groupMembersProvider', () { 139 test('returns members from service', () { 140 final groupId = TestFixtures.groupId(1); 141 final groupIdHex = bytesToHex(groupId); 142 final member1 = TestFixtures.groupMemberInfo( 143 contactIdBytes: TestFixtures.contactId(1), 144 nickname: 'Alice', 145 role: 1, 146 ); 147 final member2 = TestFixtures.groupMemberInfo( 148 contactIdBytes: TestFixtures.contactId(2), 149 nickname: 'Bob', 150 ); 151 152 when(() => mockService.getGroupMembers(any())) 153 .thenReturn([member1, member2]); 154 155 container = createTestContainer(mockService: mockService); 156 final result = container.read(groupMembersProvider(groupIdHex)); 157 158 expect(result, hasLength(2)); 159 expect(result[0].nickname, equals('Alice')); 160 expect(result[0].role, equals(1)); 161 expect(result[1].nickname, equals('Bob')); 162 expect(result[1].role, equals(0)); 163 }); 164 165 test('returns empty list when service not initialized', () { 166 final uninitService = MockUninitializedService(); 167 168 final groupIdHex = bytesToHex(TestFixtures.groupId(1)); 169 container = createTestContainer(mockService: uninitService); 170 final result = container.read(groupMembersProvider(groupIdHex)); 171 172 expect(result, isEmpty); 173 }); 174 }); 175 }