import 'package:drift/drift.dart' hide isNotNull, isNull; import 'package:drift/native.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:twonly/locator.dart'; import 'package:twonly/src/database/tables/messages.table.dart'; import 'package:twonly/src/database/twonly.db.dart'; import 'package:twonly/src/model/json/userdata.model.dart'; import 'package:twonly/src/services/user.service.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); setUp(() async { await locator.reset(); locator ..registerSingleton( TwonlyDB.forTesting( DatabaseConnection( NativeDatabase.memory(), closeStreamsSynchronously: true, ), ), ) ..registerSingleton(UserService()); userService.currentUser = UserData( userId: 1, username: 'test_user', displayName: 'Test User', subscriptionPlan: 'Free', currentSetupPage: null, appVersion: 100, ); userService.isUserCreated = true; }); tearDown(() async { await twonlyDB.close(); }); test( 'watchByGroupId stream emits updates when a new text message is inserted', () async { // 1. Create a group await twonlyDB.groupsDao.createNewGroup( GroupsCompanion.insert( groupId: 'test_group_stream', groupName: 'Test Group Stream', ), ); // 2. Start watching final stream = await twonlyDB.messagesDao.watchByGroupId( 'test_group_stream', ); final emissions = >[]; final subscription = stream.listen(emissions.add); // Wait briefly for initial empty emission await Future.delayed(const Duration(milliseconds: 100)); expect(emissions, hasLength(1)); expect(emissions.first, isEmpty); // 3. Insert a message await twonlyDB.messagesDao.insertMessage( MessagesCompanion.insert( messageId: 'msg_1', groupId: 'test_group_stream', type: 'text', content: const Value('Hello world'), ), ); // Wait for the stream to propagate the event await Future.delayed(const Duration(milliseconds: 100)); // Verify it emitted the new list containing our message expect(emissions, hasLength(2)); expect(emissions[1], hasLength(1)); expect(emissions[1].first.messageId, equals('msg_1')); await subscription.cancel(); }, ); test( 'simulate sending flow with group updates and verify messages stream emits', () async { await twonlyDB.groupsDao.createNewGroup( GroupsCompanion.insert( groupId: 'test_group_2', groupName: 'Test Group 2', ), ); final msgStream = await twonlyDB.messagesDao.watchByGroupId( 'test_group_2', ); final messagesEmissions = >[]; final msgSub = msgStream.listen(messagesEmissions.add); final groupStream = twonlyDB.groupsDao.watchGroup('test_group_2'); final groupEmissions = []; final groupSub = groupStream.listen(groupEmissions.add); await Future.delayed(const Duration(milliseconds: 100)); expect(messagesEmissions, hasLength(1)); expect(groupEmissions, hasLength(1)); // Simulate sending: // 1. Update group draftMessage to null (as done in insertAndSendTextMessage) await twonlyDB.groupsDao.updateGroup( 'test_group_2', const GroupsCompanion( draftMessage: Value(null), ), ); // 2. Insert message final message = await twonlyDB.messagesDao.insertMessage( MessagesCompanion( groupId: const Value('test_group_2'), content: const Value('Hello from simulation'), type: Value(MessageType.text.name), ), ); expect(message, isNotNull); await Future.delayed(const Duration(milliseconds: 100)); // Verify group stream received updates expect(groupEmissions.length, greaterThan(1)); // Verify message stream received updates containing the new message expect(messagesEmissions.length, greaterThan(1)); expect( messagesEmissions.last.any((m) => m.messageId == message!.messageId), isTrue, ); await msgSub.cancel(); await groupSub.cancel(); }, ); }