From 6c7c03041f53ad2602a856c0ffc704fc413c9ce0 Mon Sep 17 00:00:00 2001 From: Satyam Jha Date: Fri, 17 Jan 2025 18:06:53 +0530 Subject: [PATCH] Migrated from uni_links to app_links package --- lib/locator.dart | 4 + lib/splash_screen.dart | 10 +- pubspec.lock | 64 ++- pubspec.yaml | 4 +- test/helpers/test_locator.dart | 4 + .../pre_auth_screens/splash_screen_test.dart | 521 ++++++++++-------- .../splash_screen_test.mocks.dart | 327 +++++++++++ 7 files changed, 677 insertions(+), 257 deletions(-) create mode 100644 test/widget_tests/pre_auth_screens/splash_screen_test.mocks.dart diff --git a/lib/locator.dart b/lib/locator.dart index 15e156508..8e1e7b709 100644 --- a/lib/locator.dart +++ b/lib/locator.dart @@ -1,3 +1,4 @@ +import 'package:app_links/app_links.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:get_it/get_it.dart'; import 'package:image_cropper/image_cropper.dart'; @@ -177,4 +178,7 @@ Future setupLocator() async { locator.registerFactory(() => DirectChatViewModel()); locator.registerFactory(() => AccessScreenViewModel()); locator.registerFactory(() => UserProfileService()); + + //AppLinks + locator.registerSingleton(AppLinks()); } diff --git a/lib/splash_screen.dart b/lib/splash_screen.dart index 89290d1ee..5ac1a0614 100644 --- a/lib/splash_screen.dart +++ b/lib/splash_screen.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:app_links/app_links.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:talawa/constants/routing_constants.dart'; @@ -8,7 +9,6 @@ import 'package:talawa/locator.dart'; import 'package:talawa/models/mainscreen_navigation_args.dart'; import 'package:talawa/services/size_config.dart'; import 'package:talawa/utils/app_localization.dart'; -import 'package:uni_links/uni_links.dart'; /// This widget return the SplashScreen. Splash Screen is the first screen that we see when we run our application. It is also known as Launch Screen. class SplashScreen extends StatefulWidget { @@ -43,7 +43,9 @@ class _SplashScreenState extends State { /// **returns**: /// None Future _handleInitialUri() async { - _sub = uriLinkStream.listen( + final appLinks = locator(); + + _sub = appLinks.uriLinkStream.listen( (Uri? uri) { // After creating a State object and before calling initState, the framework // "mounts" the State object by associating it with a BuildContext. @@ -60,8 +62,8 @@ class _SplashScreenState extends State { }, ); try { - // Retrieving the initial URI from getInitialUri function. - final uri = await getInitialUri(); + // Retrieving the initial URI from getInitialLink function. + final uri = await appLinks.getInitialLink(); if (!mounted) return; setState(() => _initialUri = uri); } on PlatformException { diff --git a/pubspec.lock b/pubspec.lock index 81be681f3..08cedc70b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -25,6 +25,38 @@ packages: url: "https://pub.dev" source: hosted version: "0.11.3" + app_links: + dependency: "direct main" + description: + name: app_links + sha256: "433df2e61b10519407475d7f69e470789d23d593f28224c38ba1068597be7950" + url: "https://pub.dev" + source: hosted + version: "6.3.3" + app_links_linux: + dependency: transitive + description: + name: app_links_linux + sha256: f5f7173a78609f3dfd4c2ff2c95bd559ab43c80a87dc6a095921d96c05688c81 + url: "https://pub.dev" + source: hosted + version: "1.0.3" + app_links_platform_interface: + dependency: "direct main" + description: + name: app_links_platform_interface + sha256: "05f5379577c513b534a29ddea68176a4d4802c46180ee8e2e966257158772a3f" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + app_links_web: + dependency: transitive + description: + name: app_links_web + sha256: af060ed76183f9e2b87510a9480e56a5352b6c249778d07bd2c95fc35632a555 + url: "https://pub.dev" + source: hosted + version: "1.0.4" args: dependency: transitive description: @@ -693,6 +725,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.1" + gtk: + dependency: transitive + description: + name: gtk + sha256: e8ce9ca4b1df106e4d72dad201d345ea1a036cc12c360f1a7d5a758f78ffa42c + url: "https://pub.dev" + source: hosted + version: "2.1.0" hive: dependency: "direct main" description: @@ -1529,30 +1569,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" - uni_links: - dependency: "direct main" - description: - name: uni_links - sha256: "051098acfc9e26a9fde03b487bef5d3d228ca8f67693480c6f33fd4fbb8e2b6e" - url: "https://pub.dev" - source: hosted - version: "0.5.1" - uni_links_platform_interface: - dependency: "direct main" - description: - name: uni_links_platform_interface - sha256: "929cf1a71b59e3b7c2d8a2605a9cf7e0b125b13bc858e55083d88c62722d4507" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - uni_links_web: - dependency: transitive - description: - name: uni_links_web - sha256: "7539db908e25f67de2438e33cc1020b30ab94e66720b5677ba6763b25f6394df" - url: "https://pub.dev" - source: hosted - version: "0.1.0" url_launcher: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index b710b071b..9b52254cc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -19,6 +19,8 @@ dependencies: # analyzer_plugin: ################################ + app_links: ^6.3.3 + app_links_platform_interface: ^2.0.2 auto_size_text: ^3.0.0 cached_network_image: ^3.4.1 clock: ^1.1.1 @@ -72,8 +74,6 @@ dependencies: syncfusion_flutter_datepicker: ^27.2.5 timelines: ^0.1.0 tutorial_coach_mark: ^1.2.12 - uni_links: ^0.5.1 - uni_links_platform_interface: ^1.0.0 url_launcher: ^6.3.1 vibration: ^2.0.1 video_player: ^2.9.2 diff --git a/test/helpers/test_locator.dart b/test/helpers/test_locator.dart index 250b9bf1c..972b6de8e 100644 --- a/test/helpers/test_locator.dart +++ b/test/helpers/test_locator.dart @@ -1,6 +1,7 @@ // ignore_for_file: talawa_api_doc // ignore_for_file: talawa_good_doc_comments +import 'package:app_links/app_links.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:get_it/get_it.dart'; import 'package:image_cropper/image_cropper.dart'; @@ -149,4 +150,7 @@ void testSetupLocator() { locator.registerFactory(() => DirectChatViewModel()); locator.registerFactory(() => SelectContactViewModel()); locator.registerFactory(() => UserProfileService()); + + //AppLinks + locator.registerSingleton(AppLinks()); } diff --git a/test/widget_tests/pre_auth_screens/splash_screen_test.dart b/test/widget_tests/pre_auth_screens/splash_screen_test.dart index 50f08eab4..8a811c736 100644 --- a/test/widget_tests/pre_auth_screens/splash_screen_test.dart +++ b/test/widget_tests/pre_auth_screens/splash_screen_test.dart @@ -3,20 +3,26 @@ // ignore_for_file: unused_import +import 'package:app_links/app_links.dart'; +import 'package:fake_async/fake_async.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'package:talawa/constants/custom_theme.dart'; import 'package:talawa/locator.dart'; import 'package:talawa/router.dart' as router; import 'package:talawa/services/size_config.dart'; +import 'package:talawa/services/user_config.dart'; import 'package:talawa/splash_screen.dart'; import 'package:talawa/utils/app_localization.dart'; import 'package:talawa/view_model/lang_view_model.dart'; import 'package:talawa/views/base_view.dart'; -import 'package:uni_links/uni_links.dart'; +import 'splash_screen_test.mocks.dart'; +@GenerateNiceMocks([MockSpec(), MockSpec()]) Widget createSplashScreenLight({ThemeMode themeMode = ThemeMode.light}) => BaseView( onModelReady: (model) => model.initialize(), @@ -64,6 +70,36 @@ Widget createSplashScreenDark({ThemeMode themeMode = ThemeMode.dark}) => ); Future main() async { + late MockAppLinks mockAppLinks; + late MockUserConfig mockUserConfig; + + setUp(() { + mockAppLinks = MockAppLinks(); + mockUserConfig = MockUserConfig(); + + // Unregister and re-register AppLinks for each test + if (locator.isRegistered()) { + locator.unregister(); + } + locator.registerSingleton(mockAppLinks); + + // Unregister and re-register UserConfig for each test + if (locator.isRegistered()) { + locator.unregister(); + } + locator.registerSingleton(mockUserConfig); + }); + + tearDown(() { + // Clean up after each test + if (locator.isRegistered()) { + locator.unregister(); + } + if (locator.isRegistered()) { + locator.unregister(); + } + }); + setUpAll(() { setupLocator(); graphqlConfig.test(); @@ -71,253 +107,284 @@ Future main() async { group('Splash Screen Widget Test in light mode', () { testWidgets("Testing if Splash Screen shows up", (tester) async { - await tester.pumpWidget(createSplashScreenLight()); - await tester.pumpAndSettle(); - final screenScaffoldWidget = - find.byKey(const Key('SplashScreenScaffold')); - expect(screenScaffoldWidget, findsOneWidget); - expect( - (tester.firstWidget(find.byKey(const Key('Root'))) as MaterialApp) - .theme! - .scaffoldBackgroundColor, - TalawaTheme.lightTheme.scaffoldBackgroundColor, - ); + await tester.runAsync(() async { + await tester.pumpWidget(createSplashScreenLight()); + await tester.pumpAndSettle(); + final screenScaffoldWidget = + find.byKey(const Key('SplashScreenScaffold')); + expect(screenScaffoldWidget, findsOneWidget); + expect( + (tester.firstWidget(find.byKey(const Key('Root'))) as MaterialApp) + .theme! + .scaffoldBackgroundColor, + TalawaTheme.lightTheme.scaffoldBackgroundColor, + ); + }); }); testWidgets("Testing if app logo shows up", (tester) async { - await tester.pumpWidget(createSplashScreenLight()); - await tester.pumpAndSettle(); - final logoWidget = find.byKey(const Key('LogoPainter')); - expect(logoWidget, findsOneWidget); - expect( - (tester.firstWidget(logoWidget) as CustomPaint).size, - Size( - SizeConfig.screenWidth! * 0.6, - SizeConfig.screenWidth! * 0.6, - ), - ); + await tester.runAsync(() async { + await tester.pumpWidget(createSplashScreenLight()); + await tester.pumpAndSettle(); + final logoWidget = find.byKey(const Key('LogoPainter')); + expect(logoWidget, findsOneWidget); + expect( + (tester.firstWidget(logoWidget) as CustomPaint).size, + Size( + SizeConfig.screenWidth! * 0.6, + SizeConfig.screenWidth! * 0.6, + ), + ); + }); }); testWidgets("Testing if app name shows up", (tester) async { - await tester.pumpWidget(createSplashScreenLight()); - await tester.pumpAndSettle(); - final findAppNameWidget = find.text('TALAWA'); - expect(findAppNameWidget, findsOneWidget); - expect( - (tester.firstWidget(findAppNameWidget) as Text).style!.color, - TalawaTheme.lightTheme.textTheme.headlineMedium!.color, - ); - expect( - (tester.firstWidget(findAppNameWidget) as Text).style!.fontFamily, - TalawaTheme.lightTheme.textTheme.headlineMedium!.fontFamily, - ); - expect( - (tester.firstWidget(findAppNameWidget) as Text).style!.fontSize, - TalawaTheme.lightTheme.textTheme.headlineMedium!.fontSize, - ); + await tester.runAsync(() async { + await tester.pumpWidget(createSplashScreenLight()); + await tester.pumpAndSettle(); + final findAppNameWidget = find.text('TALAWA'); + expect(findAppNameWidget, findsOneWidget); + expect( + (tester.firstWidget(findAppNameWidget) as Text).style!.color, + TalawaTheme.lightTheme.textTheme.headlineMedium!.color, + ); + expect( + (tester.firstWidget(findAppNameWidget) as Text).style!.fontFamily, + TalawaTheme.lightTheme.textTheme.headlineMedium!.fontFamily, + ); + expect( + (tester.firstWidget(findAppNameWidget) as Text).style!.fontSize, + TalawaTheme.lightTheme.textTheme.headlineMedium!.fontSize, + ); + }); }); testWidgets("Testing if provider text shows up", (tester) async { - await tester.pumpWidget(createSplashScreenLight()); - await tester.pumpAndSettle(); - final findProviderTextWidget = find.text('from'); - expect(findProviderTextWidget, findsOneWidget); - expect( - (tester.firstWidget(findProviderTextWidget) as Text).style!.color, - TalawaTheme.lightTheme.textTheme.bodySmall!.color, - ); - expect( - (tester.firstWidget(findProviderTextWidget) as Text).style!.fontFamily, - TalawaTheme.lightTheme.textTheme.bodySmall!.fontFamily, - ); - expect( - (tester.firstWidget(findProviderTextWidget) as Text).style!.fontSize, - TalawaTheme.lightTheme.textTheme.bodySmall!.fontSize, - ); + await tester.runAsync(() async { + await tester.pumpWidget(createSplashScreenLight()); + await tester.pumpAndSettle(); + final findProviderTextWidget = find.text('from'); + expect(findProviderTextWidget, findsOneWidget); + expect( + (tester.firstWidget(findProviderTextWidget) as Text).style!.color, + TalawaTheme.lightTheme.textTheme.bodySmall!.color, + ); + expect( + (tester.firstWidget(findProviderTextWidget) as Text) + .style! + .fontFamily, + TalawaTheme.lightTheme.textTheme.bodySmall!.fontFamily, + ); + expect( + (tester.firstWidget(findProviderTextWidget) as Text).style!.fontSize, + TalawaTheme.lightTheme.textTheme.bodySmall!.fontSize, + ); + }); }); testWidgets("Testing if provider name shows up", (tester) async { - await tester.pumpWidget(createSplashScreenLight()); - await tester.pumpAndSettle(); - final findProviderNameWidget = find.text('PALISADOES'); - expect(findProviderNameWidget, findsOneWidget); - expect( - (tester.firstWidget(findProviderNameWidget) as Text).style!.color, - TalawaTheme.lightTheme.textTheme.titleSmall!.color, - ); - expect( - (tester.firstWidget(findProviderNameWidget) as Text).style!.fontFamily, - TalawaTheme.lightTheme.textTheme.titleSmall!.fontFamily, - ); + await tester.runAsync(() async { + await tester.pumpWidget(createSplashScreenLight()); + await tester.pumpAndSettle(); + final findProviderNameWidget = find.text('PALISADOES'); + expect(findProviderNameWidget, findsOneWidget); + expect( + (tester.firstWidget(findProviderNameWidget) as Text).style!.color, + TalawaTheme.lightTheme.textTheme.titleSmall!.color, + ); + expect( + (tester.firstWidget(findProviderNameWidget) as Text) + .style! + .fontFamily, + TalawaTheme.lightTheme.textTheme.titleSmall!.fontFamily, + ); + }); }); }); group('Splash Screen Widget Test in dark mode', () { testWidgets("Testing if Splash Screen shows up", (tester) async { - await tester.pumpWidget(createSplashScreenDark()); - await tester.pumpAndSettle(); - final screenScaffoldWidget = - find.byKey(const Key('SplashScreenScaffold')); - expect(screenScaffoldWidget, findsOneWidget); - expect( - (tester.firstWidget(find.byKey(const Key('Root'))) as MaterialApp) - .darkTheme! - .scaffoldBackgroundColor, - TalawaTheme.darkTheme.scaffoldBackgroundColor, - ); + await tester.runAsync(() async { + await tester.pumpWidget(createSplashScreenDark()); + await tester.pumpAndSettle(); + final screenScaffoldWidget = + find.byKey(const Key('SplashScreenScaffold')); + expect(screenScaffoldWidget, findsOneWidget); + expect( + (tester.firstWidget(find.byKey(const Key('Root'))) as MaterialApp) + .darkTheme! + .scaffoldBackgroundColor, + TalawaTheme.darkTheme.scaffoldBackgroundColor, + ); + }); }); testWidgets("Testing if app logo shows up", (tester) async { - await tester.pumpWidget(createSplashScreenDark()); - await tester.pumpAndSettle(); - final logoWidget = find.byKey(const Key('LogoPainter')); - expect(logoWidget, findsOneWidget); - expect( - (tester.firstWidget(logoWidget) as CustomPaint).size, - Size( - SizeConfig.screenWidth! * 0.6, - SizeConfig.screenWidth! * 0.6, - ), - ); + await tester.runAsync(() async { + await tester.pumpWidget(createSplashScreenDark()); + await tester.pumpAndSettle(); + final logoWidget = find.byKey(const Key('LogoPainter')); + expect(logoWidget, findsOneWidget); + expect( + (tester.firstWidget(logoWidget) as CustomPaint).size, + Size( + SizeConfig.screenWidth! * 0.6, + SizeConfig.screenWidth! * 0.6, + ), + ); + }); }); testWidgets("Testing if app name shows up", (tester) async { - await tester.pumpWidget(createSplashScreenDark()); - await tester.pumpAndSettle(); - final findAppNameWidget = find.text('TALAWA'); - expect(findAppNameWidget, findsOneWidget); - expect( - (tester.firstWidget(findAppNameWidget) as Text).style!.color, - TalawaTheme.darkTheme.textTheme.headlineMedium!.color, - ); - expect( - (tester.firstWidget(findAppNameWidget) as Text).style!.fontFamily, - TalawaTheme.darkTheme.textTheme.headlineMedium!.fontFamily, - ); - expect( - (tester.firstWidget(findAppNameWidget) as Text).style!.fontSize, - TalawaTheme.darkTheme.textTheme.headlineMedium!.fontSize, - ); + await tester.runAsync(() async { + await tester.pumpWidget(createSplashScreenDark()); + await tester.pumpAndSettle(); + final findAppNameWidget = find.text('TALAWA'); + expect(findAppNameWidget, findsOneWidget); + expect( + (tester.firstWidget(findAppNameWidget) as Text).style!.color, + TalawaTheme.darkTheme.textTheme.headlineMedium!.color, + ); + expect( + (tester.firstWidget(findAppNameWidget) as Text).style!.fontFamily, + TalawaTheme.darkTheme.textTheme.headlineMedium!.fontFamily, + ); + expect( + (tester.firstWidget(findAppNameWidget) as Text).style!.fontSize, + TalawaTheme.darkTheme.textTheme.headlineMedium!.fontSize, + ); + }); }); testWidgets("Testing if provider text shows up", (tester) async { - await tester.pumpWidget(createSplashScreenDark()); - await tester.pumpAndSettle(); - final findProviderTextWidget = find.text('from'); - expect(findProviderTextWidget, findsOneWidget); - expect( - (tester.firstWidget(findProviderTextWidget) as Text).style!.color, - TalawaTheme.darkTheme.textTheme.bodySmall!.color, - ); - expect( - (tester.firstWidget(findProviderTextWidget) as Text).style!.fontFamily, - TalawaTheme.darkTheme.textTheme.bodySmall!.fontFamily, - ); - expect( - (tester.firstWidget(findProviderTextWidget) as Text).style!.fontSize, - TalawaTheme.darkTheme.textTheme.bodySmall!.fontSize, - ); + await tester.runAsync(() async { + await tester.pumpWidget(createSplashScreenDark()); + await tester.pumpAndSettle(); + final findProviderTextWidget = find.text('from'); + expect(findProviderTextWidget, findsOneWidget); + expect( + (tester.firstWidget(findProviderTextWidget) as Text).style!.color, + TalawaTheme.darkTheme.textTheme.bodySmall!.color, + ); + expect( + (tester.firstWidget(findProviderTextWidget) as Text) + .style! + .fontFamily, + TalawaTheme.darkTheme.textTheme.bodySmall!.fontFamily, + ); + expect( + (tester.firstWidget(findProviderTextWidget) as Text).style!.fontSize, + TalawaTheme.darkTheme.textTheme.bodySmall!.fontSize, + ); + }); }); testWidgets("Testing if provider name shows up", (tester) async { - await tester.pumpWidget(createSplashScreenDark()); - await tester.pumpAndSettle(); - final findProviderNameWidget = find.text('PALISADOES'); - expect(findProviderNameWidget, findsOneWidget); - expect( - (tester.firstWidget(findProviderNameWidget) as Text).style!.color, - TalawaTheme.darkTheme.textTheme.titleSmall!.color, - ); - expect( - (tester.firstWidget(findProviderNameWidget) as Text).style!.fontFamily, - TalawaTheme.darkTheme.textTheme.titleSmall!.fontFamily, - ); + await tester.runAsync(() async { + await tester.pumpWidget(createSplashScreenDark()); + await tester.pumpAndSettle(); + final findProviderNameWidget = find.text('PALISADOES'); + expect(findProviderNameWidget, findsOneWidget); + expect( + (tester.firstWidget(findProviderNameWidget) as Text).style!.color, + TalawaTheme.darkTheme.textTheme.titleSmall!.color, + ); + expect( + (tester.firstWidget(findProviderNameWidget) as Text) + .style! + .fontFamily, + TalawaTheme.darkTheme.textTheme.titleSmall!.fontFamily, + ); + }); }); }); -} - -// Added the following test cases - -Future testWidgets1(WidgetTester tester) async { - await tester.pumpWidget(createSplashScreenLight()); - await tester.pumpAndSettle(); - - // Mock the uriLinkStream to emit a test URI - final testUri = Uri.parse("https://example.com"); - uriLinkStream.any(testUri as bool Function(Uri? element)); - - // Wait for the URI to be handled - await tester.pumpAndSettle(); - - // Verify that the latest URI is updated correctly - expect(find.text("Latest URI: $testUri"), findsOneWidget); -} -Future testWidgets2(WidgetTester tester) async { - await tester.pumpWidget(createSplashScreenLight()); - await tester.pumpAndSettle(); - - // Mock the userConfig.userLoggedIn() to return true - when(userConfig.userLoggedIn()).thenAnswer((_) async => true); - - // Wait for the user log in to be handled - await tester.pumpAndSettle(); - - // Verify that the user log in is handled correctly - expect(find.text("User logged in"), findsOneWidget); -} - -Future testWidgets3(WidgetTester tester) async { - await tester.pumpWidget(createSplashScreenLight()); - await tester.pumpAndSettle(); - - // Mock the userConfig.userLoggedIn() to return true - when(userConfig.userLoggedIn()).thenAnswer((_) async => true); - - // Mock the uriLinkStream to emit a test URI - final testUri = Uri.parse("https://example.com"); - uriLinkStream.any(testUri as bool Function(Uri? element)); - - // Wait for the URI to be handled - await tester.pumpAndSettle(); - - // Verify that the user log in is not handled - expect(find.text("User logged in"), findsNothing); -} - -Future testWidgets4(WidgetTester tester) async { - await tester.pumpWidget(createSplashScreenLight()); - await tester.pumpAndSettle(); - - // Mock the userConfig.userLoggedIn() to return true - when(userConfig.userLoggedIn()).thenAnswer((_) async => true); - - // Wait for the user log in to be handled - await tester.pumpAndSettle(); - - // Verify that the user log in is handled correctly - expect(find.text("User logged in"), findsOneWidget); -} - -Future testWidgets5(WidgetTester tester) async { - await tester.pumpWidget(createSplashScreenLight()); - await tester.pumpAndSettle(); - - // Mock the userConfig.userLoggedIn() to return true - when(userConfig.userLoggedIn()).thenAnswer((_) async => true); - - // Mock the initial URI to be a test URI - final testUri = Uri.parse("https://example.com"); - when(getInitialUri()).thenAnswer((_) async => testUri); - - // Wait for the initial URI to be handled - await tester.pumpAndSettle(); - - // Verify that the user log in is not handled - expect(find.text("User logged in"), findsNothing); -} - -Future testWidgets6(WidgetTester tester) async { - await tester.pumpWidget(createSplashScreenLight()); - await tester.pumpAndSettle(); - - // Mock the userConfig.userLoggedIn() to return true - when(userConfig.userLoggedIn()).thenAnswer((_) async => true); - - // Wait for the user log in to be handled - await tester.pumpAndSettle(); - - // Verify that the user log in is handled correctly - expect(find.text("User logged in"), findsOneWidget); + group("URI Link Handling Tests", () { + testWidgets("should handle initial URI successfully", (tester) async { + await tester.runAsync(() async { + // Arrange + final uri = Uri.parse('talawa://example.com'); + when(mockAppLinks.getInitialLink()).thenAnswer((_) async => uri); + when(mockAppLinks.uriLinkStream).thenAnswer((_) => Stream.value(uri)); + + // Act: Pump the widget + await tester.pumpWidget(createSplashScreenLight()); + await tester.pumpAndSettle(); + + // Assert + verify(mockAppLinks.getInitialLink()).called(1); + expect(find.byKey(const Key('SplashScreenScaffold')), findsOneWidget); + }); + }); + testWidgets('should handle URI stream updates', (tester) async { + await tester.runAsync(() async { + // Arrange + final uri = Uri.parse('talawa://example.com'); + when(mockAppLinks.uriLinkStream).thenAnswer((_) => Stream.value(uri)); + when(mockUserConfig.loggedIn).thenReturn(true); + + // Act + await tester.pumpWidget(createSplashScreenLight()); + await tester.pumpAndSettle(); + + // Assert + verify(mockAppLinks.uriLinkStream).called(1); + }); + }); + testWidgets("should handle PlatformException when getting initial URI", + (tester) async { + await tester.runAsync(() async { + // Arrange + when(mockAppLinks.getInitialLink()) + .thenThrow(PlatformException(code: 'TEST_ERROR')); + when(mockAppLinks.uriLinkStream) + .thenAnswer((_) => const Stream.empty()); + + // Act + await tester.pumpWidget(createSplashScreenLight()); + await tester.pumpAndSettle(); + + // Assert + verify(mockAppLinks.getInitialLink()).called(1); + }); + }); + testWidgets("should handle FormatException when getting initial URI", + (tester) async { + await tester.runAsync(() async { + // Arrange + when(mockAppLinks.getInitialLink()) + .thenThrow(const FormatException('Invalid URI format')); + when(mockAppLinks.uriLinkStream) + .thenAnswer((_) => const Stream.empty()); + + // Act + await tester.pumpWidget(createSplashScreenLight()); + await tester.pumpAndSettle(); + + // Assert + verify(mockAppLinks.getInitialLink()).called(1); + }); + }); + testWidgets('should handle URI stream errors', (tester) async { + await tester.runAsync(() async { + // Arrange + when(mockAppLinks.uriLinkStream) + .thenAnswer((_) => Stream.error('Test error')); + when(mockUserConfig.loggedIn).thenReturn(true); + + // Act + await tester.pumpWidget(createSplashScreenLight()); + await tester.pumpAndSettle(); + + // Assert + verify(mockAppLinks.uriLinkStream).called(1); + }); + }); + testWidgets('should cleanup stream subscription on dispose', + (tester) async { + await tester.runAsync(() async { + // Arrange + when(mockUserConfig.loggedIn).thenReturn(true); + when(mockAppLinks.uriLinkStream) + .thenAnswer((_) => Stream.value(Uri.parse('talawa://example.com'))); + + // Act + await tester.pumpWidget(createSplashScreenLight()); + await tester.pumpWidget(Container()); // Force dispose + + // No explicit assert needed - test will fail if subscription isn't properly canceled + }); + }); + }); } diff --git a/test/widget_tests/pre_auth_screens/splash_screen_test.mocks.dart b/test/widget_tests/pre_auth_screens/splash_screen_test.mocks.dart new file mode 100644 index 000000000..b02fd2a1b --- /dev/null +++ b/test/widget_tests/pre_auth_screens/splash_screen_test.mocks.dart @@ -0,0 +1,327 @@ +// Mocks generated by Mockito 5.4.4 from annotations +// in talawa/test/widget_tests/pre_auth_screens/splash_screen_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i2; + +import 'package:app_links/src/app_links.dart' as _i5; +import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i7; +import 'package:talawa/models/organization/org_info.dart' as _i3; +import 'package:talawa/models/user/user_info.dart' as _i4; +import 'package:talawa/services/user_config.dart' as _i6; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class + +class _FakeStreamController_0 extends _i1.SmartFake + implements _i2.StreamController { + _FakeStreamController_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeOrgInfo_1 extends _i1.SmartFake implements _i3.OrgInfo { + _FakeOrgInfo_1( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeUser_2 extends _i1.SmartFake implements _i4.User { + _FakeUser_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +/// A class which mocks [AppLinks]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockAppLinks extends _i1.Mock implements _i5.AppLinks { + @override + _i2.Stream get stringLinkStream => (super.noSuchMethod( + Invocation.getter(#stringLinkStream), + returnValue: _i2.Stream.empty(), + returnValueForMissingStub: _i2.Stream.empty(), + ) as _i2.Stream); + + @override + _i2.Stream get uriLinkStream => (super.noSuchMethod( + Invocation.getter(#uriLinkStream), + returnValue: _i2.Stream.empty(), + returnValueForMissingStub: _i2.Stream.empty(), + ) as _i2.Stream); + + @override + _i2.Future getInitialLink() => (super.noSuchMethod( + Invocation.method( + #getInitialLink, + [], + ), + returnValue: _i2.Future.value(), + returnValueForMissingStub: _i2.Future.value(), + ) as _i2.Future); + + @override + _i2.Future getInitialLinkString() => (super.noSuchMethod( + Invocation.method( + #getInitialLinkString, + [], + ), + returnValue: _i2.Future.value(), + returnValueForMissingStub: _i2.Future.value(), + ) as _i2.Future); + + @override + _i2.Future getLatestLink() => (super.noSuchMethod( + Invocation.method( + #getLatestLink, + [], + ), + returnValue: _i2.Future.value(), + returnValueForMissingStub: _i2.Future.value(), + ) as _i2.Future); + + @override + _i2.Future getLatestLinkString() => (super.noSuchMethod( + Invocation.method( + #getLatestLinkString, + [], + ), + returnValue: _i2.Future.value(), + returnValueForMissingStub: _i2.Future.value(), + ) as _i2.Future); +} + +/// A class which mocks [UserConfig]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockUserConfig extends _i1.Mock implements _i6.UserConfig { + @override + _i2.Stream<_i3.OrgInfo> get currentOrgInfoStream => (super.noSuchMethod( + Invocation.getter(#currentOrgInfoStream), + returnValue: _i2.Stream<_i3.OrgInfo>.empty(), + returnValueForMissingStub: _i2.Stream<_i3.OrgInfo>.empty(), + ) as _i2.Stream<_i3.OrgInfo>); + + @override + _i2.StreamController<_i3.OrgInfo> get currentOrgInfoController => + (super.noSuchMethod( + Invocation.getter(#currentOrgInfoController), + returnValue: _FakeStreamController_0<_i3.OrgInfo>( + this, + Invocation.getter(#currentOrgInfoController), + ), + returnValueForMissingStub: _FakeStreamController_0<_i3.OrgInfo>( + this, + Invocation.getter(#currentOrgInfoController), + ), + ) as _i2.StreamController<_i3.OrgInfo>); + + @override + _i3.OrgInfo get currentOrg => (super.noSuchMethod( + Invocation.getter(#currentOrg), + returnValue: _FakeOrgInfo_1( + this, + Invocation.getter(#currentOrg), + ), + returnValueForMissingStub: _FakeOrgInfo_1( + this, + Invocation.getter(#currentOrg), + ), + ) as _i3.OrgInfo); + + @override + String get currentOrgName => (super.noSuchMethod( + Invocation.getter(#currentOrgName), + returnValue: _i7.dummyValue( + this, + Invocation.getter(#currentOrgName), + ), + returnValueForMissingStub: _i7.dummyValue( + this, + Invocation.getter(#currentOrgName), + ), + ) as String); + + @override + bool get loggedIn => (super.noSuchMethod( + Invocation.getter(#loggedIn), + returnValue: false, + returnValueForMissingStub: false, + ) as bool); + + @override + set currentOrg(_i3.OrgInfo? org) => super.noSuchMethod( + Invocation.setter( + #currentOrg, + org, + ), + returnValueForMissingStub: null, + ); + + @override + _i4.User get currentUser => (super.noSuchMethod( + Invocation.getter(#currentUser), + returnValue: _FakeUser_2( + this, + Invocation.getter(#currentUser), + ), + returnValueForMissingStub: _FakeUser_2( + this, + Invocation.getter(#currentUser), + ), + ) as _i4.User); + + @override + set currentUser(_i4.User? user) => super.noSuchMethod( + Invocation.setter( + #currentUser, + user, + ), + returnValueForMissingStub: null, + ); + + @override + void initialiseStream() => super.noSuchMethod( + Invocation.method( + #initialiseStream, + [], + ), + returnValueForMissingStub: null, + ); + + @override + _i2.Future userLoggedIn() => (super.noSuchMethod( + Invocation.method( + #userLoggedIn, + [], + ), + returnValue: _i2.Future.value(false), + returnValueForMissingStub: _i2.Future.value(false), + ) as _i2.Future); + + @override + _i2.Future userLogOut() => (super.noSuchMethod( + Invocation.method( + #userLogOut, + [], + ), + returnValue: _i2.Future.value(), + returnValueForMissingStub: _i2.Future.value(), + ) as _i2.Future); + + @override + _i2.Future updateUserJoinedOrg(List<_i3.OrgInfo>? orgDetails) => + (super.noSuchMethod( + Invocation.method( + #updateUserJoinedOrg, + [orgDetails], + ), + returnValue: _i2.Future.value(), + returnValueForMissingStub: _i2.Future.value(), + ) as _i2.Future); + + @override + _i2.Future updateUserCreatedOrg(List<_i3.OrgInfo>? orgDetails) => + (super.noSuchMethod( + Invocation.method( + #updateUserCreatedOrg, + [orgDetails], + ), + returnValue: _i2.Future.value(), + returnValueForMissingStub: _i2.Future.value(), + ) as _i2.Future); + + @override + _i2.Future updateUserMemberRequestOrg(List<_i3.OrgInfo>? orgDetails) => + (super.noSuchMethod( + Invocation.method( + #updateUserMemberRequestOrg, + [orgDetails], + ), + returnValue: _i2.Future.value(), + returnValueForMissingStub: _i2.Future.value(), + ) as _i2.Future); + + @override + _i2.Future updateUserAdminOrg(List<_i3.OrgInfo>? orgDetails) => + (super.noSuchMethod( + Invocation.method( + #updateUserAdminOrg, + [orgDetails], + ), + returnValue: _i2.Future.value(), + returnValueForMissingStub: _i2.Future.value(), + ) as _i2.Future); + + @override + _i2.Future updateAccessToken({ + required String? accessToken, + required String? refreshToken, + }) => + (super.noSuchMethod( + Invocation.method( + #updateAccessToken, + [], + { + #accessToken: accessToken, + #refreshToken: refreshToken, + }, + ), + returnValue: _i2.Future.value(), + returnValueForMissingStub: _i2.Future.value(), + ) as _i2.Future); + + @override + _i2.Future updateUser(_i4.User? updatedUserDetails) => + (super.noSuchMethod( + Invocation.method( + #updateUser, + [updatedUserDetails], + ), + returnValue: _i2.Future.value(false), + returnValueForMissingStub: _i2.Future.value(false), + ) as _i2.Future); + + @override + void saveUserInHive() => super.noSuchMethod( + Invocation.method( + #saveUserInHive, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void saveCurrentOrgInHive(_i3.OrgInfo? saveOrgAsCurrent) => + super.noSuchMethod( + Invocation.method( + #saveCurrentOrgInHive, + [saveOrgAsCurrent], + ), + returnValueForMissingStub: null, + ); +}