import 'package:flutter_test/flutter_test.dart'; import 'package:iop_client/client_bootstrap.dart'; import 'package:iop_client/main.dart'; import 'package:iop_client/src/integrations/nexo/nexo_notification_client.dart'; import 'package:iop_client/src/integrations/nexo/nexo_notification_host_integration.dart'; import 'widget_test.dart'; /// Fake NexoNotificationClient that does not reach out to Firebase/FCM. /// Includes `initializedForTest` for test verification. class _TestFakeNexoClient implements NexoNotificationClient { bool _initialized = false; bool get initializedForTest => _initialized; @override Stream> get onNotification => const Stream>.empty(); @override Future initialize() async { _initialized = true; } @override Future getDeviceToken() async => null; @override Future setAuthToken( String serverUrl, String token, { String? identifier, }) async {} @override Future setSigningKey(String serverUrl, String signingKey) async {} @override set onDeviceTokenReady(Future Function(String token)? callback) {} @override set onNavigateToChannel( void Function(String serverUrl, String channelId)? callback, ) {} @override set onNavigateToThread( void Function(String serverUrl, String rootId)? callback, ) {} } void main() { testWidgets('runIopClient can skip external integrations', ( WidgetTester tester, ) async { const options = IopClientBootstrapOptions( initializeFirebase: false, initializeNotifications: false, ); // This should run without any exceptions await bootstrapIopClient(options: options); final fakeClient = FakeClientWireClient(shouldSuccess: true); // Verify it doesn't fail basic widget pump await tester.pumpWidget( IopClientApp(testClient: fakeClient, statusRepository: null), ); expect(find.byType(IopClientApp), findsOneWidget); }); testWidgets('bootstrap initializes Nexo notification host by default', ( WidgetTester tester, ) async { // Default initializeNotifications = true, but with fake host to avoid // Firebase/FCM plugin calls in test environment. final fakeHost = NexoNotificationHostIntegration( pushClient: _TestFakeNexoClient(), ); final testOptions = IopClientBootstrapOptions( initializeFirebase: false, notificationHost: fakeHost, ); await bootstrapIopClient(options: testOptions); // Verify the provided host is initialized expect(fakeHost.isInitialized, isTrue); }); testWidgets('bootstrap skips notification when disabled', ( WidgetTester tester, ) async { final fakeHost = NexoNotificationHostIntegration( pushClient: _TestFakeNexoClient(), ); const options = IopClientBootstrapOptions( initializeFirebase: false, initializeNotifications: false, ); await bootstrapIopClient( options: IopClientBootstrapOptions( initializeFirebase: options.initializeFirebase, initializeNotifications: options.initializeNotifications, notificationHost: fakeHost, ), ); expect(fakeHost.isInitialized, isFalse); }); testWidgets('bootstrap accepts custom NexoNotificationHostIntegration', ( WidgetTester tester, ) async { final customHost = NexoNotificationHostIntegration( pushClient: _TestFakeNexoClient(), ); final testOptions = IopClientBootstrapOptions( initializeFirebase: false, notificationHost: customHost, ); await bootstrapIopClient(options: testOptions); expect(customHost.isInitialized, isTrue); }); testWidgets('bootstrap initializes with injected host without requiring ' 'auth login or credential assets', (WidgetTester tester) async { final fakeClient = _TestFakeNexoClient(); final fakeHost = NexoNotificationHostIntegration(pushClient: fakeClient); final testOptions = IopClientBootstrapOptions( initializeFirebase: false, notificationHost: fakeHost, ); // This must succeed without looking for external push credentials. await bootstrapIopClient(options: testOptions); expect(fakeHost.isInitialized, isTrue); expect(fakeClient.initializedForTest, isTrue); }); }