import 'dart:io'; import 'package:flutter_test/flutter_test.dart'; import 'package:ikar/backend/modules/chats.dart'; import 'package:ikar/backend/modules/messages.dart'; import 'package:ikar/core/storage/app_database.dart'; import 'package:ikar/models/attachment.dart'; import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; import 'package:plugin_platform_interface/plugin_platform_interface.dart'; class _SyntheticPathProvider extends PathProviderPlatform with MockPlatformInterfaceMixin { _SyntheticPathProvider(this.directory); final String directory; @override Future getApplicationSupportPath() async => directory; } void main() { TestWidgetsFlutterBinding.ensureInitialized(); setUp(() async { final dir = Directory.systemTemp.createTempSync('qlyra_outgoing_preview'); PathProviderPlatform.instance = _SyntheticPathProvider(dir.path); addTearDown(() async { await AppDatabase.close(); dir.deleteSync(recursive: true); }); await AppDatabase.init(); await AppDatabase.saveProfile( ProfileData( id: 77, firstName: 'Test', phone: 100000, country: 'ZZ', accountStatus: 0, updateTime: 1, ), isActive: true, ); await AppDatabase.saveChats([ CachedChat( id: 42, accountId: 77, type: 'DIALOG', title: 'Test', lastMsgTime: 0, unreadCount: 0, lastEventTime: 0, cachedAt: 0, dontDisturbUntil: ChatsModule.muteOff, isOnline: false, seenTime: 0, participants: {77: 0, 88: 0}, ).toDbRow(), ]); }); CachedMessage message(String id, int time, {int e2ee = 0}) => CachedMessage( id: id, accountId: 77, chatId: 42, senderId: 77, time: time, text: 'Private caption', e2ee: e2ee, status: 'sending', attachments: [const PhotoAttachment(localPath: '/tmp/photo.jpg')], ); Future row() async => CachedChat.fromDbRow((await AppDatabase.loadChat(77, 42)).single); test( 'sending, error and sent persist without a mounted chat screen', () async { final module = chats; await module.applyOutgoingMessage( message('temp_one', 100), status: 'sending', ); expect((await row()).lastMsgStatus, 'sending'); expect((await row()).lastMsgPreview, contains('file:')); await module.applyOutgoingMessage( message('temp_one', 100), status: 'error', ); expect((await row()).lastMsgStatus, 'error'); await module.applyOutgoingMessage(message('900', 101), status: 'sent'); expect((await row()).lastMsgId, 900); expect((await row()).lastMsgStatus, 'sent'); }, ); test( 'a stale pending upload does not replace a newer pending preview', () async { final module = chats; await module.applyOutgoingMessage( message('temp_new', 200), status: 'sending', ); await module.applyOutgoingMessage( message('temp_old', 100), status: 'error', ); expect((await row()).lastMsgTime, 200); expect((await row()).lastMsgStatus, 'sending'); }, ); test('encrypted caption is excluded from persisted chat preview', () async { await chats.applyOutgoingMessage( message('temp_secret', 100, e2ee: CachedMessage.e2eeFile), status: 'sending', ); final chat = await row(); expect(chat.lastMsgText, isNot(contains('Private caption'))); expect(chat.lastMsgPreview, isNot(contains('Private caption'))); }); }