import 'package:commons_core/commons_core.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:tane/services/inbox_service.dart'; import 'package:tane/services/message_store.dart'; import 'package:tane/services/social_service.dart'; import 'package:tane/services/social_settings.dart'; import '../support/test_support.dart'; /// The app-wide inbox listener persists incoming messages and announces changes, /// so the inbox list refreshes even when the specific chat isn't open. Driven /// through the [InboxService.ingest] seam so no relay/network is involved. void main() { const seedHex = '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f'; late MessageStore store; late InboxService inbox; setUp(() async { store = MessageStore(InMemorySecretStore()); inbox = InboxService( social: await SocialService.fromRootSeedHex(seedHex), settings: SocialSettings(InMemorySecretStore()), store: store, ); }); tearDown(() => inbox.stop()); PrivateMessage msg(String from, String text, int atMs) => PrivateMessage( fromPubkey: from, text: text, at: DateTime.fromMillisecondsSinceEpoch(atMs)); test('an incoming message is persisted into its conversation', () async { await inbox.ingest(msg('alice', 'got seeds?', 1000)); final convos = await store.conversations(); expect(convos.single.peerPubkey, 'alice'); expect(convos.single.lastText, 'got seeds?'); }); test('a new message announces a change; a duplicate stays silent', () async { final changes = []; final sub = inbox.changes.listen(changes.add); await inbox.ingest(msg('alice', 'hola', 1000)); await inbox.ingest(msg('alice', 'hola', 1000)); // relay re-delivery await Future.delayed(Duration.zero); // let the broadcast flush expect(changes, hasLength(1)); // only the first, new one fired expect(await store.history('alice'), hasLength(1)); await sub.cancel(); }); }